summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:29:52 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:29:52 +0000
commitca67b09c015d4af3ae3cce12aa72e60941dbb8b5 (patch)
treeb7316d7b06c373e08dabb79a2c866c568e08f49e
parentAdding upstream version 2.06. (diff)
downloadgrub2-debian.tar.xz
grub2-debian.zip
Adding debian version 2.06-13+deb12u1.debian/2.06-13+deb12u1debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--debian/NEWS21
-rw-r--r--debian/README.source41
-rw-r--r--debian/apport/source_grub2.py105
-rw-r--r--debian/bug-presubj23
-rwxr-xr-xdebian/bug-script61
-rwxr-xr-xdebian/build-efi-images278
-rw-r--r--debian/changelog5736
-rw-r--r--debian/clean17
-rw-r--r--debian/config.in92
-rw-r--r--debian/control779
-rw-r--r--debian/copyright375
-rw-r--r--debian/default/grub39
-rw-r--r--debian/default/grub.md5sum3
-rw-r--r--debian/dirs.in3
-rw-r--r--debian/grub-common.bash-completion.in1
-rw-r--r--debian/grub-common.dirs2
-rw-r--r--debian/grub-common.examples1
-rw-r--r--debian/grub-common.init39
-rw-r--r--debian/grub-common.install.in51
-rw-r--r--debian/grub-common.install.kfreebsd.in2
-rw-r--r--debian/grub-common.install.linux.in2
-rw-r--r--debian/grub-common.install.sparc.in2
-rw-r--r--debian/grub-common.install.sparc64.in2
-rw-r--r--debian/grub-common.links10
-rw-r--r--debian/grub-common.maintscript.hurd.in3
-rw-r--r--debian/grub-common.maintscript.in1
-rw-r--r--debian/grub-common.maintscript.kfreebsd.in3
-rw-r--r--debian/grub-common.maintscript.linux.in3
-rw-r--r--debian/grub-common.pm-sleep11
-rw-r--r--debian/grub-coreboot-bin.install.amd64.in1
-rw-r--r--debian/grub-coreboot-bin.install.kopensolaris-i386.in1
-rw-r--r--debian/grub-coreboot-bin.install.linux-i386.in1
-rw-r--r--debian/grub-efi-amd64-signed-template.lintian-overrides1
-rw-r--r--debian/grub-efi-arm64-signed-template.lintian-overrides1
-rw-r--r--debian/grub-efi-ia32-signed-template.lintian-overrides1
-rw-r--r--debian/grub-emu-dbg.install.in4
-rw-r--r--debian/grub-emu.install.in8
-rw-r--r--debian/grub-emu.install.kopensolaris-i386.in1
-rw-r--r--debian/grub-emu.install.linux-i386.in1
-rw-r--r--debian/grub-emu.maintscript.in1
-rw-r--r--debian/grub-extras/915resolution/915resolution.c1081
-rw-r--r--debian/grub-extras/915resolution/COPYING674
-rw-r--r--debian/grub-extras/915resolution/Makefile.core.def7
-rw-r--r--debian/grub-extras/915resolution/README11
-rw-r--r--debian/grub-extras/disabled/gpxe/Makefile.common2
-rw-r--r--debian/grub-extras/disabled/gpxe/Makefile.core.def434
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/assert.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/bits/errfile.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/bits/uaccess.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/byteswap.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/config/ioapi.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/console.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/ctype.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/errno.h508
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/device.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/efi/efi_uaccess.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/features.h68
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/io.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/list.h118
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/nap.h44
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/pci.h296
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/timer.h66
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/vsprintf.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/gpxe/wrap.h261
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/libgen.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/limits.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/stddef.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/stdint.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/stdio.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/stdlib.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/string.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/strings.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/include_wrap/unistd.h1
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/base64.c68
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/basename.c64
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/bitmap.c101
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/cwuri.c46
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/interface.c63
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/iobuf.c96
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/job.c97
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/linebuf.c111
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/misc.c80
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/nvo.c263
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/open.c197
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/process.c106
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/random.c41
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/refcnt.c78
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/resolv.c415
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/settings.c1447
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/uri.c463
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/uuid.c51
-rw-r--r--debian/grub-extras/disabled/gpxe/src/core/xfer.c417
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/bitbash/bitbash.c57
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/bitbash/i2c_bit.c393
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/bitbash/spi_bit.c225
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/block/scsi.c366
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.c432
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.h394
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c515.c763
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c529.c62
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.c553
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.h437
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c5x9.c416
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.c994
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.h302
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.c693
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.h631
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.c1694
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.h1275
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_attach.c340
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_caps.c154
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_desc.c544
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_dma.c631
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_eeprom.c1749
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_gpio.c122
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_initvals.c1560
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_pcu.c534
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_phy.c2586
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_qcu.c394
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_reset.c1176
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/base.h140
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/desc.h332
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/eeprom.h441
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/reg.h2589
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfbuffer.h1181
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfgain.h516
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/atl1e.c1757
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/b44.c951
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/b44.h470
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.c2697
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.h4598
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/davicom.c727
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/depca.c805
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/dmfe.c1226
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/eepro.c637
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/eepro100.c853
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.c539
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.h190
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.c4236
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.h553
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric_nic.h204
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/forcedeth.c1442
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ipoib.c718
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/legacy.c157
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/mtd80x.c1022
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.c609
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.h232
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ne2k_isa.c375
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ns83820.c1013
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.c1037
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.h240
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/pcnet32.c1021
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/pnic.c281
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/pnic_api.h61
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/prism2.c857
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_pci.c58
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_plx.c122
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.c2285
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.h487
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/rtl8139.c606
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.c1304
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.h375
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.c955
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.h428
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/sundance.c897
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.c1723
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.h491
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/tulip.c2098
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/net/w89c840.c964
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/nvs/nvs.c149
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/nvs/spi.c140
-rw-r--r--debian/grub-extras/disabled/gpxe/src/drivers/nvs/threewire.c131
-rw-r--r--debian/grub-extras/disabled/gpxe/src/hci/strerror.c123
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/etherboot.h44
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/acpi.h43
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/aes.h10
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ansiesc.h120
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/aoe.h150
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/api.h84
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/arp.h46
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/asn1.h34
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ata.h209
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/base64.h26
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/bitbash.h52
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/bitmap.h85
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/bitops.h230
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/blockdev.h53
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/cbc.h100
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/chap.h53
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/command.h26
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/cpio.h53
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/crypto.h154
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcp.h618
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcpopts.h34
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcppkt.h64
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/dns.h92
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/downloader.h19
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/editbox.h61
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/editstring.h33
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/eisa.h130
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/elf.h17
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/errfile.h196
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/errortab.h23
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ethernet.h20
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/fakedhcp.h23
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/filter.h75
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ftp.h15
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbserial.h21
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbstub.h77
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbudp.h24
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/hidemem.h17
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/hmac.h32
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/http.h23
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/i2c.h171
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cm.h72
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cmrc.h20
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mad.h561
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mcast.h48
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mi.h135
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_packet.h147
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_pathrec.h76
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_sma.h20
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_smc.h20
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_srp.h79
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp.h25
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp6.h59
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ieee80211.h1182
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/if_arp.h102
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/if_ether.h35
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/image.h194
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/in.h105
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/infiniband.h652
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/init.h81
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/interface.h58
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/iobuf.h229
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ip.h97
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ip6.h80
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ipoib.h60
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/isa.h97
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/isa_ids.h51
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/isapnp.h278
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/iscsi.h678
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/job.h169
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/keys.h81
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/linebuf.h30
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/linux_compat.h27
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/login_ui.h14
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/malloc.h59
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/mca.h108
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/md5.h24
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/memmap.h36
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/monojob.h17
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/net80211.h1016
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/netdevice.h525
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/null_nap.h23
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/nvo.h55
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/nvs.h68
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/open.h105
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/pci_io.h124
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/pcibackup.h33
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/posix_io.h87
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/process.h80
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/profile.h80
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/ramdisk.h24
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/rarp.h16
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/rc80211.h19
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/refcnt.h46
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/resolv.h170
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/retry.h81
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/rotate.h29
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/rsa.h12
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/sanboot.h18
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/scsi.h281
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/segment.h17
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/serial.h16
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/settings.h334
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/settings_ui.h16
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/shell.h14
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/shell_banner.h14
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/smbios.h161
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/socket.h101
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/spi.h258
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/spi_bit.h63
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/srp.h868
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/tables.h434
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/tcp.h318
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/tcpip.h128
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/tftp.h85
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/threewire.h105
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/tls.h187
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/uaccess.h344
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/udp.h48
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/umalloc.h68
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/uri.h144
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/uuid.h33
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/x509.h41
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/gpxe/xfer.h277
-rw-r--r--debian/grub-extras/disabled/gpxe/src/include/nic.h273
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/80211/net80211.c2645
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/80211/rc80211.c371
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/aoe.c471
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/arp.c289
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/dhcpopts.c436
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/dhcppkt.c283
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/ethernet.c181
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/fakedhcp.c217
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/icmp.c103
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband.c923
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cm.c411
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cmrc.c436
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mcast.c218
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mi.c406
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_packet.c244
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_pathrec.c296
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_sma.c362
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_smc.c179
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_srp.c406
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/iobpad.c68
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/ipv4.c635
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/netdev_settings.c102
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/netdevice.c633
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/nullnet.c60
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/rarp.c70
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/retry.c192
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/tcp.c1156
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/tcp/http.c603
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/tcp/https.c51
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/tcp/iscsi.c1934
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/tcpip.c135
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/tls.c1759
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/udp.c463
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/udp/dhcp.c1430
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/udp/dns.c602
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/udp/slam.c812
-rw-r--r--debian/grub-extras/disabled/gpxe/src/net/udp/tftp.c1205
-rw-r--r--debian/grub-extras/disabled/gpxe/wrap/nic.c138
-rw-r--r--debian/grub-extras/disabled/gpxe/wrap/pci.c56
-rw-r--r--debian/grub-extras/disabled/gpxe/wrap/wrap.c75
-rw-r--r--debian/grub-extras/disabled/zfs/COPYING674
-rw-r--r--debian/grub-extras/disabled/zfs/Makefile.common1
-rw-r--r--debian/grub-extras/disabled/zfs/Makefile.core.def16
-rw-r--r--debian/grub-extras/disabled/zfs/Makefile.util.def10
-rw-r--r--debian/grub-extras/disabled/zfs/README11
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/dmu.h120
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/dmu_objset.h44
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/dnode.h81
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dataset.h53
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dir.h49
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/sa_impl.h35
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/spa.h312
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/uberblock_impl.h61
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/vdev_impl.h70
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zap_impl.h112
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zap_leaf.h104
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zfs.h125
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_acl.h60
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_znode.h71
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zil.h57
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zio.h85
-rw-r--r--debian/grub-extras/disabled/zfs/include/grub/zfs/zio_checksum.h50
-rw-r--r--debian/grub-extras/disabled/zfs/zfs.c2546
-rw-r--r--debian/grub-extras/disabled/zfs/zfs_fletcher.c86
-rw-r--r--debian/grub-extras/disabled/zfs/zfs_lzjb.c95
-rw-r--r--debian/grub-extras/disabled/zfs/zfs_sha256.c145
-rw-r--r--debian/grub-extras/disabled/zfs/zfsinfo.c414
-rw-r--r--debian/grub-extras/lua/COPYING674
-rw-r--r--debian/grub-extras/lua/Makefile.core.def39
-rw-r--r--debian/grub-extras/lua/README11
-rw-r--r--debian/grub-extras/lua/grub_lib.c537
-rw-r--r--debian/grub-extras/lua/grub_lib.h24
-rw-r--r--debian/grub-extras/lua/grub_lua.h50
-rw-r--r--debian/grub-extras/lua/grub_main.c230
-rw-r--r--debian/grub-extras/lua/lapi.c1088
-rw-r--r--debian/grub-extras/lua/lapi.h16
-rw-r--r--debian/grub-extras/lua/lauxlib.c687
-rw-r--r--debian/grub-extras/lua/lauxlib.h175
-rw-r--r--debian/grub-extras/lua/lbaselib.c652
-rw-r--r--debian/grub-extras/lua/lcode.c852
-rw-r--r--debian/grub-extras/lua/lcode.h76
-rw-r--r--debian/grub-extras/lua/ldblib.c398
-rw-r--r--debian/grub-extras/lua/ldebug.c638
-rw-r--r--debian/grub-extras/lua/ldebug.h33
-rw-r--r--debian/grub-extras/lua/ldo.c519
-rw-r--r--debian/grub-extras/lua/ldo.h57
-rw-r--r--debian/grub-extras/lua/ldump.c164
-rw-r--r--debian/grub-extras/lua/lfunc.c174
-rw-r--r--debian/grub-extras/lua/lfunc.h34
-rw-r--r--debian/grub-extras/lua/lgc.c713
-rw-r--r--debian/grub-extras/lua/lgc.h110
-rw-r--r--debian/grub-extras/lua/linit.c38
-rw-r--r--debian/grub-extras/lua/liolib.c553
-rw-r--r--debian/grub-extras/lua/llex.c467
-rw-r--r--debian/grub-extras/lua/llex.h81
-rw-r--r--debian/grub-extras/lua/llimits.h128
-rw-r--r--debian/grub-extras/lua/lmathlib.c263
-rw-r--r--debian/grub-extras/lua/lmem.c86
-rw-r--r--debian/grub-extras/lua/lmem.h50
-rw-r--r--debian/grub-extras/lua/loadlib.c665
-rw-r--r--debian/grub-extras/lua/lobject.c221
-rw-r--r--debian/grub-extras/lua/lobject.h380
-rw-r--r--debian/grub-extras/lua/lopcodes.c102
-rw-r--r--debian/grub-extras/lua/lopcodes.h268
-rw-r--r--debian/grub-extras/lua/loslib.c243
-rw-r--r--debian/grub-extras/lua/lparser.c1340
-rw-r--r--debian/grub-extras/lua/lparser.h82
-rw-r--r--debian/grub-extras/lua/lstate.c213
-rw-r--r--debian/grub-extras/lua/lstate.h169
-rw-r--r--debian/grub-extras/lua/lstring.c112
-rw-r--r--debian/grub-extras/lua/lstring.h31
-rw-r--r--debian/grub-extras/lua/lstrlib.c874
-rw-r--r--debian/grub-extras/lua/ltable.c594
-rw-r--r--debian/grub-extras/lua/ltable.h40
-rw-r--r--debian/grub-extras/lua/ltablib.c288
-rw-r--r--debian/grub-extras/lua/ltm.c76
-rw-r--r--debian/grub-extras/lua/ltm.h54
-rw-r--r--debian/grub-extras/lua/lua.h388
-rw-r--r--debian/grub-extras/lua/luaconf.h846
-rw-r--r--debian/grub-extras/lua/lualib.h53
-rw-r--r--debian/grub-extras/lua/lundump.c229
-rw-r--r--debian/grub-extras/lua/lundump.h36
-rw-r--r--debian/grub-extras/lua/lvm.c764
-rw-r--r--debian/grub-extras/lua/lvm.h36
-rw-r--r--debian/grub-extras/lua/lzio.c83
-rw-r--r--debian/grub-extras/lua/lzio.h67
-rw-r--r--debian/grub-extras/lua/osdetect.lua204
-rw-r--r--debian/grub-extras/ntldr-img/COPYING674
-rw-r--r--debian/grub-extras/ntldr-img/Makefile.core.common38
-rw-r--r--debian/grub-extras/ntldr-img/Makefile.core.def32
-rw-r--r--debian/grub-extras/ntldr-img/README11
-rw-r--r--debian/grub-extras/ntldr-img/bin2h.c69
-rw-r--r--debian/grub-extras/ntldr-img/g2hdr.S98
-rw-r--r--debian/grub-extras/ntldr-img/grldrstart.S5793
-rw-r--r--debian/grub-extras/ntldr-img/grubinst.c1043
-rw-r--r--debian/grub-extras/ntldr-img/ntfsbs.S1508
-rw-r--r--debian/grub-extras/ntldr-img/utils.c392
-rw-r--r--debian/grub-extras/ntldr-img/utils.h88
-rw-r--r--debian/grub-extras/ntldr-img/version.h3
-rw-r--r--debian/grub-firmware-qemu.dirs1
-rw-r--r--debian/grub-firmware-qemu.install1
-rw-r--r--debian/grub-firmware-qemu_grub.cfg37
-rw-r--r--debian/grub-ieee1275-bin.install.amd64.in1
-rw-r--r--debian/grub-ieee1275-bin.install.kopensolaris-i386.in1
-rw-r--r--debian/grub-ieee1275-bin.install.linux-i386.in1
-rw-r--r--debian/grub-ieee1275-bin.install.powerpc.in3
-rw-r--r--debian/grub-ieee1275-bin.install.ppc64.in3
-rw-r--r--debian/grub-ieee1275-bin.install.ppc64el.in3
-rw-r--r--debian/grub-ieee1275.install.sparc.in2
-rw-r--r--debian/grub-ieee1275.install.sparc64.in2
-rw-r--r--debian/grub-ieee1275.links.sparc.in1
-rw-r--r--debian/grub-ieee1275.links.sparc64.in1
-rw-r--r--debian/grub-mount-udeb.install2
-rw-r--r--debian/grub-pc-bin.install.amd64.in1
-rw-r--r--debian/grub-pc-bin.install.in4
-rw-r--r--debian/grub-pc-bin.install.kopensolaris-i386.in1
-rw-r--r--debian/grub-pc-bin.install.linux-i386.in1
-rw-r--r--debian/grub-pc-dbg.install.in1
-rw-r--r--debian/grub-pc.dirs.in1
-rw-r--r--debian/grub-pc.install.in4
-rw-r--r--debian/grub-pc.links.in4
-rw-r--r--debian/grub-pc.prerm28
-rw-r--r--debian/grub-pc.templates.in157
-rw-r--r--debian/grub-rescue-pc.README.Debian22
-rw-r--r--debian/grub-rescue-pc.install2
-rw-r--r--debian/grub-rescue-pc.links3
-rw-r--r--debian/grub-theme-starfield.install1
-rw-r--r--debian/grub-xen-host.install3
-rw-r--r--debian/grub-xen-host.lintian-overrides3
-rw-r--r--debian/grub-xen-host_grub-bootstrap.cfg1
-rw-r--r--debian/grub-xen-host_grub-pvh.cfg9
-rw-r--r--debian/grub-xen-host_grub.cfg24
-rwxr-xr-xdebian/grub.d/05_debian_theme197
-rw-r--r--debian/grub2-common.install12
-rw-r--r--debian/grub2-common.links6
-rw-r--r--debian/grub2-common.manpages1
-rw-r--r--debian/init-select.cfg7
-rw-r--r--debian/install-bin.in5
-rw-r--r--debian/install-dbg.in4
-rw-r--r--debian/install.in0
-rwxr-xr-xdebian/kernel/zz-update-grub26
-rwxr-xr-xdebian/legacy/update-grub1068
-rwxr-xr-xdebian/legacy/update-grub.ubuntu.patch119
-rwxr-xr-xdebian/legacy/upgrade-from-grub-legacy44
-rw-r--r--debian/maintscript.in1
-rw-r--r--debian/patches/0063-loader-efi-chainloader-Simplify-the-loader-state.patch119
-rw-r--r--debian/patches/0064-commands-boot-Add-API-to-pass-context-to-loader.patch158
-rw-r--r--debian/patches/0065-loader-efi-chainloader-Use-grub_loader_set_ex.patch75
-rw-r--r--debian/patches/0066-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch99
-rw-r--r--debian/patches/0067-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch37
-rw-r--r--debian/patches/0068-video-readers-png-Abort-sooner-if-a-read-operation-f.patch197
-rw-r--r--debian/patches/0069-video-readers-png-Refuse-to-handle-multiple-image-he.patch27
-rw-r--r--debian/patches/0070-video-readers-png-Drop-greyscale-support-to-fix-heap.patch168
-rw-r--r--debian/patches/0071-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch38
-rw-r--r--debian/patches/0072-video-readers-png-Sanity-check-some-huffman-codes.patch39
-rw-r--r--debian/patches/0073-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch254
-rw-r--r--debian/patches/0074-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch28
-rw-r--r--debian/patches/0075-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch42
-rw-r--r--debian/patches/0076-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch73
-rw-r--r--debian/patches/0077-normal-charset-Fix-array-out-of-bounds-formatting-un.patch33
-rw-r--r--debian/patches/0078-net-netbuff-Block-overly-large-netbuff-allocs.patch45
-rw-r--r--debian/patches/0079-net-ip-Do-IP-fragment-maths-safely.patch43
-rw-r--r--debian/patches/0080-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch55
-rw-r--r--debian/patches/0081-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch69
-rw-r--r--debian/patches/0082-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch111
-rw-r--r--debian/patches/0083-net-tftp-Avoid-a-trivial-UAF.patch34
-rw-r--r--debian/patches/0084-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch40
-rw-r--r--debian/patches/0085-net-http-Fix-OOB-write-for-split-http-headers.patch45
-rw-r--r--debian/patches/0086-net-http-Error-out-on-headers-with-LF-without-CR.patch47
-rw-r--r--debian/patches/0087-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch71
-rw-r--r--debian/patches/0088-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch131
-rw-r--r--debian/patches/0089-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch37
-rw-r--r--debian/patches/0090-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch75
-rw-r--r--debian/patches/0091-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch133
-rw-r--r--debian/patches/0092-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch75
-rw-r--r--debian/patches/987008-lvrename-boot-fail.patch35
-rw-r--r--debian/patches/arm64-handover-to-kernel-if-sb-enabled.patch152
-rw-r--r--debian/patches/arm64_remove_magic_number_check.patch37
-rw-r--r--debian/patches/at_keyboard-module-init.patch44
-rw-r--r--debian/patches/bash-completion-drop-have-checks.patch143
-rw-r--r--debian/patches/blacklist-1440x900x32.patch34
-rw-r--r--debian/patches/bootp-new-net_bootp6-command.patch1119
-rw-r--r--debian/patches/bootp-process-dhcpack-http-boot.patch124
-rw-r--r--debian/patches/core-in-fs.patch45
-rw-r--r--debian/patches/cve_2022_2601/0001-video-readers-Add-artificial-limit-to-image-dimensio.patch109
-rw-r--r--debian/patches/cve_2022_2601/0002-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch33
-rw-r--r--debian/patches/cve_2022_2601/0003-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch110
-rw-r--r--debian/patches/cve_2022_2601/0004-font-Fix-several-integer-overflows-in-grub_font_cons.patch81
-rw-r--r--debian/patches/cve_2022_2601/0005-font-Remove-grub_font_dup_glyph.patch42
-rw-r--r--debian/patches/cve_2022_2601/0006-font-Fix-integer-overflow-in-ensure_comb_space.patch48
-rw-r--r--debian/patches/cve_2022_2601/0007-font-Fix-integer-overflow-in-BMP-index.patch65
-rw-r--r--debian/patches/cve_2022_2601/0008-font-Fix-integer-underflow-in-binary-search-of-char-.patch86
-rw-r--r--debian/patches/cve_2022_2601/0009-kern-efi-sb-Enforce-verification-of-font-files.patch54
-rw-r--r--debian/patches/cve_2022_2601/0010-fbutil-Fix-integer-overflow.patch85
-rw-r--r--debian/patches/cve_2022_2601/0011-font-Fix-an-integer-underflow-in-blit_comb.patch91
-rw-r--r--debian/patches/cve_2022_2601/0012-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch75
-rw-r--r--debian/patches/cve_2022_2601/0013-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch36
-rw-r--r--debian/patches/cve_2022_2601/0014-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch55
-rw-r--r--debian/patches/debug_verifiers.patch28
-rw-r--r--debian/patches/default-grub-d.patch209
-rw-r--r--debian/patches/dejavu-font-path.patch23
-rw-r--r--debian/patches/disable-floppies.patch37
-rw-r--r--debian/patches/disk-cryptodisk-when-cheatmounting-use-the-sector-info-of-the-cheat-device.patch72
-rw-r--r--debian/patches/dpkg-version-comparison.patch38
-rw-r--r--debian/patches/efi-variable-storage-minimise-writes.patch895
-rw-r--r--debian/patches/efinet-set-dns-from-uefi-proto.patch341
-rw-r--r--debian/patches/efinet-set-network-from-uefi-devpath.patch388
-rw-r--r--debian/patches/efinet-uefi-ipv6-pxe-support.patch126
-rw-r--r--debian/patches/fix-lockdown.patch45
-rw-r--r--debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch76
-rw-r--r--debian/patches/fs-tester-time-fail.patch27
-rw-r--r--debian/patches/gcc12_build_array_bounds.patch493
-rw-r--r--debian/patches/gcc12_build_array_bounds2.patch46
-rw-r--r--debian/patches/gcc12_build_dangling_pointer.patch67
-rw-r--r--debian/patches/gettext-quiet.patch30
-rw-r--r--debian/patches/gfxpayload-dynamic.patch290
-rw-r--r--debian/patches/gfxpayload-keep-default.patch39
-rw-r--r--debian/patches/grub-install-extra-removable.patch202
-rw-r--r--debian/patches/grub-install-pvxen-paths.patch71
-rw-r--r--debian/patches/grub-install-removable-shim.patch196
-rw-r--r--debian/patches/grub-legacy-0-based-partitions.patch39
-rw-r--r--debian/patches/grub.cfg-400.patch25
-rw-r--r--debian/patches/grub_mkconfig_restore_umask.patch36
-rw-r--r--debian/patches/grub_os-prober.patch22
-rw-r--r--debian/patches/ieee1275-clear-reset.patch32
-rw-r--r--debian/patches/ignore-grub_func_test-failures.patch29
-rw-r--r--debian/patches/ignore_checksum_seed_incompat_feature.patch54
-rw-r--r--debian/patches/ignore_the_large_dir_incompat_feature.patch53
-rw-r--r--debian/patches/insmod-xzio-and-lzopio-on-xen.patch33
-rw-r--r--debian/patches/install-efi-adjust-distributor.patch34
-rw-r--r--debian/patches/install-efi-fallback.patch91
-rw-r--r--debian/patches/install-locale-langpack.patch116
-rw-r--r--debian/patches/install-powerpc-machtypes.patch220
-rw-r--r--debian/patches/install-signed.patch309
-rw-r--r--debian/patches/install-stage2-confusion.patch46
-rw-r--r--debian/patches/kern-file-Fix-error-handling-in-grub_file_open.patch37
-rw-r--r--debian/patches/linuxefi.patch552
-rw-r--r--debian/patches/maybe-quiet.patch386
-rw-r--r--debian/patches/minilzo-2.10.patch2539
-rw-r--r--debian/patches/mkconfig-loopback.patch96
-rw-r--r--debian/patches/mkconfig-nonexistent-loopback.patch55
-rw-r--r--debian/patches/mkconfig-other-inits.patch90
-rw-r--r--debian/patches/mkconfig-recovery-title.patch130
-rw-r--r--debian/patches/mkconfig-signed-kernel.patch48
-rw-r--r--debian/patches/mkconfig-ubuntu-distributor.patch37
-rw-r--r--debian/patches/mkconfig-ubuntu-recovery.patch107
-rw-r--r--debian/patches/mkimage-fix-section-sizes.patch109
-rw-r--r--debian/patches/mkrescue-efi-modules.patch35
-rw-r--r--debian/patches/net-read-bracketed-ipv6-addr.patch255
-rw-r--r--debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch57
-rw-r--r--debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-index-at.patch46
-rw-r--r--debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entries-fr.patch69
-rw-r--r--debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-reside.patch54
-rw-r--r--debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_LIST-.patch89
-rw-r--r--debian/patches/ntfs-cve-fixes/fs-ntfs-Make-code-more-readable.patch155
-rw-r--r--debian/patches/olpc-prefix-hack.patch51
-rw-r--r--debian/patches/os-prober-Allow-initrd-to-contain-spaces.patch50
-rw-r--r--debian/patches/osdep-devmapper-getroot-have-devmapper-recognize-luks2.patch54
-rw-r--r--debian/patches/osdep-devmapper-getroot-set-up-cheated-luks2-cryptodisk-mount-from-dm-parameters.patch154
-rw-r--r--debian/patches/pc-verifiers-module.patch167
-rw-r--r--debian/patches/ppc64el-disable-vsx.patch52
-rw-r--r--debian/patches/probe-fusionio.patch76
-rw-r--r--debian/patches/quick-boot-lvm.patch77
-rw-r--r--debian/patches/quick-boot.patch358
-rw-r--r--debian/patches/restore-mkdevicemap.patch1326
-rw-r--r--debian/patches/series129
-rw-r--r--debian/patches/skip-grub_cmd_set_date.patch27
-rw-r--r--debian/patches/tests-ahci-update-qemu-device-name.patch34
-rw-r--r--debian/patches/tpm-unknown-error-non-fatal.patch31
-rw-r--r--debian/patches/uefi-secure-boot-cryptomount.patch48
-rw-r--r--debian/patches/vt-handoff.patch101
-rw-r--r--debian/patches/wubi-no-windows.patch57
-rw-r--r--debian/patches/xen-no-xsm-policy-in-non-xsm-options.patch35
-rw-r--r--debian/patches/xfs-fix-v4-superblock.patch122
-rw-r--r--debian/patches/zpool-full-device-name.patch33
-rwxr-xr-xdebian/platform-subst38
-rw-r--r--debian/po/POTFILES.in2
-rw-r--r--debian/po/ar.po494
-rw-r--r--debian/po/ast.po467
-rw-r--r--debian/po/be.po524
-rw-r--r--debian/po/bg.po483
-rw-r--r--debian/po/ca.po490
-rw-r--r--debian/po/cs.po477
-rw-r--r--debian/po/cy.po485
-rw-r--r--debian/po/da.po484
-rw-r--r--debian/po/de.po498
-rw-r--r--debian/po/dz.po460
-rw-r--r--debian/po/el.po513
-rw-r--r--debian/po/eo.po487
-rw-r--r--debian/po/es.po561
-rw-r--r--debian/po/eu.po474
-rw-r--r--debian/po/fa.po460
-rw-r--r--debian/po/fi.po479
-rw-r--r--debian/po/fr.po516
-rw-r--r--debian/po/gl.po478
-rw-r--r--debian/po/gu.po442
-rw-r--r--debian/po/he.po449
-rw-r--r--debian/po/hr.po491
-rw-r--r--debian/po/hu.po460
-rw-r--r--debian/po/id.po443
-rw-r--r--debian/po/is.po466
-rw-r--r--debian/po/it.po491
-rw-r--r--debian/po/ja.po464
-rw-r--r--debian/po/ka.po413
-rw-r--r--debian/po/kk.po481
-rw-r--r--debian/po/km.po440
-rw-r--r--debian/po/ko.po459
-rw-r--r--debian/po/lt.po474
-rw-r--r--debian/po/lv.po478
-rw-r--r--debian/po/mr.po450
-rw-r--r--debian/po/nb.po453
-rw-r--r--debian/po/nl.po466
-rw-r--r--debian/po/pl.po480
-rw-r--r--debian/po/pt.po493
-rw-r--r--debian/po/pt_BR.po495
-rw-r--r--debian/po/ro.po540
-rw-r--r--debian/po/ru.po490
-rw-r--r--debian/po/si.po440
-rw-r--r--debian/po/sk.po468
-rw-r--r--debian/po/sl.po481
-rw-r--r--debian/po/sq.po463
-rw-r--r--debian/po/sr.po457
-rw-r--r--debian/po/sr@latin.po457
-rw-r--r--debian/po/sv.po494
-rw-r--r--debian/po/ta.po456
-rw-r--r--debian/po/templates.pot364
-rw-r--r--debian/po/th.po447
-rw-r--r--debian/po/tr.po456
-rw-r--r--debian/po/ug.po476
-rw-r--r--debian/po/uk.po478
-rw-r--r--debian/po/vi.po481
-rw-r--r--debian/po/zh_CN.po438
-rw-r--r--debian/po/zh_TW.po445
-rw-r--r--debian/postinst.in796
-rw-r--r--debian/postrm.in66
-rw-r--r--debian/preinst.in15
-rw-r--r--debian/prep-bootdev.c39
-rwxr-xr-xdebian/rules589
-rw-r--r--debian/sbat.debian.csv.in3
-rwxr-xr-xdebian/signing-template.generate49
-rw-r--r--debian/signing-template.json.in14
-rw-r--r--debian/signing-template/README.source4
-rw-r--r--debian/signing-template/bug-control.in1
-rw-r--r--debian/signing-template/changelog.in11
-rw-r--r--debian/signing-template/compat1
-rw-r--r--debian/signing-template/control.in28
-rw-r--r--debian/signing-template/copyright51
-rwxr-xr-xdebian/signing-template/rules.in19
-rw-r--r--debian/signing-template/source/format1
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/include-binaries1
-rw-r--r--debian/templates.in65
-rw-r--r--debian/update-grub3
-rw-r--r--debian/update-grub.814
-rw-r--r--debian/upstream/metadata4
-rw-r--r--debian/upstream/signing-key.asc158
-rw-r--r--debian/watch9
695 files changed, 201967 insertions, 0 deletions
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644
index 0000000..ee5e795
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,21 @@
+grub2 (2.06-1) unstable; urgency=medium
+
+ * Boot menu entries for other operating systems are no longer generated by
+ default. To re-enable this, set GRUB_DISABLE_OS_PROBER=false in
+ /etc/default/grub.
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 28 Nov 2021 13:30:32 +0000
+
+grub2 (1.96+20090609-1) experimental; urgency=low
+
+ Before this version, grub-efi was 32bit on i386 and 64bit on amd64.
+ However, EFI can be 32bit even if you have a 64bit CPU, like in the
+ first MacBook models with Core 2 Duo released in late 2006. Thus,
+ grub-efi has been split into grub-efi-amd64 and grub-efi-ia32 which are
+ available on both amd64 and i386.
+
+ If you've experienced problems trying to load grub.efi, please try
+ again using the package that doesn't match your CPU's architecture.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 09 Jun 2009 19:21:15 +0200
+
diff --git a/debian/README.source b/debian/README.source
new file mode 100644
index 0000000..b288429
--- /dev/null
+++ b/debian/README.source
@@ -0,0 +1,41 @@
+Git Tree
+========
+
+The grub2 packaging is maintained via the grub-team project on Salsa:
+https://salsa.debian.org/grub-team
+
+The primary git tree is grub-team/grub. It can be obtained with:
+
+ git clone https://salsa.debian.org/grub-team/grub
+
+Git Subtrees
+------------
+
+grub.git/debian/grub-extras is maintained using git subtree merges. To
+update it to a given commit, first ensure that you have the relevant
+upstream remote, e.g.:
+
+ git remote add -f grub-extras https://git.sv.gnu.org/git/grub-extras.git
+
+And then:
+
+ git subtree merge -P debian/grub-extras <commit>
+
+Git Branches
+------------
+
+grub-team/grub uses git-dpm and contains the following branches:
+
+- upstream:
+
+ The master branch of the upstream grub.git tree, at the point
+ corresponding to the current Debian package version.
+
+- master:
+
+ The main packaging branch, based on upstream. debian/patches
+ maintained using git-dpm.
+
+- pristine-tar:
+
+ pritine-tar metadata based on upstream (not upstream).
diff --git a/debian/apport/source_grub2.py b/debian/apport/source_grub2.py
new file mode 100644
index 0000000..90182af
--- /dev/null
+++ b/debian/apport/source_grub2.py
@@ -0,0 +1,105 @@
+# vim: set fileencoding=UTF-8 :
+'''apport package hook for grub2
+
+Author: Jean-Baptiste Lallement <jeanbaptiste.lallement@gmail.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version. See http://www.gnu.org/copyleft/gpl.html for
+the full text of the license.
+'''
+
+from __future__ import print_function
+
+import os
+import re
+import subprocess
+
+from apport.hookutils import (
+ attach_default_grub,
+ attach_file,
+ attach_file_if_exists,
+ path_to_key,
+)
+
+
+def check_shell_syntax(path):
+ ''' Check the syntax of a shell script '''
+ try:
+ with open(os.devnull, 'w') as devnull:
+ subprocess.check_call(['/bin/sh', '-n', path], stderr=devnull)
+ except subprocess.CalledProcessError:
+ return False
+ return True
+
+
+def check_shell_syntax_harder(path):
+ ''' Check the syntax of a shell script '''
+ try:
+ # sh -n is tempting, but not good enough. Consider this case:
+ #
+ # GRUB_CMDLINE_LINUX_DEFAULT=â€quiet splash nomodesetâ€
+ #
+ # The quotes are Unicode quotes, not valid in the shell and probably
+ # caused by copying a line out of a web page. This is parsed as an
+ # instruction to run the 'splash' command with argument 'nomodesetâ€'
+ # and with the GRUB_CMDLINE_LINUX_DEFAULT environment variable set
+ # to 'â€quiet'. 'sh -n' allows this because this is a valid parse
+ # and it's possible that the command 'splash' might exist, but what
+ # we need to know is whether sourcing the file will fail.
+ #
+ # Unfortunately this test may involve executing code. However, this
+ # file is already sourced as root when running update-grub, so it
+ # seems unlikely that this could do any further harm.
+ with open(os.devnull, 'w') as devnull:
+ subprocess.check_call(
+ ['/bin/sh', '-ec', '. %s' % re.escape(path)], stderr=devnull)
+ except subprocess.CalledProcessError:
+ return False
+ return True
+
+
+def add_info(report):
+ if report['ProblemType'] == 'Package':
+ # To detect if root fs is a loop device
+ attach_file(report, '/proc/cmdline', 'ProcCmdLine')
+ attach_default_grub(report, 'EtcDefaultGrub')
+ attach_file_if_exists(report, '/boot/grub/device.map', 'DeviceMap')
+ try:
+ grub_d = '/etc/default/grub.d'
+ for name in sorted(os.listdir(grub_d)):
+ if name.endswith('.cfg'):
+ key = 'EtcDefaultGrubD.' + path_to_key(name)
+ attach_file_if_exists(
+ report, os.path.join(grub_d, name), key)
+ except OSError:
+ pass
+
+ invalid_grub_script = []
+ if not check_shell_syntax_harder('/etc/default/grub'):
+ invalid_grub_script.append('/etc/default/grub')
+
+ # Check scripts in /etc/grub.d since some users directly change
+ # configuration there
+ grubdir = '/etc/grub.d'
+ for f in os.listdir(grubdir):
+ fullpath = os.path.join(grubdir, f)
+ if f != 'README' and os.access(fullpath, os.X_OK) \
+ and not check_shell_syntax(fullpath):
+ invalid_grub_script.append(fullpath)
+ attach_file(report, fullpath)
+
+ # TODO: Add some UI to ask if the user modified the invalid script
+ # and if he still wants to report it
+ if invalid_grub_script:
+ report['InvalidGrubScript'] = ' '.join(invalid_grub_script)
+
+
+if __name__ == '__main__':
+ r = {}
+ r['ProblemType'] = 'Package'
+ add_info(r)
+ for k, v in r.items():
+ print('%s: "%s"' % (k, v))
+ print("========================================")
diff --git a/debian/bug-presubj b/debian/bug-presubj
new file mode 100644
index 0000000..e6e1859
--- /dev/null
+++ b/debian/bug-presubj
@@ -0,0 +1,23 @@
+
+MAKE SURE YOU ARE RUNNING THE LATEST VERSION
+
+The grub packages never update the installed version of GRUB
+automatically, except if you choose a device in the debconf prompt
+`GRUB install devices', which is currently only implemented for grub-pc.
+
+Because of this, you need to make sure you're running the LATEST VERSION of
+GRUB before you report a bug. Use grub-install to update it, and then check
+if the bug still applies. Debugging problems we already fixed makes us waste
+valuable time, so please try to avoid it.
+
+IMPORTANT NOTE WHEN SUBMITTING PATCHES
+
+Like many other FSF projects, GRUB upstream has specific requirements for
+accepting patches with regard to copyright assignment. If you're going to
+submit a patch, it is likely that it will only be accepted in upstream if you're
+willing to submit your paperwork as well.
+
+Because of this, we want to avoid diverging from upstream by adding patches to
+the Debian package unless we know the copyright issues can be sorted out. We
+encourage you to submit your work to upstream directly by sending a mail to the
+GRUB maintainers <grub-devel@gnu.org>.
diff --git a/debian/bug-script b/debian/bug-script
new file mode 100755
index 0000000..5c4ec7e
--- /dev/null
+++ b/debian/bug-script
@@ -0,0 +1,61 @@
+#!/bin/bash
+set -e
+
+if test -e /boot/grub/setup_left_core_image_in_filesystem ; then
+ echo >&3
+ echo "*********************** WARNING grub-setup left core.img in filesystem" >&3
+fi
+
+for i in /proc/mounts ; do
+ if test -e $i ; then
+ echo >&3
+ echo "*********************** BEGIN $i" >&3
+ grep ^/dev/ $i >&3
+ echo "*********************** END $i" >&3
+ fi
+done
+
+for i in /boot/grub/{device.map,grub.cfg} ; do
+ if ! test -e $i ; then
+ continue
+ fi
+ echo >&3
+ echo "*********************** BEGIN $i" >&3
+ if test -r $i ; then
+ sed $i -e "s/.*password.*/### PASSWORD LINE REMOVED ###/g" >&3
+ else
+ echo "$i is not readable by you. Please enter your root password."
+ echo "Any password line in it gets removed."
+ su root -c "sed $i -e 's/.*password.*/### PASSWORD LINE REMOVED ###/g'" >&3
+ fi
+ echo "*********************** END $i" >&3
+done
+
+echo >&3
+echo "*********************** BEGIN /proc/mdstat" >&3
+cat /proc/mdstat >&3 2>&1 || true
+echo "*********************** END /proc/mdstat" >&3
+
+cat <<EOF
+Information on any LVM volumes on this system is valuable to the GRUB
+developers, but gathering this information requires the root password.
+EOF
+yesno "Do you want to provide LVM volume information?" nop
+if [ "$REPLY" = yep ]; then
+ echo >&3
+ echo "*********************** BEGIN LVM" >&3
+ su root -c "vgdisplay; pvdisplay; lvdisplay" >&3 || true
+ echo "*********************** END LVM" >&3
+fi
+
+echo >&3
+echo "*********************** BEGIN /dev/disk/by-id" >&3
+ls -l /dev/disk/by-id >&3 2>&1 || true
+echo "*********************** END /dev/disk/by-id" >&3
+
+echo >&3
+echo "*********************** BEGIN /dev/disk/by-uuid" >&3
+ls -l /dev/disk/by-uuid >&3 2>&1 || true
+echo "*********************** END /dev/disk/by-uuid" >&3
+
+exit 0
diff --git a/debian/build-efi-images b/debian/build-efi-images
new file mode 100755
index 0000000..888f1ad
--- /dev/null
+++ b/debian/build-efi-images
@@ -0,0 +1,278 @@
+#! /bin/sh
+set -e
+
+# Copyright (C) 2010, 2011, 2012 Canonical Ltd.
+# Author: Colin Watson <cjwatson@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Make EFI boot images for signing.
+
+if [ $# -lt 7 ]; then
+ echo "usage: $0 GRUB-MKIMAGE GRUB-CORE OUTPUT-DIRECTORY DEB-ARCH PLATFORM EFI-NAME SBAT-CSV [EFI-VENDOR]"
+fi
+
+grub_mkimage="$1"
+grub_core="$2"
+outdir="$3"
+deb_arch="$4"
+platform="$5"
+efi_name="$6"
+sbat_csv="$7"
+efi_vendor="${8:-$(dpkg-vendor --query vendor | tr '[:upper:]' '[:lower:]')}"
+
+# mkfs.msdos may not be on the default PATH.
+export PATH="$PATH:/sbin:/usr/sbin"
+
+workdir=
+
+cleanup () {
+ [ -z "$workdir" ] || rm -rf "$workdir"
+}
+trap cleanup EXIT HUP INT QUIT TERM
+
+# Return the number of 1KiB blocks needed to store a file in the
+# memdisk, with an extra block for the directory entry
+rounded_size () {
+ BLOCK_SIZE=1024
+ size=$(stat -c %s $1)
+ rounded=$(( ( ($size + $BLOCK_SIZE - 1) / $BLOCK_SIZE) + 1))
+ echo "Adding $rounded blocks to memdisk for $1" >&2
+ echo $rounded
+}
+
+rm -rf "$outdir"
+mkdir -p "$outdir"
+
+workdir="$(mktemp -d build-efi-images.XXXXXX)"
+
+# GRUB's rescue parser doesn't understand 'if'.
+echo 'normal (memdisk)/grub.cfg' >"$workdir/grub-bootstrap.cfg"
+
+# Skeleton configuration file which finds the real boot disk.
+cat >"$workdir/grub.cfg" <<EOF
+if [ -z "\$prefix" -o ! -e "\$prefix" ]; then
+ if ! search --file --set=root /.disk/info; then
+ search --file --set=root /.disk/mini-info
+ fi
+ set prefix=(\$root)/boot/grub
+fi
+if [ -e \$prefix/$platform/grub.cfg ]; then
+ source \$prefix/$platform/grub.cfg
+elif [ -e \$prefix/grub.cfg ]; then
+ source \$prefix/grub.cfg
+else
+ source \$cmdpath/grub.cfg
+fi
+EOF
+
+cat >"$workdir/grub-netboot.cfg" <<EOF
+if [ -e \$prefix/$platform/grub.cfg ]; then
+ source \$prefix/$platform/grub.cfg
+else
+ source \$prefix/grub.cfg
+fi
+EOF
+
+# Calculate the size of the embedded filesystem needed
+FATFS_SIZE=64 # 64KiB for the embedded grub.cfg and the metadata
+
+# Only copy in unicode.pf2 for now, we don't want the binary images
+# too large
+FONTS=$grub_core/../unicode.pf2
+for FONT in $FONTS; do
+ FATFS_SIZE=$(($FATFS_SIZE + $(rounded_size $FONT)))
+done
+
+mkfs.msdos -C "$workdir/memdisk.fat" $FATFS_SIZE
+mcopy -i "$workdir/memdisk.fat" "$workdir/grub.cfg" ::grub.cfg
+mmd -i "$workdir/memdisk.fat" ::fonts
+for FONT in $FONTS; do
+ mcopy -i "$workdir/memdisk.fat" "$FONT" ::fonts/$(basename $FONT)
+done
+# Let's show what's here so we have it in build logs
+mdir -/ -i "$workdir/memdisk.fat"
+
+mkfs.msdos -C "$workdir/memdisk-netboot.fat" $FATFS_SIZE
+mcopy -i "$workdir/memdisk-netboot.fat" "$workdir/grub-netboot.cfg" ::grub.cfg
+mmd -i "$workdir/memdisk-netboot.fat" ::fonts
+for FONT in $FONTS; do
+ mcopy -i "$workdir/memdisk-netboot.fat" "$FONT" ::fonts/$(basename $FONT)
+done
+# Let's show what's here so we have it in build logs
+mdir -/ -i "$workdir/memdisk.fat"
+
+CD_MODULES="
+ all_video
+ boot
+ btrfs
+ cat
+ chain
+ configfile
+ echo
+ efifwsetup
+ efinet
+ ext2
+ fat
+ font
+ f2fs
+ gettext
+ gfxmenu
+ gfxterm
+ gfxterm_background
+ gzio
+ halt
+ help
+ hfsplus
+ iso9660
+ jfs
+ jpeg
+ keystatus
+ loadenv
+ loopback
+ linux
+ ls
+ lsefi
+ lsefimmap
+ lsefisystab
+ lssal
+ memdisk
+ minicmd
+ normal
+ ntfs
+ part_apple
+ part_msdos
+ part_gpt
+ password_pbkdf2
+ png
+ probe
+ reboot
+ regexp
+ search
+ search_fs_uuid
+ search_fs_file
+ search_label
+ serial
+ sleep
+ smbios
+ squash4
+ test
+ true
+ video
+ xfs
+ zfs
+ zfscrypt
+ zfsinfo
+ "
+
+# Platform-specific modules
+case $platform in
+ x86_64-efi|i386-efi)
+ CD_MODULES="$CD_MODULES
+ cpuid
+ linuxefi
+ play
+ tpm
+ "
+ ;;
+esac
+
+GRUB_MODULES="$CD_MODULES
+ cryptodisk
+ gcry_arcfour
+ gcry_blowfish
+ gcry_camellia
+ gcry_cast5
+ gcry_crc
+ gcry_des
+ gcry_dsa
+ gcry_idea
+ gcry_md4
+ gcry_md5
+ gcry_rfc2268
+ gcry_rijndael
+ gcry_rmd160
+ gcry_rsa
+ gcry_seed
+ gcry_serpent
+ gcry_sha1
+ gcry_sha256
+ gcry_sha512
+ gcry_tiger
+ gcry_twofish
+ gcry_whirlpool
+ luks
+ luks2
+ lvm
+ mdraid09
+ mdraid1x
+ raid5rec
+ raid6rec
+ "
+NET_MODULES="$CD_MODULES
+ tftp
+ "
+
+# CD boot image
+echo "Including modules $CD_MODULES in $outdir/gcd$efi_name.efi"
+"$grub_mkimage" \
+ -O "$platform" \
+ -o "$outdir/gcd$efi_name.efi" \
+ -c "$workdir/grub-bootstrap.cfg" \
+ -d "$grub_core" \
+ -m "$workdir/memdisk.fat" \
+ -p /boot/grub \
+ --sbat "$sbat_csv" \
+ $CD_MODULES
+
+# Normal disk boot image
+echo "Including modules $GRUB_MODULES in $outdir/grub$efi_name.efi"
+"$grub_mkimage" \
+ -O "$platform" \
+ -o "$outdir/grub$efi_name.efi" \
+ -c "$workdir/grub-bootstrap.cfg" \
+ -d "$grub_core" \
+ -m "$workdir/memdisk.fat" \
+ -p "/EFI/$efi_vendor" \
+ --sbat "$sbat_csv" \
+ $GRUB_MODULES
+
+# Normal network boot image
+echo "Including modules $NET_MODULES in $outdir/grubnet$efi_name.efi"
+"$grub_mkimage" \
+ -O "$platform" \
+ -o "$outdir/grubnet$efi_name.efi" \
+ -c "$workdir/grub-bootstrap.cfg" \
+ -d "$grub_core" \
+ -m "$workdir/memdisk-netboot.fat" \
+ -p /grub \
+ --sbat "$sbat_csv" \
+ $NET_MODULES
+
+# Special network boot image for d-i to use. Just the same as the
+# normal network boot image, but with a different value baked in for
+# the prefix setting
+echo "Including modules $NET_MODULES in $outdir/grubnet$efi_name-installer.efi"
+"$grub_mkimage" \
+ -O "$platform" \
+ -o "$outdir/grubnet$efi_name-installer.efi" \
+ -c "$workdir/grub-bootstrap.cfg" \
+ -d "$grub_core" \
+ -m "$workdir/memdisk-netboot.fat" \
+ -p "/${efi_vendor}-installer/$deb_arch/grub" \
+ --sbat "$sbat_csv" \
+ $NET_MODULES
+
+exit 0
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..6113fcd
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5736 @@
+grub2 (2.06-13+deb12u1) bookworm-security; urgency=medium
+
+ [ Mate Kukri ]
+ * SECURITY UPDATE: Crafted file system images can cause out-of-bounds write
+ and may leak sensitive information into the GRUB pager.
+ - d/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-
+ label.patch:
+ fs/ntfs: Fix an OOB read when parsing a volume label
+ - d/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-bs-for-
+ index-at.patch:
+ fs/ntfs: Fix an OOB read when parsing bitmaps for index attributes
+ - d/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-dory-
+ entries-fr.patch:
+ fs/ntfs: Fix an OOB read when parsing directory entries from resident and
+ non-resident index attributes
+ - d/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-reading-data-fhe-
+ reside.patch:
+ fs/ntfs: Fix an OOB read when reading data from the resident $DATA +
+ attribute
+ - CVE-2023-4693
+ * SECURITY UPDATE: Crafted file system images can cause heap-based buffer
+ overflow and may allow arbitrary code execution and secure boot bypass.
+ - d/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-write-when-parsing-the-
+ ATTRIBUTE_LIST-.patch:
+ fs/ntfs: Fix an OOB write when parsing the $ATTRIBUTE_LIST attribute for
+ the $MFT file
+ - d/patches/ntfs-cve-fixes/fs-ntfs-Make-code-more-readable.patch
+ fs/ntfs: Make code more readable
+ - CVE-2023-4692
+
+ [ Julian Andres Klode ]
+ * Bump SBAT to grub,4
+
+ -- Julian Andres Klode <jak@debian.org> Mon, 02 Oct 2023 16:11:34 +0200
+
+grub2 (2.06-13) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * When *also* installing to the removable media path, include the
+ relevant mokmanager binary. Closes: #1034409
+
+ [ General Chaos ]
+ * Allow initrd to contain spaces. Closes: #838177, #820838.
+
+ [ Translators ]
+ * Update lots of translations of debconf templates, thanks to the
+ following:
+ + Welsh (Dafydd Tomos)
+ + German (Helge Kreutzmann). Closes: #1034850
+ + Croatian (Tomislav Krznar)
+ + Greek (Emmanuel Galatoulas)
+ + Esperanto (Felipe Castro)
+ + French (Baptiste Jammet). Closes: #1035761
+ + Italian (Luca Monducci). Closes: #1034825
+ + Kazakh (Baurzhan Muftakhidinov)
+ + Korean (Changwoo Ryu). Closes: #1034868
+ + Latvian (Rudolfs Mazurs)
+ + Dutch (Frans Spiesschaert). Closes: #1035399
+ + Norwegian Bokmål (Petter Reinholdtsen, Sverre Vaabenoe)
+ + Brazilian Portuguese (Adriano Rafael Gomes). Closes: #1035905
+ + Romanian (Remus-Gabriel Chelu)
+ + Russian (Yuri Kozlov). Closes: #1035294
+ + Turkish (Atila KOÇ). Closes: #1035846
+ + Swedish (Luna Jernberg)
+
+ -- Steve McIntyre <93sam@debian.org> Sun, 23 Apr 2023 20:55:54 +0100
+
+grub2 (2.06-12) unstable; urgency=medium
+
+ * Fix up arm64 SB patch to fix build failure on 32-bit arm systems
+
+ -- Steve McIntyre <93sam@debian.org> Fri, 21 Apr 2023 13:30:26 +0100
+
+grub2 (2.06-11) unstable; urgency=medium
+
+ * And try again... :-/
+
+ -- Steve McIntyre <93sam@debian.org> Fri, 21 Apr 2023 01:50:26 +0100
+
+grub2 (2.06-10) unstable; urgency=medium
+
+ * Fix 32-bit build with the osdep/devmapper/getroot patches.
+
+ -- Steve McIntyre <93sam@debian.org> Fri, 21 Apr 2023 01:14:13 +0100
+
+grub2 (2.06-9) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * postinst: make config_item() more robust
+ * Add debconf logic for GRUB_DISABLE_OS_PROBER to make it easier to
+ control things here. Particularly useful for the installer.
+ Closes: #1031594, #1012865, #1025698.
+ * Add luks2 to the signed grub efi images. Closes: #1001248
+
+ [ Ben Hutchings ]
+ * Fix probing of LUKS2 devices (Closes: #1028301):
+ - disk/cryptodisk: When cheatmounting, use the sector info of the cheat
+ device
+ - osdep/devmapper/getroot: Have devmapper recognize LUKS2
+ - osdep/devmapper/getroot: Set up cheated LUKS2 cryptodisk mount from DM
+ parameters
+
+ [ Emanuele Rocca ]
+ * Add arm64-handover-to-kernel-if-sb-enabled.patch to fix Secure Boot on
+ arm64 (Closes: #1033657)
+
+ [ Mattia Rizzolo ]
+ * Don't warn about os-prober if it's not installed. Closes: #1020769
+
+ -- Steve McIntyre <93sam@debian.org> Thu, 20 Apr 2023 20:35:11 +0100
+
+grub2 (2.06-8.1) experimental; urgency=medium
+
+ * Non-maintainer upload.
+ * Fix an issue where a logical volume rename would lead grub to fail to
+ boot (Closes: #987008)
+
+ -- Antoine Beaupré <anarcat@debian.org> Sat, 25 Feb 2023 15:16:55 -0500
+
+grub2 (2.06-8) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Fix an issue in an f2fs security fix which caused mount
+ failures. Closes: #1021846. Thanks to программиÑÑ‚ некто for helping
+ to debug the problem!
+ * Switch build-deps from gcc-10 to gcc-12. Closes: #1022184
+ * Include upstream patch to enable EFI zboot support on arm64.
+ Closes: #1026092
+ * grub-mkconfig: Restore umask for the grub.cfg. CVE-2021-3981
+ Closes: #1001414
+ * postinst: be more verbose when using grub-install to install onto
+ devices.
+ * /etc/default/grub: Fix comment about text-mode console.
+ Fixes #845683
+ * grub-install: Don't install the shim fallback program when called
+ with --removable. Closes: #1016737
+ * grub-install: Don't use our grub CD EFI image for --removable.
+ Closes: #1026915. Thanks to Pascal Hambourg for the patch.
+ * Ignore some new ext2 flags to stay compatible with latest mke2fs
+ defaults. Closes: #1030846
+
+ [ Colin Watson ]
+ * Remove myself from Uploaders.
+
+ -- Steve McIntyre <93sam@debian.org> Thu, 09 Feb 2023 01:09:00 +0000
+
+grub2 (2.06-7) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Fix bug in core file code so errors are handled better. This makes
+ the fallback font-handling patch work properly.
+ Closes: #1025469, #1025477.
+
+ -- Steve McIntyre <93sam@debian.org> Tue, 06 Dec 2022 03:14:53 +0000
+
+grub2 (2.06-6) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Include fonts in the memdisk build for EFI images.
+ Closes: #1024395, #1025352, #1024447
+ * Bump Debian SBAT level to 4
+ - Due to a mistake in the buster upload (2.06-3~deb10u2) that left
+ the CVE-2022-2601 bugs in place, we need to bump SBAT for all of
+ the Debian GRUB binaries. :-(
+ * Switch away from git-dpm
+
+ -- Steve McIntyre <93sam@debian.org> Sun, 04 Dec 2022 20:42:23 +0000
+
+grub2 (2.06-5) unstable; urgency=high
+
+ [ Steve McIntyre ]
+ * Explicitly unset SOURCE_DATE_EPOCH before running fs tests
+ * Pull in upstream patches to harden font and image handling -
+ CVE-2022-2601, CVE-2022-3775.
+ * Bump SBAT level to 3 for grub-efi packages
+
+ -- Steve McIntyre <93sam@debian.org> Sun, 13 Nov 2022 00:33:35 +0000
+
+grub2 (2.06-4) unstable; urgency=high
+
+ [ Steve McIntyre ]
+ * Updated the 2.06-3 changelog to mention closure of CVE-2022-28736
+ * Add a commented-out GRUB_DISABLE_OS_PROBER section to
+ /etc/default/grub to make it easier for users to turn os-prober
+ back on if they want it. Closes: #1013797, #1009336
+ * Add smbios to the signed grub efi images. Closes: #1008106
+ * Add serial to the signed grub efi images. Closes: #1013962
+ * grub2-common: Remove dependency on install-info, it's apparently
+ not needed. Closes: #1013698
+ * Don't strip Xen binaries so they work again. Closes: #1017944.
+ Thanks to Valentin Kleibel for the patch.
+
+ -- Steve McIntyre <93sam@debian.org> Wed, 14 Sep 2022 22:35:49 +0100
+
+grub2 (2.06-3) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Update a few leftover uses of "which" to use "command -v" instead.
+ * Remove some old Lintian overrides.
+ * Trim trailing whitespace.
+ * debian/copyright: use spaces rather than tabs to start continuation lines.
+ * Add missing ${misc:Depends} to Depends for grub-efi-ia32-signed-template,
+ grub-efi-amd64-signed-template, grub-efi-arm64-signed-template.
+ * Bump debhelper from old 10 to 13.
+ * Set upstream metadata fields: Bug-Submit (from ./configure), Repository,
+ Repository-Browse.
+ * Drop now-unnecessary sparc PIE workaround from debian/rules (thanks,
+ John Paul Adrian Glaubitz; closes: #952815).
+
+ [ Debconf translations ]
+ * [id] Indonesian (Andika Triwidada; closes: #1007706).
+
+ [ Julian Andres Klode ]
+ * Add Julian Andres Klode to uploaders
+ * Disable building with LTO, as used in Ubuntu and possibly other
+ downstreams (maybe Debian one day), as that breaks the build.
+ * SECURITY UPDATE: Crafted PNG grayscale images may lead to out-of-bounds
+ write in heap.
+ - 0070-video-readers-png-Drop-greyscale-support-to-fix-heap.patch:
+ video/readers/png: Drop greyscale support to fix heap out-of-bounds write
+ - CVE-2021-3695
+ * SECURITY UPDATE: Crafted PNG image may lead to out-of-bound write during
+ huffman table handling.
+ - 0071-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch:
+ video/readers/png: Avoid heap OOB R/W inserting huff table items
+ - CVE-2021-3696
+ * SECURITY UPDATE: Crafted JPEG image can lead to buffer underflow write in
+ the heap.
+ - 0076-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch:
+ video/readers/jpeg: Block int underflow -> wild pointer write
+ - CVE-2021-3697
+ * SECURITY UPDATE: Integer underflow in grub_net_recv_ip4_packets
+ - 0079-net-ip-Do-IP-fragment-maths-safely.patch: net/ip: Do IP fragment
+ maths safely
+ - CVE-2022-28733
+ * SECURITY UPDATE: Out-of-bounds write when handling split HTTP headers
+ - 0085-net-http-Fix-OOB-write-for-split-http-headers.patch: net/http: Fix
+ OOB write for split http headers
+ - CVE-2022-28734
+ * SECURITY UPDATE: shim_lock verifier allows non-kernel files to be loaded
+ - 0066-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch:
+ kern/efi/sb: Reject non-kernel files in the shim_lock verifier
+ - CVE-2022-28735
+ - Closes: #1001057
+ * SECURITY UPDATE: use-after-free in grub_cmd_chainloader()
+ - 0063-loader-efi-chainloader-Simplify-the-loader-state.patch:
+ loader/efi/chainloader: simplify the loader state
+ - 0064-commands-boot-Add-API-to-pass-context-to-loader.patch: commands/boot:
+ Add API to pass context to loader
+ - 0065-loader-efi-chainloader-Use-grub_loader_set_ex.patch:
+ loader/efi/chainloader: Use grub_loader_set_ex
+ - 0066-loader-i386-efi-linux-Use-grub_loader_set_ex.patch:
+ loader/i386/efi/linux: Use grub_loader_set_ex
+ - CVE-2022-28736
+ * Various fixes as a result of fuzzing and static analysis:
+ - 0067-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch:
+ kern/file: Do not leak device_name on error in grub_file_open()
+ - 0068-video-readers-png-Abort-sooner-if-a-read-operation-f.patch:
+ video/readers/png: Abort sooner if a read operation fails
+ - 0069-video-readers-png-Refuse-to-handle-multiple-image-he.patch:
+ video/readers/png: Refuse to handle multiple image headers
+ - 0072-video-readers-png-Sanity-check-some-huffman-codes.patch:
+ video/readers/png: Sanity check some huffman codes
+ - 0073-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch:
+ video/readers/jpeg: Abort sooner if a read operation fails
+ - 0074-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch:
+ video/readers/jpeg: Do not reallocate a given huff table
+ - 0075-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch:
+ video/readers/jpeg: Refuse to handle multiple start of streams
+ - 0077-normal-charset-Fix-array-out-of-bounds-formatting-un.patch:
+ normal/charset: Fix array out-of-bounds formatting unicode for display
+ - 0078-net-netbuff-Block-overly-large-netbuff-allocs.patch:
+ net/netbuff: Block overly large netbuff allocs
+ - 0080-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch:
+ net/dns: Fix double-free addresses on corrupt DNS response
+ - 0081-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch:
+ net/dns: Don't read past the end of the string we're checking against
+ - 0082-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch:
+ net/tftp: Prevent a UAF and double-free from a failed seek
+ - 0083-net-tftp-Avoid-a-trivial-UAF.patch: net/tftp: Avoid a trivial UAF
+ - 0084-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch:
+ net/http: Do not tear down socket if it's already been torn down
+ - 0086-net-http-Error-out-on-headers-with-LF-without-CR.patch:
+ net/http: Error out on headers with LF without CR
+ - 0087-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch:
+ fs/f2fs: Do not read past the end of nat journal entries
+ - 0088-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch:
+ fs/f2fs: Do not read past the end of nat bitmap
+ - 0089-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch:
+ fs/f2fs: Do not copy file names that are too long
+ - 0090-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch:
+ fs/btrfs: Fix several fuzz issues with invalid dir item sizing
+ - 0091-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch:
+ fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing
+ - 0092-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch:
+ fs/btrfs: Fix more fuzz issues related to chunks
+ * Bump SBAT generation:
+ - update debian/sbat.debian.csv.in
+
+ -- Julian Andres Klode <jak@debian.org> Fri, 10 Jun 2022 11:15:11 +0200
+
+grub2 (2.06-2) unstable; urgency=medium
+
+ * Update to minilzo-2.10, fixing build failures on armel, mips64el,
+ mipsel, and ppc64el.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 29 Nov 2021 00:10:09 +0000
+
+grub2 (2.06-1) unstable; urgency=medium
+
+ * Use "command -v" in maintainer scripts rather than "which".
+ * New upstream release.
+ - Switch to the upstream shim_lock verifier, dropping several more
+ manual checks for UEFI Secure Boot.
+ * Cherry-pick from upstream:
+ - fs/xfs: Fix unreadable filesystem with v4 superblock
+ - tests/ahci: Change "ide-drive" deprecated QEMU device name to "ide-hd"
+ (closes: #997100)
+ * Remove dir_to_symlink maintainer script code, which was only needed for
+ upgrades from before jessie.
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 28 Nov 2021 13:30:32 +0000
+
+grub2 (2.04-20) unstable; urgency=medium
+
+ [ Mathieu Trudel-Lapierre ]
+ * tpm: Pass unknown error as non-fatal, but debug print the error we got
+ (closes: #940911, LP: #1848892).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 11 Jul 2021 00:37:36 +0100
+
+grub2 (2.04-19) unstable; urgency=medium
+
+ * Resync grub-install backup and restore patches from upstream, fixing
+ problems that left the system unbootable after certain kinds of failure
+ (closes: #983435).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 19 Jun 2021 13:04:38 +0100
+
+grub2 (2.04-18) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Enable the shim_lock and tpm modules for i386-efi too. Ensure that
+ tpm is included in our EFI images.
+ * List the modules we include the EFI images - make it easier to
+ debug things.
+ * Add debug to display what's going on with verifiers
+
+ [ Colin Watson ]
+ * util/mkimage: Some fixes to PE binaries section size calculation
+ (closes: #987103).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 25 Apr 2021 16:20:17 +0100
+
+grub2 (2.04-17) unstable; urgency=medium
+
+ * Pass --sbat when building the d-i netboot image as well.
+ * i386-pc: build verifiers API as module (thanks, Michael Chang; closes:
+ #984488, #985374).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 19 Mar 2021 10:41:41 +0000
+
+grub2 (2.04-16) unstable; urgency=medium
+
+ * Fix broken advice in message when the postinst has to bail out (thanks
+ to Daniel Leidert for pointing out the problem).
+ * Backport security patch series from upstream:
+ - verifiers: Move verifiers API to kernel image
+ - kern: Add lockdown support
+ - kern/lockdown: Set a variable if the GRUB is locked down
+ - efi: Lockdown the GRUB when the UEFI Secure Boot is enabled
+ - efi: Use grub_is_lockdown() instead of hardcoding a disabled modules
+ list
+ - CVE-2020-14372: acpi: Don't register the acpi command when locked down
+ - CVE-2020-27779: mmap: Don't register cutmem and badram commands when
+ lockdown is enforced
+ - commands: Restrict commands that can load BIOS or DT blobs when locked
+ down
+ - commands/setpci: Restrict setpci command when locked down
+ - commands/hdparm: Restrict hdparm command when locked down
+ - gdb: Restrict GDB access when locked down
+ - loader/xnu: Don't allow loading extension and packages when locked
+ down
+ - docs: Document the cutmem command
+ - CVE-2020-25632: dl: Only allow unloading modules that are not
+ dependencies
+ - CVE-2020-25647: usb: Avoid possible out-of-bound accesses caused by
+ malicious devices
+ - mmap: Fix memory leak when iterating over mapped memory
+ - net/net: Fix possible dereference to of a NULL pointer
+ - net/tftp: Fix dangling memory pointer
+ - kern/parser: Fix resource leak if argc == 0
+ - kern/efi: Fix memory leak on failure
+ - kern/efi/mm: Fix possible NULL pointer dereference
+ - gnulib/regexec: Resolve unused variable
+ - gnulib/regcomp: Fix uninitialized token structure
+ - gnulib/argp-help: Fix dereference of a possibly NULL state
+ - gnulib/regexec: Fix possible null-dereference
+ - gnulib/regcomp: Fix uninitialized re_token
+ - io/lzopio: Resolve unnecessary self-assignment errors
+ - zstd: Initialize seq_t structure fully
+ - kern/partition: Check for NULL before dereferencing input string
+ - disk/ldm: Make sure comp data is freed before exiting from make_vg()
+ - disk/ldm: If failed then free vg variable too
+ - disk/ldm: Fix memory leak on uninserted lv references
+ - disk/cryptodisk: Fix potential integer overflow
+ - hfsplus: Check that the volume name length is valid
+ - zfs: Fix possible negative shift operation
+ - zfs: Fix resource leaks while constructing path
+ - zfs: Fix possible integer overflows
+ - zfsinfo: Correct a check for error allocating memory
+ - affs: Fix memory leaks
+ - libgcrypt/mpi: Fix possible unintended sign extension
+ - libgcrypt/mpi: Fix possible NULL dereference
+ - syslinux: Fix memory leak while parsing
+ - normal/completion: Fix leaking of memory when processing a completion
+ - commands/hashsum: Fix a memory leak
+ - video/efi_gop: Remove unnecessary return value of
+ grub_video_gop_fill_mode_info()
+ - video/fb/fbfill: Fix potential integer overflow
+ - video/fb/video_fb: Fix multiple integer overflows
+ - video/fb/video_fb: Fix possible integer overflow
+ - video/readers/jpeg: Test for an invalid next marker reference from a
+ jpeg file
+ - gfxmenu/gui_list: Remove code that coverity is flagging as dead
+ - loader/bsd: Check for NULL arg up-front
+ - loader/xnu: Fix memory leak
+ - loader/xnu: Free driverkey data when an error is detected in
+ grub_xnu_writetree_toheap()
+ - loader/xnu: Check if pointer is NULL before using it
+ - util/grub-install: Fix NULL pointer dereferences
+ - util/grub-editenv: Fix incorrect casting of a signed value
+ - util/glue-efi: Fix incorrect use of a possibly negative value
+ - script/execute: Fix NULL dereference in grub_script_execute_cmdline()
+ - commands/ls: Require device_name is not NULL before printing
+ - script/execute: Avoid crash when using "$#" outside a function scope
+ - CVE-2021-20225: lib/arg: Block repeated short options that require an
+ argument
+ - script/execute: Don't crash on a "for" loop with no items
+ - CVE-2021-20233: commands/menuentry: Fix quoting in setparams_prefix()
+ - kern/misc: Always set *end in grub_strtoull()
+ - video/readers/jpeg: Catch files with unsupported quantization or
+ Huffman tables
+ - video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du()
+ - video/readers/jpeg: Don't decode data before start of stream
+ - term/gfxterm: Don't set up a font with glyphs that are too big
+ - fs/fshelp: Catch impermissibly large block sizes in read helper
+ - fs/hfsplus: Don't fetch a key beyond the end of the node
+ - fs/hfsplus: Don't use uninitialized data on corrupt filesystems
+ - fs/hfs: Disable under lockdown
+ - fs/sfs: Fix over-read of root object name
+ - fs/jfs: Do not move to leaf level if name length is negative
+ - fs/jfs: Limit the extents that getblk() can consider
+ - fs/jfs: Catch infinite recursion
+ - fs/nilfs2: Reject too-large keys
+ - fs/nilfs2: Don't search children if provided number is too large
+ - fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup()
+ - io/gzio: Bail if gzio->tl/td is NULL
+ - io/gzio: Add init_dynamic_block() clean up if unpacking codes fails
+ - io/gzio: Catch missing values in huft_build() and bail
+ - io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build()
+ fails
+ - disk/lvm: Don't go beyond the end of the data we read from disk
+ - disk/lvm: Don't blast past the end of the circular metadata buffer
+ - disk/lvm: Bail on missing PV list
+ - disk/lvm: Do not crash if an expected string is not found
+ - disk/lvm: Do not overread metadata
+ - disk/lvm: Sanitize rlocn->offset to prevent wild read
+ - disk/lvm: Do not allow a LV to be it's own segment's node's LV
+ - fs/btrfs: Validate the number of stripes/parities in RAID5/6
+ - fs/btrfs: Squash some uninitialized reads
+ - kern/parser: Fix a memory leak
+ - kern/parser: Introduce process_char() helper
+ - kern/parser: Introduce terminate_arg() helper
+ - kern/parser: Refactor grub_parser_split_cmdline() cleanup
+ - kern/buffer: Add variable sized heap buffer
+ - CVE-2020-27749: kern/parser: Fix a stack buffer overflow
+ - kern/efi: Add initial stack protector implementation
+ - util/mkimage: Remove unused code to add BSS section
+ - util/mkimage: Use grub_host_to_target32() instead of
+ grub_cpu_to_le32()
+ - util/mkimage: Always use grub_host_to_target32() to initialize PE
+ stack and heap stuff
+ - util/mkimage: Unify more of the PE32 and PE32+ header set-up
+ - util/mkimage: Reorder PE optional header fields set-up
+ - util/mkimage: Improve data_size value calculation
+ - util/mkimage: Refactor section setup to use a helper
+ - util/mkimage: Add an option to import SBAT metadata into a .sbat
+ section
+ - grub-install-common: Add --sbat option
+ - kern/misc: Split parse_printf_args() into format parsing and va_list
+ handling
+ - kern/misc: Add STRING type for internal printf() format handling
+ - kern/misc: Add function to check printf() format against expected
+ format
+ - gfxmenu/gui: Check printf() format in the gui_progress_bar and
+ gui_label
+ - kern/mm: Fix grub_debug_calloc() compilation error
+ * Add SBAT section (thanks, Chris Coulson).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 02 Mar 2021 18:00:00 +0000
+
+grub2 (2.04-15) unstable; urgency=medium
+
+ * Demote grub-common → mtools dependency to Suggests, to go with xorriso;
+ explain the situation in the package description (closes: #982313).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 08 Feb 2021 21:39:24 +0000
+
+grub2 (2.04-14) unstable; urgency=medium
+
+ [ Raphaël Hertzog ]
+ * Extend grub-efi to also cover arm64/ia64/arm (closes: #981819).
+
+ [ Colin Watson ]
+ * Cherry-pick from upstream:
+ - grub-install: Fix inverted test for NLS enabled when copying locales
+ (closes: #979754).
+ * Fix handling of trailing commas in grub-pc/install_devices (closes:
+ #913928).
+ * Make grub-firmware-qemu Recommend/Enhance qemu-system-x86, not qemu
+ (closes: #966243).
+ * Make grub-common depend on mtools on EFI platforms, for grub-mkrescue
+ (closes: #774910).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 07 Feb 2021 15:23:51 +0000
+
+grub2 (2.04-13) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Switch to using the efivarfs interface for detecting "system setup"
+ (Closes: #979299)
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 06 Feb 2021 17:30:38 +0000
+
+grub2 (2.04-12) unstable; urgency=medium
+
+ * Cherry-pick from upstream:
+ - mdraid1x_linux: Fix gcc10 error -Werror=array-bounds
+ - zfs: Fix gcc10 error -Werror=zero-length-bounds
+ * Build with GCC 10 (closes: #978515).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 28 Dec 2020 22:33:23 +0000
+
+grub2 (2.04-11) unstable; urgency=medium
+
+ * grub-install: Fix backup restoration on i386 (closes: #976671).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 06 Dec 2020 18:29:51 +0000
+
+grub2 (2.04-10) unstable; urgency=medium
+
+ [ Ian Campbell ]
+ * Remove myself from uploaders.
+
+ [ Colin Watson ]
+ * When upgrading grub-pc noninteractively, bail out if grub-install fails.
+ It's better to fail the upgrade than to produce a possibly-unbootable
+ system.
+ * Explicitly check whether the target device exists before running
+ grub-install, since grub-install copies modules to /boot/grub/ before
+ installing the core image, and the new modules might be incompatible
+ with the old core image (closes: #966575).
+ * Cherry-pick from upstream:
+ - tftp: Roll-over block counter to prevent data packets timeouts
+ (LP: #1892290).
+
+ [ Dimitri John Ledkov ]
+ * grub-install: Add backup and restore.
+ * Don't call grub-install on fresh install of grub-pc. It's the job of
+ installers to do that after a fresh install.
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 08 Nov 2020 16:26:08 +0000
+
+grub2 (2.04-9) unstable; urgency=high
+
+ * Backport security patch series from upstream:
+ - CVE-2020-10713: yylex: Make lexer fatal errors actually be fatal
+ - safemath: Add some arithmetic primitives that check for overflow
+ - calloc: Make sure we always have an overflow-checking calloc()
+ available
+ - CVE-2020-14308: calloc: Use calloc() at most places
+ - CVE-2020-14309, CVE-2020-14310, CVE-2020-14311: malloc: Use overflow
+ checking primitives where we do complex allocations
+ - iso9660: Don't leak memory on realloc() failures
+ - font: Do not load more than one NAME section
+ - gfxmenu: Fix double free in load_image()
+ - xnu: Fix double free in grub_xnu_devprop_add_property()
+ - lzma: Make sure we don't dereference past array
+ - term: Fix overflow on user inputs
+ - udf: Fix memory leak
+ - multiboot2: Fix memory leak if grub_create_loader_cmdline() fails
+ - tftp: Do not use priority queue
+ - relocator: Protect grub_relocator_alloc_chunk_addr() input args
+ against integer underflow/overflow
+ - relocator: Protect grub_relocator_alloc_chunk_align() max_addr against
+ integer underflow
+ - script: Remove unused fields from grub_script_function struct
+ - CVE-2020-15706: script: Avoid a use-after-free when redefining a
+ function during execution
+ - relocator: Fix grub_relocator_alloc_chunk_align() top memory
+ allocation
+ - hfsplus: fix two more overflows
+ - lvm: fix two more potential data-dependent alloc overflows
+ - emu: make grub_free(NULL) safe
+ - efi: fix some malformed device path arithmetic errors
+ - Fix a regression caused by "efi: fix some malformed device path
+ arithmetic errors"
+ - update safemath with fallback code for gcc older than 5.1
+ - efi: Fix use-after-free in halt/reboot path
+ - linux loader: avoid overflow on initrd size calculation
+ * CVE-2020-15707: linux: Fix integer overflows in initrd size handling
+ * Apply overflow checking to allocations in Debian patches:
+ - bootp: Fix integer overflow in parse_dhcp6_option
+ - unix/config: Fix integer overflow in grub_util_load_config
+ - deviceiter: Fix integer overflow in grub_util_iterate_devices
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 29 Jul 2020 17:58:37 +0100
+
+grub2 (2.04-8) unstable; urgency=medium
+
+ [ Vincent Lefevre ]
+ * Fix typos in /etc/grub.d/05_debian_theme. Closes: #959484
+
+ [ Fabian Greffrath ]
+ * Change font dependency to fonts-dejavu-core. Closes: #912846
+
+ [ Colin Watson ]
+ * Cherry-pick from upstream:
+ - templates/20_linux_xen: Ignore xenpolicy and config files too.
+ - templates/20_linux_xen: Support Xen Security Modules (XSM/FLASK).
+
+ [ Ian Jackson ]
+ * 20_linux_xen: Do not load XSM policy in non-XSM options (closes:
+ #961673).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 07 Jun 2020 10:06:37 +0100
+
+grub2 (2.04-7) unstable; urgency=medium
+
+ [ Christian Göttsche ]
+ * Create grub default configuration with default SELinux context.
+
+ [ Steve McIntyre ]
+ * In the signed packages, change the version dependency on
+ grub-common to be >= and not =. This will allow for installation
+ in unstable to still work in the window while we wait for the
+ template package to do its second trip through the archive.
+ * Tweak the build-dep architecture listing for libefiboot-dev and
+ libefivar-dev. The linux-* wildcards don't work in the way
+ expected, and were missing out (at least) armhf and armel.
+ Closes: #958461
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 22 Apr 2020 14:52:13 +0100
+
+grub2 (2.04-6) unstable; urgency=medium
+
+ [ Romain Perier ]
+ * Add f2fs module to signed UEFI images
+
+ [ Steve McIntyre ]
+ * Add jfs module to signed UEFI images. Closes: #950959
+
+ [ Colin Watson ]
+ * Drop mkconfig-mid-upgrade.patch; it was only needed for upgrades from
+ GRUB 1.99 (now a long time ago) and can inappropriately hide problems
+ when /etc/grub.d/00_header should have been updated but wasn't (closes:
+ #953201).
+ * Cherry-pick from upstream:
+ - btrfs: Add support for new RAID1C34 profiles (closes: #958236).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 20 Apr 2020 01:03:08 +0100
+
+grub2 (2.04-5) unstable; urgency=medium
+
+ * Cherry-pick from upstream:
+ - verifiers: Blocklist fallout cleanup (this was one cause of a build
+ failure on hurd-i386, though may not be the only one).
+ * Only recommend grub-efi-*-signed on the architectures where they exist.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 16 Dec 2019 15:48:45 +0000
+
+grub2 (2.04-4) unstable; urgency=medium
+
+ [ Thomas Gaugler ]
+ * Add leading / to prefix of network boot image for d-i.
+
+ [ Martin von Wittich ]
+ * upgrade-from-grub-legacy: Set DPKG_MAINTSCRIPT_NAME and
+ DPKG_MAINTSCRIPT_PACKAGE when calling grub-pc.postinst manually (closes:
+ #943387).
+
+ [ Colin Watson ]
+ * Use policy-compliant architecture wildcards in libefiboot-dev and
+ libefivar-dev build-dependencies.
+ * Build with GCC 9 (closes: #944166).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 08 Nov 2019 10:58:30 +0000
+
+grub2 (2.04-3) unstable; urgency=medium
+
+ * Apply patch from James Clarke to fix BIOS Boot Partition support on
+ sparc64 (closes: #931969).
+ * Fix UEFI installation for Devuan (thanks, Ivan J.; closes: #932966).
+ * Add probe module to signed UEFI images (closes: #936082).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 30 Aug 2019 13:50:41 +0100
+
+grub2 (2.04-2) unstable; urgency=medium
+
+ [ James Clarke ]
+ * Only Build-Depend on libefiboot-dev and libefivar-dev on Linux
+ architectures, since they're Linux-only.
+
+ [ Colin Watson ]
+ * Use debhelper-compat instead of debian/compat.
+ * debian/apport/source_grub2.py:
+ - Avoid star import.
+ - Fix flake8 errors.
+ * Run gentpl.py with python3.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 03 Aug 2019 13:42:49 +0100
+
+grub2 (2.04-1) unstable; urgency=medium
+
+ * New upstream release.
+ * debian/upstream/signing-key.asc: Add signing key of new upstream
+ maintainer (Daniel Kiper).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 09 Jul 2019 11:48:01 +0100
+
+grub2 (2.04~rc1-3) experimental; urgency=medium
+
+ [ Will Thompson ]
+ * Fix --disable-quiet-boot.
+
+ [ Steve Langasek ]
+ * If we don't have writable grubenv and we're on EFI, always show the menu
+ (merged from Ubuntu).
+
+ [ Steve McIntyre ]
+ * Make all the signed EFI arches have a Recommends: from
+ grub-efi-ARCH-signed to shim-signed, not just amd64.
+ Closes: #931038
+ * Add myself to Uploaders
+
+ [ Colin Watson ]
+ * Squash linuxefi* patches into a single patch.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 27 Jun 2019 08:51:37 +0100
+
+grub2 (2.04~rc1-2) experimental; urgency=medium
+
+ [ Colin Watson ]
+ * debian/build-efi-images: Add tpm on x86_64-efi (thanks, Chris Coulson).
+
+ [ Steve McIntyre ]
+ * Add the ntfs module to signed UEFI images. Closes: #923855
+ * Add the cpuid module to signed UEFI images. Closes: #928628
+ * Add the play module to signed UEFI images. Closes: #930290
+ * Add an extra di-specific version of the UEFI netboot image with a
+ different baked-in prefix value. Helps to fix #928750.
+ * Deal with --force-extra-removable with signed shim too. Closes: #930531
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 15 Jun 2019 09:41:19 +0100
+
+grub2 (2.04~rc1-1) experimental; urgency=medium
+
+ * New upstream release candidate.
+ - getroot: Save/restore CWD more reliably on Unix (closes: #918700).
+ * Rename patches to use "-" as a separator rather than "_" (except when
+ referring to a file, function, or command containing a "_").
+ * Fix format of debian/copyright.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 30 May 2019 16:56:05 +0100
+
+grub2 (2.02+dfsg1-20) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Make all the signed EFI arches have a Recommends: from
+ grub-efi-ARCH-signed to shim-signed, not just amd64.
+ Closes: #931038
+ * Add myself to Uploaders
+
+ -- Steve McIntyre <93sam@debian.org> Tue, 25 Jun 2019 10:11:12 +0100
+
+grub2 (2.02+dfsg1-19) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Fix format of debian/copyright.
+
+ [ Steve McIntyre ]
+ * Add the ntfs module to signed UEFI images. Closes: #923855
+ * Add the cpuid module to signed UEFI images. Closes: #928628
+ * Add the play module to signed UEFI images. Closes: #930290
+ * Add an extra di-specific version of the UEFI netboot image with a
+ different baked-in prefix value. Helps to fix #928750.
+ * Deal with --force-extra-removable with signed shim too. Closes: #930531
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 14 Jun 2019 19:04:01 +0100
+
+grub2 (2.02+dfsg1-18) unstable; urgency=medium
+
+ * Apply patches from Alexander Graf to fix grub-efi-arm crash (closes:
+ #927269):
+ - arm: Move trampolines into code section
+ - arm: Align section alignment with manual relocation offset code
+ * Make grub2-common Breaks+Replaces grub-cloud-amd64 (<< 0.0.4) to work
+ around that package shipping colliding configuration file names in
+ stretch-backports (closes: #919915).
+ * Apply patch from Peter Jones to forbid the "devicetree" command when
+ Secure Boot is enabled (closes: #927888).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 04 May 2019 22:58:32 +0100
+
+grub2 (2.02+dfsg1-17) unstable; urgency=medium
+
+ * Make grub-efi-*-bin recommend efibootmgr. We don't actually use it any
+ more, but it's helpful for debugging.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 15 Apr 2019 18:38:30 +0100
+
+grub2 (2.02+dfsg1-16) unstable; urgency=medium
+
+ * Fix -Wcast-align diagnostics on ARM.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 23 Mar 2019 23:28:17 +0000
+
+grub2 (2.02+dfsg1-15) unstable; urgency=medium
+
+ * Build-depend on libefiboot-dev and libefivar-dev, for EFI variable
+ storage changes.
+ * Drop now-unnecessary dependencies on efibootmgr.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 23 Mar 2019 09:56:35 +0000
+
+grub2 (2.02+dfsg1-14) unstable; urgency=medium
+
+ * Make signed packages depend on a matching version of grub-common, in an
+ attempt to prevent incorrect testing migrations (closes: #924814).
+ * Cherry-pick from upstream:
+ - xfs: Accept filesystem with sparse inodes (closes: #924760).
+ * Minimise writes to EFI variable storage (closes: #891434).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 23 Mar 2019 09:47:10 +0000
+
+grub2 (2.02+dfsg1-13) unstable; urgency=medium
+
+ * Add regexp module to signed UEFI images.
+ * debian/signing-template.json.in: Use new extendable format.
+
+ [ Debconf translations ]
+ * [nb] Norwegian Bokmål (Petter Reinholdtsen; closes: #924326).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 14 Mar 2019 10:33:24 +0000
+
+grub2 (2.02+dfsg1-12) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Remove code to migrate grub-pc/install_devices to persistent device
+ names under /dev/disk/by-id/. This migration happened in
+ 1.98+20100702-1, which was in squeeze (four stable releases ago), so we
+ no longer need to carry around this complex code.
+ * Preserve previous answer to grub-pc/install_devices if we have to ask
+ grub-pc/install_devices_disks_changed and the user chooses not to
+ install to any devices, so that we can recover from temporary bugs that
+ cause /dev/disk/by-id/ paths to change (closes: #919029).
+ * debian/signing-template.json.in: Add trusted_certs key (empty, since
+ GRUB has no hardcoded list of trusted certificates).
+ * util: Detect more I/O errors (closes: #922741).
+
+ [ Leif Lindholm ]
+ * arm64/efi: Fix grub_efi_get_ram_base().
+
+ [ Steve McIntyre ]
+ * grub-install: Check for arm-efi as a default target (closes: #922104).
+
+ [ James Clarke ]
+ * osdep/freebsd: Fix partition calculation for EBR entries (closes:
+ #923253).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 01 Mar 2019 12:34:45 +0000
+
+grub2 (2.02+dfsg1-11) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Apply patches from Alexander Graf to set arm64-efi code offset to
+ EFI_PAGE_SIZE (closes: #919012, LP: #1812317).
+ * Upgrade to debhelper v10.
+ * Set Rules-Requires-Root: no.
+ * Add help and ls modules to signed UEFI images (closes: #919955).
+ * Fix application of answers from dpkg-reconfigure to /etc/default/grub
+ (based loosely on a patch by Steve Langasek, for which thanks; closes:
+ #921702).
+
+ [ Steve McIntyre ]
+ * Make grub-efi-amd64-signed recommend shim-signed (closes: #919067).
+
+ [ Jeroen Dekkers ]
+ * Initialize keyboard in at_keyboard module init if keyboard is ready
+ (closes: #741464).
+
+ [ John Paul Adrian Glaubitz ]
+ * Include a.out header in assembly of sparc64 boot loader (closes:
+ #921249).
+
+ [ Hervé Werner ]
+ * Fix setup on Secure Boot systems where cryptodisk is in use (closes:
+ #917117).
+
+ [ Debconf translations ]
+ * [de] German (Helge Kreutzmann and Holger Wansing; closes: #921018).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 10 Feb 2019 18:53:41 +0000
+
+grub2 (2.02+dfsg1-10) unstable; urgency=medium
+
+ * Apply patch from Heinrich Schuchardt (mentioned in #916695 though
+ unrelated):
+ - grub-core/loader/efi/fdt.c: do not copy random memory
+ * Add luks modules to signed UEFI images (pointed out by Alex Griffin and
+ Hervé Werner; closes: #908162, LP: #1565950).
+ * Keep track of the previous version of /usr/share/grub/default/grub and
+ set UCF_FORCE_CONFFOLD=1 when running ucf if it hasn't changed; ucf
+ can't figure this out for itself since we apply debconf-based
+ customisations on top of the template configuration file (closes:
+ #812574, LP: #564853).
+ * Backport Xen PVH guest support from upstream (closes: #776450). Thanks
+ to Hans van Kranenburg for testing.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 11 Jan 2019 15:24:20 +0000
+
+grub2 (2.02+dfsg1-9) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Sync Maintainer/Uploaders in debian/signing-template/control.in with the
+ main packaging.
+ * Tell reportbug to submit bug reports against unsigned packages rather
+ than generated signed packages.
+ * Update Homepage, debian/copyright Source, and debian/watch to use HTTPS.
+ * Move bash completions to /usr/share/bash-completion/completions/grub and
+ add appropriate symlinks (closes: #912852).
+ * Build with GCC 8 (closes: #915735).
+
+ [ Leif Lindholm ]
+ * Apply patch series (mostly) from upstream to switch the arm loader over
+ to use the arm64 loader code and improve arm/arm64 initrd handling
+ (closes: #907596, #909420, #915091).
+
+ [ Matthew Garrett ]
+ * Don't enforce Shim signature validation if Secure Boot is disabled.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 07 Dec 2018 10:38:37 +0000
+
+grub2 (2.02+dfsg1-8) unstable; urgency=medium
+
+ * Revise grub-<platform>-bin and grub-<platform> package descriptions to
+ try to explain better how they fit together and which one should be used
+ (based loosely on work by Justin B Rye, for which thanks; closes:
+ #630224).
+ * Skip flaky grub_cmd_set_date test (closes: #906470).
+ * Work around bug in obsolete init-select package: add Conflicts/Replaces
+ from grub-common, and take over /etc/default/grub.d/init-select.cfg with
+ a no-op stub (thanks to Guillem Jover for the suggestion; closes:
+ #863801).
+ * Build-depend on dosfstools and mtools on non-Linux variants of
+ i386/amd64/arm64 as well, to match debian/rules.
+ * Cherry-pick from upstream:
+ - i386/linux: Add support for ext_lfb_base (LP: #1785033).
+ * Don't source /etc/default/grub.d/*.cfg in config maintainer scripts,
+ since otherwise we incorrectly merge settings from there into
+ /etc/default/grub (closes: #872637, LP: #1797894).
+ * Add xfs module to signed UEFI images (closes: #911147, LP: #1652822).
+ * Cope with / being on a ZFS root dataset (closes: #886178).
+
+ [ Debconf translations ]
+ * [sv] Swedish (Martin Bagge and Anders Jonsson; closes: #851964).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 29 Oct 2018 13:02:08 +0000
+
+grub2 (2.02+dfsg1-7) unstable; urgency=medium
+
+ * Move kernel maintainer script snippets into grub2-common (thanks,
+ Bastian Blank; closes: #910959).
+ * Add cryptodisk and gcry_* modules to signed UEFI images (closes:
+ #908162, LP: #1565950).
+ * Remove dh_builddeb override to use xz compression; this has been the
+ default since dpkg 1.17.0.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 27 Oct 2018 13:06:32 +0100
+
+grub2 (2.02+dfsg1-6) unstable; urgency=medium
+
+ * Only build *-signed packages on their native architecture for now, since
+ otherwise we end up with clashing source packages (closes: #906596).
+ * Refer to source packages in Built-Using, not binary packages (closes:
+ #907483).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 28 Aug 2018 16:17:21 +0100
+
+grub2 (2.02+dfsg1-5) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Change Maintainer to pkg-grub-devel@alioth-lists.debian.net, following
+ Alioth lists migration.
+ * Backport from upstream:
+ - Use grub-file to figure out whether multiboot2 should be used for
+ Xen.gz (closes: #898947).
+ - x86-64: Treat R_X86_64_PLT32 as R_X86_64_PC32.
+ * Fix some test failures:
+ - Disable sercon in SeaBIOS.
+ - Fix qemu options for UHCI test.
+
+ [ Philipp Hahn ]
+ * Disallow unsigned kernels if UEFI Secure Boot is enabled
+ (patch by Linn Crosetto <linn@hpe.com>)
+ * Add patch to fix lockdown mode
+ (patch by Luca Boccassi <bluca@debian.org>)
+ * Build monolithic EFI binaries for signing (closes: #851994)
+ * Add template for signing monolithic EFI binaries
+ * debian/build-efi-images: Use correct EFI vendor (closes: #769172)
+
+ [ Luca Boccassi ]
+ * template packages: install changelog and copyright
+ * Override lintian error about template rules file
+ * Add XB-Efi-Vendor metadata to efi-*-bin packages
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 30 Jul 2018 13:33:23 +0100
+
+grub2 (2.02+dfsg1-4) unstable; urgency=medium
+
+ * Adjust restore_mkdevicemap.patch to fix format-overflow warning with GCC
+ 7 (the overflow was in fact impossible in practice, but GCC couldn't
+ prove that).
+ * Cherry-pick upstream patch to disable -Wformat-truncation on GCC >= 7 in
+ printf_unit_test.
+ * Build with GCC 7 (closes: #892397).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 01 Apr 2018 10:49:48 +0100
+
+grub2 (2.02+dfsg1-3) unstable; urgency=medium
+
+ * sparc64: Don't use devspec to determine the OBP path (closes: #854568).
+ * ieee1275: Fix crash in of_path_of_nvme when of_path is empty (closes:
+ #891773).
+ * sparc64: Limit nvme of_path_of_nvme to just SPARC.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 02 Mar 2018 12:53:34 +0000
+
+grub2 (2.02+dfsg1-2) unstable; urgency=medium
+
+ * Build-depend on libparted-dev on powerpc and ppc64 (closes: #891070).
+ * Add support for modern sparc64 hardware (thanks, Eric Snowberg via John
+ Paul Adrian Glaubitz; closes: #854568).
+ * Build without PIE on sparc and sparc64 (thanks, John Paul Adrian
+ Glaubitz; closes: #891733).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 28 Feb 2018 12:03:49 +0000
+
+grub2 (2.02+dfsg1-1) unstable; urgency=medium
+
+ * Switch to tracking debian/grub-extras/ using "git subtree" rather than
+ submodules.
+ * Update debian/README.source for Salsa migration.
+ * Use pkg-config to find FreeType (closes: #887721).
+ * Change various binary packages' priorities to optional, since "Priority:
+ extra" is now deprecated.
+ * Repack upstream tarball without grub-core/lib/libgcrypt*/cipher/crc.c,
+ and provide a replacement implementation backported from more recent
+ versions of libgcrypt (closes: #745409).
+ * Cherry-pick upstream patch to avoid -Werror=unused-value build failure
+ (closes: #890431).
+ * Handle the case where udevadm exists but is non-functional, as warned
+ about by Lintian 2.5.75.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 17 Feb 2018 21:28:41 +0000
+
+grub2 (2.02-3) unstable; urgency=medium
+
+ * Use current location for upstream signing key
+ (debian/upstream/signing-key.asc).
+ * Update upstream signing key to a non-expired version.
+ * Install bootinfo.txt and grub.chrp in grub-ieee1275-bin for ppc64, and
+ install and use prep-bootdev on powerpc and ppc64 as well as ppc64el
+ (thanks, John Paul Adrian Glaubitz; closes: #881730).
+ * Cherry-pick upstream patch to change the default TSC calibration method
+ to pmtimer on EFI systems (closes: #883193).
+ * Move VCS to salsa.debian.org.
+ * Consistently create /boot/grub in the postinst of all grub-<platform>
+ packages (closes: #884883).
+
+ [ Debconf translations ]
+ * [sq] Albanian (Silva Arapi; closes: #874497).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 10 Feb 2018 03:00:30 +0000
+
+grub2 (2.02-2) unstable; urgency=medium
+
+ * Comment out debian/watch lines for betas and pre-releases for now.
+ * Cherry-pick upstream patch to allow mounting ext2/3/4 file systems that
+ have the 'encrypt' feature enabled (closes: #840204).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 06 Jul 2017 18:02:02 +0100
+
+grub2 (2.02-1) unstable; urgency=medium
+
+ * New upstream release.
+ - xen: Fix wrong register in relocator (closes: #799480).
+ * Resolve symlinks for supported init paths as well as for /sbin/init
+ (thanks, Felipe Sateler; closes: #842315).
+
+ [ Debconf translations ]
+ * [sr] Serbian (Karolina Kalic; closes: #691288).
+ * [sr@latin] Serbian Latin (Karolina Kalic; closes: #691289).
+ * [pt] Portuguese (Rui Branco - DebianPT; closes: #864171).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 23 Jun 2017 13:47:39 +0100
+
+grub2 (2.02~beta3-5) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Make grub-install check for errors from efibootmgr (closes: #853234).
+ There are probably still underlying issues in other similar reported
+ bugs, but they're more effectively tracked elsewhere (e.g. efibootmgr)
+ at this point (closes: #756253, #852513).
+
+ [ Debconf translations ]
+ * [ug] Uyghur (Abduqadir Abliz).
+ * [es] Spanish (Manuel "Venturi" Porras Peralta; closes: #852977).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 11 Feb 2017 15:09:19 +0000
+
+grub2 (2.02~beta3-4) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Drop build-dependency on libxen-dev, unnecessary now that upstream has
+ taken a copy of the necessary public headers.
+ * Ensure that build-efi-images has a suitable PATH for running mkfs.msdos
+ (thanks, Luca Boccassi; closes: #852001).
+
+ [ dann frazier ]
+ * Add grub2/update_nvram template to allow users to disable NVRAM
+ updates during package upgrades (LP: #1642298).
+
+ [ Debconf translations ]
+ * [ro] Romanian (Andrei POPESCU).
+ * [kk] Kazakh (Baurzhan Muftakhidinov).
+ * [lt] Lithuanian (Rimas Kudelis).
+ * [th] Thai (Theppitak Karoonboonyanan).
+ * [sl] Slovenian (Vanja Cvelbar).
+ * [pl] Polish (Åukasz Dulny).
+ * [eu] Basque (Iñaki Larrañaga Murgoitio; closes: #851981).
+ * [bg] Bulgarian (Damyan Ivanov; closes: #852024).
+ * [de] German (Helge Kreutzmann; closes: #852027).
+ * [vi] Vietnamese (Trần Ngá»c Quân).
+ * [ko] Korean (Changwoo Ryu; closes: #852061).
+ * [ru] Russian (Yuri Kozlov; closes: #852064).
+ * [tr] Turkish (Mert Dirik).
+ * [it] Italian (Luca Monducci; closes: #852073).
+ * [cs] Czech (Miroslav Kure; closes: #852189).
+ * [be] Belarusian (Viktar Siarheichyk; closes: #852286).
+ * [eo] Esperanto (Felipe Castro).
+ * [uk] Ukrainian (Yatsenko Alexandr).
+ * [pt_BR] Brazilian Portuguese (Adriano Rafael Gomes; closes: #852325).
+ * [hr] Croatian (Tomislav Krznar).
+ * [ca] Catalan (Innocent De Marchi; closes: #852331).
+ * [fr] French (Baptiste Jammet; closes: #852341).
+ * [da] Danish (Joe Hansen; closes: #852349).
+ * [nl] Dutch (Frans Spiesschaert; closes: #852403).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 24 Jan 2017 11:39:45 +0000
+
+grub2 (2.02~beta3-3) unstable; urgency=medium
+
+ [ Chad MILLER ]
+ * Signal to zpool that it should emit full names of constituent devices
+ (closes: #824974, LP: #1527727).
+
+ [ Mathieu Trudel-Lapierre ]
+ * Fix support for IPv6 PXE booting under UEFI (LP: #1229458):
+ - misc-fix-invalid-char-strtol.patch: fix strto*l methods invalid chars.
+ - net_read_bracketed_ipv6_addr.patch: read bracketed IPv6 addresses.
+ - bootp_new_net_bootp6_command.patch: add new bootp6 commands.
+ - efinet_uefi_ipv6_pxe_support.patch: teach efinet to allow bootp6.
+ - bootp_process_dhcpack_http_boot.patch: process DHCPACK, support HTTP.
+ - efinet_set_network_from_uefi_devpath.patch: configure network from the
+ devpath provided by the UEFI firmware.
+ - efinet_set_dns_from_uefi_proto.patch: set DNS nameservers and search
+ domains from the UEFI protocol.
+ * debian/patches/install_signed.patch: update patch for the new names of
+ the EFI binaries from shim.
+ * debian/control: Breaks shim (<< 0.9+1474479173.6c180c6-0ubuntu1~) due to
+ the renamed binaries in the new shim.
+ * debian/postinst.in: call on to update-secureboot-policy on configure to
+ make sure users can disable shim validation if necessary.
+ * debian/build-efi-images: add loopback and squash4 modules to the signed
+ EFI images.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 01 Nov 2016 11:10:52 +0000
+
+grub2 (2.02~beta3-2) unstable; urgency=medium
+
+ * debian/watch: Switch URL scheme to HTTP.
+ * Fix operator precedence in GRUB_DEVICE UUID tests (closes: #841680,
+ #841741).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 31 Oct 2016 10:24:02 +0000
+
+grub2 (2.02~beta3-1) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * New upstream beta release.
+ * syslinux_test: Fix out-of-tree build handling.
+ * Drop "grub-shell: Pass -no-pad to xorriso when building floppy images".
+ The floppy images built by grub-shell are no longer over the floppy
+ limit, and this patch now itself causes fddboot_test failures.
+ * Build with GCC 6 (closes: #835964).
+ * linuxefi.patch: Adjust for libgcc removal.
+ * Apply openSUSE patch to accept empty modules for now so that Xen builds
+ work.
+
+ [ Debconf translations ]
+ * [ja] Japanese (Takuma Yamada; closes: #815203, #817084).
+
+ [ Martin Pitt ]
+ * debian/grub-common.init: Don't source /lib/init/vars.sh, we don't depend
+ on initscripts (and don't want to). There is no reason why we would not
+ use the LSB log_action_msg in non-verbose (default) mode, most other
+ packages use it unconditionally (closes: #824875, LP: #1584134).
+
+ [ Steve Beattie ]
+ * debian/rules: Disable PIE builds for GRUB modules (closes: #837493).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 16 Oct 2016 10:46:46 +0100
+
+grub2 (2.02~beta2-36) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Use HTTPS for Vcs-Git URL.
+ * Add zfs, zfscrypt, and zfsinfo to signed EFI images (LP: #1542358).
+
+ [ Martin Pitt ]
+ * debian/postinst.in, debian/kernel/zz-update-grub: Call
+ systemd-detect-virt (which works under any init system, despite the
+ name) instead of the Ubuntu specific running-in-container wrapper.
+ (LP: #1539016)
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 05 Feb 2016 15:41:05 +0000
+
+grub2 (2.02~beta2-35) unstable; urgency=medium
+
+ * Apply the arm64 -mpc-relative-literal-loads workaround in configure
+ rather than in debian/rules, to cope with toolchains that don't have the
+ relevant patch applied.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 22 Jan 2016 11:02:10 +0000
+
+grub2 (2.02~beta2-34) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Remove duplicate Replaces on grub-ieee1275 (<< 2.00-4) from
+ grub2-common.
+ * Refer to /usr/share/common-licenses/GPL-3 rather than
+ /usr/share/common-licenses/GPL.
+ * Cherry-pick upstream patches to add more ACPI opcodes to acpihalt
+ (closes: #766853, LP: #1530648).
+ * Drop build-dependency on libusb-dev, since it was currently unused in
+ any case; also explicitly configure with --disable-grub-emu-usb to avoid
+ possible future ambiguity (closes: #810421).
+ * Use dpkg-maintscript-helper to convert directories to symlinks in
+ various upgrade cases, in place of hand-coded equivalents.
+ * Change versioned Conflicts from grub-common and grub2-common into Breaks
+ or Breaks+Replaces as appropriate.
+ * Remove pragmas related to -Wunreachable-code (closes: #812047).
+ * Temporarily work around arm64 build failure with gcc-5 >= 5.3.1-4 using
+ -mpc-relative-literal-loads.
+ * Backport various ZFS improvements from trunk (closes: #706415, #772797;
+ LP: #1451476, #1530457).
+
+ [ Didier Roche ]
+ * Use new plymouth theme path to set grub theme configuration.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 22 Jan 2016 10:03:00 +0000
+
+grub2 (2.02~beta2-33) unstable; urgency=high
+
+ [ Mathieu Trudel-Lapierre ]
+ * Cherry-picks to better handle TFTP timeouts on some arches: (LP: #1521612)
+ - (7b386b7) efidisk: move device path helpers in core for efinet
+ - (c52ae40) efinet: skip virtual IP devices when enumerating cards
+ - (f348aee) efinet: enable hardware filters when opening interface
+
+ [ Lee Trager ]
+ * Add raid5rec and raid6rec to signed EFI images (closes: #807385).
+
+ [ Colin Watson ]
+ * CVE-2015-8370: Fix authentication bypass via backspace integer underflow
+ (closes: #808122).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 16 Dec 2015 09:46:22 +0000
+
+grub2 (2.02~beta2-32) unstable; urgency=medium
+
+ [ Mathieu Trudel-Lapierre ]
+ * Cherry-pick patch to add SAS disks to the device list from the ofdisk
+ module. (LP: #1517586)
+
+ [ dann frazier ]
+ * Cherry-pick patch to open Simple Network Protocol exclusively.
+ (LP: #1508893)
+
+ [ Linn Crosetto ]
+ * Install arm64 signed images if UEFI Secure Boot is enabled (closes:
+ #806178).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 25 Nov 2015 16:07:21 +0000
+
+grub2 (2.02~beta2-31) unstable; urgency=medium
+
+ * Cherry-pick upstream patch to fix XFS alignment treatment.
+ * Cherry-pick upstream patch to fix XFS handling of symlink with
+ crc-enabled filesystem.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 05 Nov 2015 15:08:03 +0000
+
+grub2 (2.02~beta2-30) unstable; urgency=medium
+
+ [ dann frazier ]
+ * arm64/setjmp: Add missing license macro. (LP: #1459871)
+
+ [ Colin Watson ]
+ * Cherry-pick upstream patches for XFS v5 support (closes: #772565).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 05 Nov 2015 12:30:27 +0000
+
+grub2 (2.02~beta2-29) unstable; urgency=medium
+
+ [ Linn Crosetto ]
+ * Clean up docs, mpi, and other files (closes: #798607).
+
+ [ dann frazier ]
+ * progress: avoid NULL dereference for net files. (LP: #1459872)
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 13 Oct 2015 23:36:46 +0100
+
+grub2 (2.02~beta2-28) unstable; urgency=medium
+
+ * Reduce the CFLAGS -O3 default on Ubuntu ppc64el to -O2; it introduces
+ various -Werror failures and isn't worth it here.
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 06 Sep 2015 01:25:56 +0100
+
+grub2 (2.02~beta2-27) unstable; urgency=medium
+
+ [ Felix Zielcke ]
+ * Remove Robert Millan from Uploaders with his permission. Thanks for
+ all the work he did for GRUB 2!
+ * Stop forcing gcc-4.9 for building.
+ * Update to Policy 3.9.6.
+ * Update the Browser URL for our git repository.
+ * Use dpkg-buildflags at least for the host binaries.
+ * Simplify Build-Depends.
+
+ [ Colin Watson ]
+ * Go back to forcing a particular compiler version, but this time gcc-5.
+ The reason for this is that new compiler versions often make slight
+ changes to the size of compiled code which break delicate parts of GRUB,
+ and we want to make sure that we test newer versions before switching to
+ them.
+ * Make builds that are not limited to architecture-dependent packages
+ (i.e. dpkg-buildpackage -b) work on non-x86 architectures (closes:
+ #744954).
+
+ [ Mathieu Trudel-Lapierre ]
+ * debian/build-efi-images: Look for grub.cfg in $cmdpath too in
+ gcdx64.efi, to simplify embedded scenarios: putting a grub.cfg snippet
+ that loads the right "real" grub.cfg can be useful. (LP: #1468111)
+ * debian/patches/uefi_firmware_setup.patch: Take into account that the
+ UEFI variable OsIndicationsSupported is a bit field, and as such should
+ be compared as hex values in 30_uefi-firmware.in. (LP: #1456911)
+ * Update quick boot logic to handle abstractions for which there is no
+ write support. (LP: #1274320)
+
+ [ dann frazier ]
+ * d/p/arm64-set-correct-length-of-device-path-end-entry.patch: Fixes
+ booting arm64 kernels on certain UEFI implementations. (LP: #1476882)
+
+ [ Debconf translations ]
+ * [lv] Latvian (Rudolfs Mazurs; closes: #777648).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 04 Sep 2015 12:35:59 +0100
+
+grub2 (2.02~beta2-26) unstable; urgency=medium
+
+ [ William Grant ]
+ * Fix linuxefi module to be included on x86_64-efi rather than amd64-efi.
+ amd64-efi isn't a thing. (LP: #1464959)
+
+ [ Steven Chamberlain ]
+ * Recognise Xen xbd and KVM virtio disks on kFreeBSD (closes: #786621).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 14 Jun 2015 10:02:19 +0100
+
+grub2 (2.02~beta2-25) unstable; urgency=medium
+
+ * Build-depend on dosfstools and mtools on arm64 as well as amd64.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 12 Jun 2015 12:29:19 +0100
+
+grub2 (2.02~beta2-24) unstable; urgency=medium
+
+ [ Mathieu Trudel-Lapierre ]
+ * Fix handling of --disk-module option (cherry-pick from fa335308).
+ (Closes: #746596, LP: #1309735)
+ * Fix double-free of LV names for mdraid (cherry-pick from fc535b32).
+ (LP: #1330963)
+
+ [ dann frazier ]
+ * Build image tarball on arm64
+ * Only include linuxefi module in images for amd64. This module doesn't
+ exist on other platforms like arm64, where GRUB chainloads to the kernel
+ EFI stub.
+
+ [ Paulo Flabiano Smorigo ]
+ * powerpc: Add a flag to avoid unnecessary optimizations (like vsx)
+ (LP: #1459706).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 11 Jun 2015 17:08:09 +0100
+
+grub2 (2.02~beta2-23) unstable; urgency=medium
+
+ [ Debconf translations ]
+ * [da] Danish (Joe Dalton; closes: #781333).
+
+ [ Felix Zielcke ]
+ * Run the tests with LC_MESSAGES=C.UTF-8. Some tests fail with non
+ english locale. (Closes: #782580)
+
+ [ Mathieu Trudel-Lapierre ]
+ * Backport from upstream:
+ - arp, icmp: Fix handling in case of oversized or invalid packets.
+ (LP: #1428005)
+
+ [ Robie Basak ]
+ * Change the default GRUB_RECORDFAIL_TIMEOUT to 30, so interactive users
+ still get the opporunity to intervene after a real boot failure, but
+ headless users will not end up stuck after boot failures that were
+ really power failures (closes: #782552, LP: #1443735).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 14 May 2015 16:18:33 +0100
+
+grub2 (2.02~beta2-22) unstable; urgency=medium
+
+ * Make grub-common's Suggests on grub-emu architecture-specific, to
+ quieten debcheck.
+ * Remove unnecessary feature test macros from hostfs, to fix building with
+ glibc 2.20.
+ * Backport from upstream:
+ - Fix UEFI boot failure with some firmware that returns incorrect paths
+ (closes: #735960).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 23 Mar 2015 15:30:15 +0000
+
+grub2 (2.02~beta2-21) unstable; urgency=medium
+
+ [ Mathieu Trudel-Lapierre ]
+ * Fix overlap check in check_blocklists for load_env (backported patch
+ from upstream commit 1f6af2a9; LP: #1311247).
+
+ [ Steve McIntyre ]
+ * Add support for running a 64-bit Linux kernel on a 32-bit EFI (closes:
+ #775202).
+
+ [ Colin Watson ]
+ * Use mtmsr rather than mtmsrd in ppc64el-disable-vsx.patch, since the
+ "VSX Available" bit is in the lower half of the MSR anyway, and mtmsrd
+ faults on 32-bit systems (closes: #776400).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 27 Jan 2015 20:37:04 +0000
+
+grub2 (2.02~beta2-20) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Generate alternative init entries in advanced menu (closes: #757298,
+ #773173).
+ * When configuring grub-pc, copy unicode.pf2 to /boot/grub/ even if
+ /boot/grub/grub.cfg does not exist yet; this matches the behaviour of
+ grub-efi-* (thanks, Luca Capello; closes: #617196).
+
+ [ Debconf translations ]
+ * [fi] Finnish (Timo Jyrinki; closes: #774060).
+ * [mr] Marathi (sampada nakhare; closes: #773901).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 03 Jan 2015 12:39:52 +0000
+
+grub2 (2.02~beta2-19) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Handle case insensitivity of VFAT filesystem on /boot/EFI when installing
+ extra cpoy of grub-efi to the removable media path
+ /boot/efi/EFI/BOOT/BOOT$ARCH.EFI (Closes: #773092)
+ * Make the force_efi_extra_removable debconf prompt only show up when
+ configuring grub-*efi*. Closes: #773004
+
+ [ Ian Campbell ]
+ * Improvements to English wording of new debconf template from Justin B Rye.
+ * Add debian/README.source.
+
+ [ Debconf translations ]
+ * [eu] Basque (Iñaki Larrañaga Murgoitio, Closes: #772946)
+ * [be] Belarusian (Viktar Siarheichyk, Closes: #773054)
+ * [pt_BR] Brazilian Portuguese (Adriano Rafael Gomes, Closes: #773682)
+ * [bg] Bulgarian (Damyan Ivanov, Closes: #772878)
+ * [cs] Czech (Miroslav Kure, Closes: #772924)
+ * [nl] Dutch (Frans Spiesschaert, Closes: 773637)
+ * [eo] Esperanto (Felipe Castro, Closes: #773096)
+ * [fi] Finnish (Timo Jyrinki, Closes: #772921)
+ * [fr] French (Christian PERRIER, Closes: #772771)
+ * [de] German (Martin Eberhard Schauer, Closes: #773664)
+ * [el] Greek (Panagiotis Georgakopoulos, Closes: #773068)
+ * [he] Hebrew (Omer Zak, Closes: #773377)
+ * [is] Icelandic (Sveinn í Felli, Closes: #772922)
+ * [it] Italian (Luca Monducci, Closes: #773553)
+ * [kk] Kazakh (Baurzhan Muftakhidinov, Closes: #772916)
+ * [lt] Lithuanian (Rimas Kudelis, Closes: #773060)
+ * [pl] Polish (Åukasz Dulny, Closes: #772930)
+ * [ro] Romanian (Andrei POPESCU, Closes: #773349)
+ * [ru] Russian (Yuri Kozlov, Closes: #773211)
+ * [sl] Slovenian (Vanja Cvelbar, Closes: #773508)
+ * [es] Spanish (Manuel "Venturi" Porras Peralta, Closes: #773222)
+ * [sv] Swedish (Martin Bagge & Anders Jonsson, Closes: 773208)
+ * [th] Thai (Theppitak Karoonboonyanan, Closes: #773160)
+ * [zh_TW] Traditional Chinese (Vincent W. Chen, Closes: #773418)
+ * [tr] Turkish (Mert Dirik, Closes: #773666)
+
+ -- Ian Campbell <ijc@debian.org> Mon, 22 Dec 2014 11:55:33 +0000
+
+grub2 (2.02~beta2-18) unstable; urgency=medium
+
+ [ Steve McIntyre ]
+ * Add support for forcing an extra copy of grub-efi to the removable
+ media path /boot/efi/EFI/BOOT/BOOT$ARCH.EFI (#767037)
+
+ [ Ian Campbell ]
+ * Add myself to Uploaders.
+
+ -- Ian Campbell <ijc@debian.org> Mon, 08 Dec 2014 08:38:38 +0000
+
+grub2 (2.02~beta2-17) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Fix up some pointer-to-integer casts in linuxefi so that it can build on
+ i386-efi.
+ * Backport from upstream:
+ - Fix typo (gettext_print instead of gettext_printf) (LP: #1390766).
+
+ [ Ian Campbell ]
+ * Correct syntax error in grub-xen-host bootstrap configuration file.
+ * Log failure when grub-install fails in postinst, rather than failing the
+ entire postinst. (Closes: #770412)
+ * Arrange to insmod xzio and lzopio when booting a kernel as a Xen guest.
+ (Closes: #755256)
+
+ -- Ian Campbell <ijc@debian.org> Sun, 30 Nov 2014 17:15:21 +0000
+
+grub2 (2.02~beta2-16) unstable; urgency=medium
+
+ [ Ian Campbell ]
+ * Provide prebuilt grub-xen binaries for host use in a new grub-xen-host
+ package.
+ * Build/Install binaries into /boot/xen when installing grub-xen.
+
+ -- Ian Campbell <ijc@debian.org> Thu, 06 Nov 2014 13:32:01 +0000
+
+grub2 (2.02~beta2-15) unstable; urgency=medium
+
+ * Disable nvram installation again on chrp_ibm machines that are emulated
+ by qemu; that doesn't have nvram devices so the nvram utility inevitably
+ fails.
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 15 Oct 2014 21:34:02 +0100
+
+grub2 (2.02~beta2-14) unstable; urgency=medium
+
+ * On architectures without a real GRUB port, just build the utilities.
+ This makes tools such as grub-probe and grub-fstest available
+ everywhere, and makes grub-mount available on all Linux and kFreeBSD
+ architectures.
+ * Remove .MIPS.abiflags section from images (thanks, Jurica Stanojkovic,
+ although I used a slightly simpler approach; closes: #762307).
+ * Include a text attribute reset in the clear command for ppc
+ (LP: #1295255).
+ * Disable VSX instruction on powerpc startup to fix booting on ppc64el.
+ * Stop adding a CHRP note on chrp_ibm machines, since that apparently
+ breaks PowerVM and isn't needed on other machine types as far as we can
+ tell (LP: #1334793).
+ * Refactor flicker-free-boot configuration in debian/rules to reduce
+ duplication.
+ * Disable flicker-free-boot on Ubuntu ppc64el for now, as it isn't needed
+ there and causes too many problems (LP: #1338471).
+ * Use nvram rather than nvsetenv on chrp_ibm machines, since that tool is
+ better-supported and copes with such things as nvram being missing in
+ qemu.
+ * Remove brace-expansion from the postrm, and switch the preinst and
+ postrm to /bin/sh (closes: #762940).
+ * On ppc64el, look for a PReP partition and install the core image to the
+ first one if found. For now this is done by borrowing prep-bootdev.c
+ from grub-installer, incurring a dependency on libparted.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 26 Sep 2014 18:05:15 +0100
+
+grub2 (2.02~beta2-13) unstable; urgency=medium
+
+ * Drop gcc-4.9-multilib build-dependency on ppc64el again.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 19 Sep 2014 20:30:31 +0100
+
+grub2 (2.02~beta2-12) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Point Vcs-* fields back at master.
+ * Support grub-emu on x32 (closes: #760428).
+ * Adjust packaging for x32:
+ - Build-depend on cpio on x32 as well.
+ - Make grub-efi-ia32-bin and grub-efi-amd64-bin depend on efibootmgr on
+ any Linux architecture for which they are built (in practice, adding
+ x32).
+ - Build grub-mount-udeb on x32 as well.
+ - Add Lintian binary-from-other-architecture overrides where
+ appropriate.
+ * Apply patches from Paulo Flabiano Smorigo to allow building a 32-bit
+ big-endian loader on ppc64el using -m32 -mbig-endian, replacing the
+ cross-compiler hack.
+
+ [ Ian Campbell ]
+ * Add dependency on efibootmgr to grub-efi-{arm,arm64}-bin.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 19 Sep 2014 15:19:26 +0100
+
+grub2 (2.02~beta2-11) unstable; urgency=medium
+
+ * Force grub-pc/mixed_legacy_and_grub2 to be reshown, rather than failing
+ when it was already seen (closes: #749571).
+ * Build with GCC 4.9 (closes: #748003).
+ * Build for sparc64 (closes: #753784).
+ * Fix an infinite loop in grub-mkconfig when kernel paths contain regex
+ metacharacters. Thanks to Heimo Stranner for the report.
+ * On upgrade, if we find that one of the install devices no longer exists,
+ ask the debconf question at priority critical rather than high.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 24 Jul 2014 09:11:31 +0100
+
+grub2 (2.02~beta2-10) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Add the true module to the signed image, since 05_debian_theme uses it.
+ Thanks to Dimitri John Ledkov for the report.
+ * Limit test suite parallelisation to 1; the test suite seems to have some
+ isolation problems at higher levels at the moment (closes: #746856).
+ * Simplify override_dh_install a bit.
+ * Backport patches from upstream to make the network stack more responsive
+ on busy networks (LP: #1314134).
+
+ [ Dimitri John Ledkov ]
+ * Add support for nvme device in grub-mkdevicemap (closes: #746396,
+ LP: #1275162).
+
+ [ Debconf translations ]
+ * Korean (Changwoo Ryu, closes: #745559).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 08 May 2014 11:13:48 +0100
+
+grub2 (2.02~beta2-9) unstable; urgency=medium
+
+ * Backport from upstream:
+ - Tolerate devices with no filesystem UUID returned by os-prober
+ (LP: #1287436).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 10 Apr 2014 17:34:44 +0100
+
+grub2 (2.02~beta2-8) unstable; urgency=medium
+
+ [ Colin Watson ]
+ * Backport from upstream:
+ - ieee1275: check for IBM pseries emulated machine.
+ - Fix partmap, cryptodisk, and abstraction handling in grub-mkconfig
+ (closes: #735935).
+ - btrfs: fix get_root key comparison failures due to endianness.
+ * Build-depend on automake (>= 1.10.1) to ensure that it meets configure's
+ requirements (LP: #1299041).
+ * When installing an image for use with UEFI Secure Boot, generate a
+ load.cfg even if there are no device abstractions in use (LP: #1298399).
+
+ [ Jon Severinsson ]
+ * Add Tanglu support, as in Debian except:
+ - Enable splash screen by default (as Ubuntu)
+ - Enable quiet and quick boot (as Ubuntu)
+ - Enable the grub-common init script (as Ubuntu)
+ - Enable dynamic gfxpayload (as Ubuntu)
+ - Enable vt handover (as Ubuntu)
+ - Use monochromatic theme by default (as Ubuntu)
+ - Use Tanglu GRUB wallpaper by default.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 31 Mar 2014 16:30:37 +0100
+
+grub2 (2.02~beta2-7) experimental; urgency=medium
+
+ * Fix shift-held-down test not to clear other modifier key states
+ (LP: #843804).
+ * Explicitly pass an appropriate --target to grub-install in the postinst
+ (suggested by Jordan Uggla).
+ * Backport from upstream:
+ - Use bootaa64.efi instead of bootaarch64.efi on arm64 to comply with
+ EFI specification. Also use grubaa64.efi for consistency.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 10 Mar 2014 13:39:33 +0000
+
+grub2 (2.02~beta2-6) experimental; urgency=medium
+
+ * Install bootinfo.txt and grub.chrp into grub-ieee1275-bin on powerpc and
+ ppc64el.
+ * Port yaboot logic to improve installation for various powerpc machine
+ types.
+ * Improve parsing of /etc/default/grub.d/*.cfg in C utilities
+ (LP: #1273694).
+ * Run grub-install on install or upgrade on grub-ieee1275/ppc64el.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 28 Jan 2014 23:50:55 +0000
+
+grub2 (2.02~beta2-5) experimental; urgency=medium
+
+ * Add a number of EFI debugging commands to the signed image (lsefi,
+ lsefimmap, lsefisystab, lssal).
+ * Add gfxterm_background to the signed image so that background_image
+ works in UEFI Secure Boot mode. Thanks to syscon-hh for the report.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 27 Jan 2014 10:03:00 +0000
+
+grub2 (2.02~beta2-4) experimental; urgency=medium
+
+ * Remove redundant build-dependencies on autoconf and automake, covered by
+ dh-autoreconf.
+ * In --enable-quick-boot mode, restore previous behaviour of using a
+ hidden timeout if GRUB_HIDDEN_TIMEOUT=0 (thanks to Sebastien Bacher for
+ the report).
+ * Disable cpio test on kFreeBSD again for now; it fails within cpio itself
+ with "field width not sufficient for storing rdev minor".
+ * Copy shim.efi.signed to the correct path in UEFI Secure Boot mode.
+ Thanks to syscon-hh for the report.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 20 Jan 2014 15:53:36 +0000
+
+grub2 (2.02~beta2-3) experimental; urgency=medium
+
+ * Pass VERBOSE=1 when running tests so that Automake will print test logs
+ on failure.
+ * Adjust Vcs-* fields to indicate the experimental branch.
+ * Build-depend on cpio on architectures where we run the test suite, for
+ tests/cpio_test.in.
+ * Ignore EPERM when modifying kern.geom.debugflags on FreeBSD, fixing
+ tests.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 17 Jan 2014 10:50:40 +0000
+
+grub2 (2.02~beta2-2) experimental; urgency=medium
+
+ * Convert patch handling to git-dpm.
+ * Add bi-endian support to ELF parser (Tomohiro B Berry).
+ * Adjust restore_mkdevicemap.patch to mark get_kfreebsd_version as static,
+ to appease "gcc -Werror=missing-prototypes".
+ * Cherry-pick from upstream:
+ - Change grub-macbless' manual page section to 8.
+ * Install grub-glue-efi, grub-macbless, grub-render-label, and
+ grub-syslinux2cfg.
+ * grub-shell: Pass -no-pad to xorriso when building floppy images.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 16 Jan 2014 15:18:04 +0000
+
+grub2 (2.02~beta2-1) experimental; urgency=low
+
+ * New upstream beta release.
+ * Drop qemu-utils build-dependency; the test suite no longer uses
+ qemu-img.
+ * Build grub-common, grub2-common, grub-themes-starfield, and grub-mount
+ on ARM and ARM64 architectures.
+ * Install grub-mkrescue in grub-common on all architectures.
+ * Make grub-efi-ia32, grub-efi-amd64, and grub-efi-ia64 conflict with
+ elilo.
+ * Adjust the postinst of grub-efi-ia64, grub-efi-arm, and grub-efi-arm64
+ to keep the EFI System Partition up to date with grub-install after it
+ has been run once, like grub-efi-ia32 and grub-efi-amd64 already do.
+ * Regularise indentation of "recordfail" in /etc/grub.d/10_linux.
+ * Add alpha.gnu.org to debian/watch, for pre-releases.
+ * Add OpenPGP signature checking configuration to watch file.
+ * Drop mkconfig_skip_dmcrypt.patch; it breaks GRUB_ENABLE_CRYPTODISK=y,
+ which is a better fix for the original problem (closes: #732245).
+ * Fix mismerge of mkconfig_loopback.patch.
+ * Build for ppc64el, using a powerpc cross-compiler at least for now.
+ * Don't run gettext_strings_test; this test is mainly useful as an
+ upstream maintenance check.
+ * Silence warning if /usr/share/locale-langpack does not exist (closes:
+ #732595).
+ * Remove debian/grub-common.preinst, superseded by .maintscript files.
+ * Install grub-file in grub-common.
+ * Fix crash due to pointer confusion in grub-mkdevicemap, introduced while
+ converting away from nested functions in 2.00+20131208-1.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 26 Dec 2013 00:52:47 +0000
+
+grub2 (2.00+20131208-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - Skip issuing cursor on/off sequences on Macs (closes: #683068).
+ - Move grub-mknetdir to /usr/bin (closes: #688799).
+ - Apply program name transformations at build-time rather than at
+ run-time (closes: #696465).
+ - Add info documentation for grub-mount (closes: #666427).
+ - Clean up dangling references to grub-setup (LP: #1082045).
+ - Avoid installing to sectors matching the signature of an Acer
+ registration utility with several sightings in the wild (LP: #987022).
+ - Document the need for GRUB_DEFAULT=saved in grub-set-default(8)
+ (LP: #1102925).
+ - Fix missing PVs if they don't contain an "interesting" LV (probably
+ closes: #650724, #707613).
+ - Reimplement grub-reboot to not depend on saved_entry (closes: #707695,
+ LP: #704406).
+ - Fix Ctrl-u handling to copy the killed characters to the kill buffer
+ as UCS4 stored as grub_uint32_t rather than as 8-bit characters stored
+ as char (closes: #710076).
+ - Fix inconsistent use of GRUB_CRYPTODISK_ENABLE and
+ GRUB_ENABLE_CRYPTODISK (LP: #1232237).
+ - Support GRUB_DISABLE_SUBMENU configuration, and document submenu usage
+ in grub-reboot(8) (closes: #690538).
+ - Don't decompress initrd when booting with Xen (closes: #700197).
+ - Document how to delete the whole environment block (closes: #726265).
+ - Revamp hidden timeout handling by adding a new timeout_style
+ environment variable and a corresponding GRUB_TIMEOUT_STYLE
+ configuration key for grub-mkconfig. This controls hidden-timeout
+ handling more simply than the previous arrangements, and pressing any
+ hotkeys associated with menu entries during the hidden timeout will
+ now boot the corresponding menu entry immediately (LP: #1178618). As
+ part of merging this, radically simplify the mess that
+ quick_boot.patch had made of /etc/grub.d/30_os-prober; if it finds
+ other OSes it can now just set timeout_style=menu and make sure the
+ timeout is non-zero.
+ - On Linux, read partition start offsets from sysfs if possible
+ (LP: #1237519).
+ - New ports to arm-uboot, arm-efi, arm64-efi, i386-xen, and x86_64-xen.
+ * Add grub-uboot*, grub-efi-arm*, and grub-xen* binary packages.
+ * Ignore functional test failures for now as they are broken.
+ * Move working directories around (build/<package> -> obj/<package>,
+ build/stamps -> debian/stamps) so that "debian/rules build" still works
+ after working directories have been created.
+ * Drop "grub-mkrescue --diet" option; never merged upstream and only
+ matters for floppies. Please let me know if you were using this.
+ Explicitly use -no-pad to build grub-rescue-floppy.img, which has an
+ equivalent effect on size.
+ * Break lupin-support (<< 0.55) due to the rewrite of grub-install in C.
+ * Remove build-dependency on autogen, no longer needed.
+ * Compress GRUB files on grub-rescue-floppy.img using xz.
+ * Build-depend on wamerican, newly required by the test suite.
+ * Run tests with LC_CTYPE=C.UTF-8, so that grub-fs-tester can handle UTF-8
+ data correctly.
+ * Update debian/legacy/update-grub to the version from grub 0.97-67.
+ * Silence error message on initial installation when /etc/default/grub
+ does not yet exist.
+ * Add GRUB_RECOVERY_TITLE option, to allow the controversial "recovery
+ mode" text to be customised (LP: #1240360).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 09 Dec 2013 00:21:45 +0000
+
+grub2 (2.00-20) unstable; urgency=low
+
+ * Backport from upstream:
+ - Sort gnumach kernels in version order (closes: #725451).
+ * Move packaging to git, following upstream. Adjust Vcs-* fields.
+ * Remove obsolete DM-Upload-Allowed field.
+ * Merge (completely!) from Ubuntu:
+ - Handle probing striped DM-RAID devices (thanks, Robert Collins;
+ LP: #803658).
+ - Unconditionally create grub.cfg on our EFI boot partition in Secure
+ Boot mode; GRUB always needs some configuration in this case to find
+ /boot/grub, since we can't modify the signed image at install time
+ (Steve Langasek, LP: #1236625).
+ - If MokManager is present on the host system, copy it onto the EFI boot
+ partition for use (Steve Langasek).
+ - Adjust UEFI installation to cope with Kubuntu setting GRUB_DISTRIBUTOR
+ (LP: #1242417).
+ - If building for Ubuntu:
+ + Bypass menu unless other OSes are installed or Shift is pressed.
+ + Show the boot menu if the previous boot failed.
+ + Set GRUB_GFXPAYLOAD_LINUX=keep unless it's known to be unsupported
+ on the current hardware.
+ + Set vt.handoff=7 for smooth handoff to kernel graphical mode.
+ + In recovery mode, add nomodeset to the Linux kernel arguments, and
+ remove the 'set gfxpayload=keep' command.
+ + Set default timeout to 10 seconds.
+ + Enable hidden timeout support by default.
+ - Migrate timeout settings from menu.lst.
+ - Probe FusionIO devices (LP: #1237519).
+ * Make grub.cfg world-unreadable if even hashed passwords are in use
+ (closes: #632598).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 14 Nov 2013 10:49:31 +0000
+
+grub2 (2.00-19) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Merge from Ubuntu:
+ - debian/build-efi-images: Where possible, make use of the device path
+ derived from the EFI Loaded Image Protocol to compute the prefix
+ (LP: #1097570).
+ - debian/build-efi-images: Add a netboot image target to our set of
+ prebuilt EFI images (thanks, Steve Langasek).
+ * Backport from upstream:
+ - Handle partitions on non-512B EFI disks (LP: #1065281).
+
+ [ Phillip Susi ]
+ * restore_mkdevicemap.patch: Fix dmraid uuid check to look for "DMRAID-"
+ anywhere instead of only at the start, since kpartx prefixes it with
+ "partN-" (LP: #1183915).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 18 Sep 2013 17:18:27 +0100
+
+grub2 (2.00-18) unstable; urgency=low
+
+ * Add gettext module to signed UEFI images (LP: #1104627).
+ * Put the preprocessor definition for quiet-boot in the right place so
+ that it actually takes effect.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 26 Aug 2013 17:23:09 +0100
+
+grub2 (2.00-17) unstable; urgency=low
+
+ * Really include patches to reduce visual clutter in normal mode when
+ building for Ubuntu.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 15 Aug 2013 09:58:59 +0100
+
+grub2 (2.00-16) unstable; urgency=low
+
+ * Make reportbug script file robust against su authentication failures and
+ missing LVM commands.
+ * Backport from upstream:
+ - Move @itemize after @subsection to satisfy texinfo-5.1.
+ - grub-mkconfig: Fix detection of Emacs autosave files.
+ - Fix spurious failure on Xen partition devices without disk devices
+ (closes: #708614).
+ * Merge from Ubuntu:
+ - Treat Kubuntu as an alias for Ubuntu in GRUB_DISTRIBUTOR (Harald
+ Sitter).
+ - Make any EFI system boot into the shim (if installed) even if
+ SecureBoot is disabled (Stéphane Graber).
+ - Allow Shift to interrupt 'sleep --interruptible'.
+ - If building for Ubuntu:
+ + Reduce visual clutter in normal mode.
+ + Remove verbose messages printed before reading configuration.
+ + Suppress kernel/initrd progress messages, except in recovery mode.
+ + Suppress "GRUB loading" message unless Shift is held down.
+ - Skip Windows os-prober entries on Wubi systems.
+ * Consolidate debian/rules logic for when to build signed images.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 15 Aug 2013 08:35:53 +0100
+
+grub2 (2.00-15) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Install reportbug presubj and script files in all binary packages.
+ * Make grub-yeeloong.postinst explicitly install with
+ --target=mipsel-loongson (closes: #708204).
+ * Make grub-script-check fail on scripts containing no commands (closes:
+ #713886).
+ * Make the description of grub-firmware-qemu a little more generic, rather
+ than assuming that bochsbios provides qemu's default BIOS image (closes:
+ #714277).
+ * Don't assume that the presence of /etc/default/grub or
+ /etc/default/grub.d/*.cfg means that any particular item is set in it
+ (LP: #1199731).
+
+ [ Debconf translations ]
+ * Hungarian (Dr. Nagy Elemér Károly).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 13 Jul 2013 11:04:15 +0100
+
+grub2 (2.00-14) unstable; urgency=low
+
+ * Merge from Ubuntu:
+ - Don't call update-grub in the zz-update-grub kernel hook if
+ /boot/grub/grub.cfg doesn't exist.
+ - acpihalt: expand parser to handle SSDTs and some more opcodes. Fixes
+ test suite hang with current seabios.
+ * Remove kernel-specific grub.d conffiles that were dropped from packages
+ built for all but their corresponding kernel type in 1.96+20090307-1
+ (closes: #703539).
+ * Look for grub-bios-setup in /usr/lib/grub/i386-pc/ as well (closes:
+ #705636).
+ * Merge 1.99-27.1 (thanks, Steve McIntyre):
+ - Add entries for Windows Boot Manager found via UEFI in os-prober
+ (closes: #698914).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 09 May 2013 00:14:55 +0100
+
+grub2 (2.00-13) experimental; urgency=low
+
+ * Backport from upstream:
+ - Fix booting FreeBSD >= 9.1 amd64 kernels (closes: #699002).
+ * Merge from Ubuntu:
+ - Stop using the /usr/share/images/desktop-base/desktop-grub.png
+ alternative as the fallback background if GRUB_DISTRIBUTOR is
+ "Ubuntu".
+ - source_grub2.py: Use attach_default_grub from apport's hookutils.
+ - Output a menu entry for firmware setup on UEFI FastBoot systems.
+ - Set a monochromatic theme and an appropriate background for Ubuntu.
+ - Remove "GNU/Linux" from default distributor string for Ubuntu.
+ - Apply Ubuntu GRUB Legacy changes to legacy update-grub script.
+ - Apply patch from Fedora to add a "linuxefi" loader which boots kernels
+ with EFI handover patches, avoiding ExitBootServices.
+ - Temporarily make linuxefi refuse to validate kernels in the absence of
+ a shim, until we get some other details worked out.
+ - Automatically call linuxefi from linux if secure boot is enabled and
+ the kernel is signed, to hand over to the kernel without calling
+ ExitBootServices. Otherwise, linux will fall through to previous
+ code, call ExitBootServices itself, and boot the kernel normally.
+ - Generate configuration for signed UEFI kernels if available.
+ - On Ubuntu amd64, add a raw-uefi custom upload tarball for signing.
+ - Install signed images if available and UEFI Secure Boot is enabled.
+ - Add "splash" to default boot options on Ubuntu.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 01 Feb 2013 15:44:25 +0000
+
+grub2 (2.00-12) experimental; urgency=low
+
+ * Silence output from running-in-container.
+ * Also skip update-grub when running in a container (LP: #1060404).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 24 Jan 2013 23:21:48 +0000
+
+grub2 (2.00-11) experimental; urgency=low
+
+ [ Adam Conrad ]
+ * debian/{postinst,config}.in: Don't fail if /etc/default/grub.d
+ configuration snippets exist, but /etc/default/grub does not.
+
+ [ Colin Watson ]
+ * Merge wheezy branch up to 1.99-27, fixing overzealous removal of
+ load_video call when GRUB_GFXPAYLOAD_LINUX is empty (closes: #661789).
+ * Merge from Ubuntu:
+ - If the postinst is running in a container, skip grub-install and all
+ its associated questions (LP: #1060404).
+ - Fix backslash-escaping in merge_debconf_into_conf (LP: #448413). Note
+ that this differs slightly from the fix in Ubuntu, which corrected
+ behaviour when amending an existing configuration item but
+ accidentally over-escaped when adding a new one.
+ - Replace "single" with "recovery" when friendly-recovery is installed
+ (LP: #575469).
+ - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
+ Ubuntu's backport of the grub-doc split (LP: #493968).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 21 Jan 2013 10:49:00 +0000
+
+grub2 (2.00-10) experimental; urgency=low
+
+ * Support parallel builds.
+ * Remove /boot/grub/unicode.pf2 on purge of grub-efi-{amd64,i386} (closes:
+ #697183).
+ * Build with GCC 4.7.
+ * Merge from Ubuntu:
+ - Don't permit loading modules on UEFI Secure Boot (since in such a
+ setup the GRUB core image must be signed but it has no provision for
+ verifying module signatures).
+ - Read /etc/default/grub.d/*.cfg after /etc/default/grub (LP: #901600).
+ - Blacklist 1440x900x32 from VBE preferred mode handling until a better
+ solution is available (LP: #701111).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 03 Jan 2013 09:38:25 +0000
+
+grub2 (2.00-9) experimental; urgency=low
+
+ * Ensure /boot/grub exists before copying files to it for EFI installs
+ (closes: #696962).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 29 Dec 2012 23:44:51 +0000
+
+grub2 (2.00-8) experimental; urgency=low
+
+ * debian/apport/source_grub2.py:
+ - Use context managers to avoid (harmless) file descriptor leaks.
+ - Set a file encoding, per PEP 0263.
+ * Drop grub-ieee1275-bin's dependency on bc in favour of powerpc-ibm-utils
+ (>= 1.2.12-1) (cf. #625728).
+ * Move powerpc-ibm-utils and powerpc-utils dependencies from
+ grub-ieee1275-bin to grub-ieee1275 (closes: #693400).
+ * Merge from Ubuntu:
+ - Ignore symlink traversal failures in grub-mount readdir
+ (LP: #1051306).
+ - Fix incorrect initrd minimum address calculation (LP: #1055686).
+ - Avoid assuming that gets is declared.
+ * Copy unicode.pf2 to /boot/grub/ for EFI installs so that it is more
+ likely to be readable by GRUB (closes: #661789).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 28 Dec 2012 17:34:32 +0000
+
+grub2 (2.00-7) experimental; urgency=low
+
+ * Backport from upstream:
+ - Fix stderr leakage from grub-probe in is_path_readable_by_grub.
+ - Fix tftp endianness problem.
+ * Merge from Ubuntu:
+ - Prefer translations from language packs (LP: #537998). (No-op for
+ Debian, but harmless.)
+ - Avoid getting confused by inaccessible loop device backing paths
+ (LP: #938724).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 26 Sep 2012 16:05:07 +0100
+
+grub2 (2.00-6) experimental; urgency=low
+
+ [ Colin Watson ]
+ * Adjust package descriptions to talk about update-grub, not update-grub2.
+ * Backport from upstream:
+ - Fix grub-emu build on FreeBSD.
+ * Revert gcc-4.6-multilib build-dependency change from 2.00-1, since
+ kfreebsd-i386 and hurd-i386 don't have gcc-4.6-multilib. Instead, make
+ sure to only install efiemu32.o and efiemu64.o on (linux-)i386,
+ kopensolaris-i386, and any-amd64.
+ * Manually expand @PACKAGE@ symbols in grub-efi.postinst (closes:
+ #688725), grub-linuxbios.postinst (closes: #688726), and grub2.postinst
+ (closes: #688724).
+
+ [ Debconf translations ]
+ * Lithuanian (Rimas Kudelis). Closes: #675628
+ * Galician (Jorge Barreiro). Closes: #677389
+ * Welsh (Daffyd Tomos).
+ * Greek (galaxico). Closes: #685201
+ * Romanian (Andrei POPESCU). Closes: #685477
+ * Finnish (Timo Jyrinki).
+
+ [ Cyril Brulebois ]
+ * Use xz compression for all binaries to save up some space on CD images
+ (closes: #688773).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 25 Sep 2012 22:47:03 +0100
+
+grub2 (2.00-5) experimental; urgency=low
+
+ * Backport from upstream:
+ - Remove extra layer of escaping from grub_probe.
+ - Add efifwsetup module to reboot into firmware setup menu.
+ - Revert incorrect off-by-one fix when embedding in MBR (LP: #1051154).
+ * Switch watch file to point to ftp.gnu.org.
+ * Build-depend on liblzma-dev, enabling 'grub-mkimage -C xz'.
+ * Adjust /etc/grub.d/30_os-prober to detect Ubuntu's use of "recovery"
+ rather than "single".
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 19 Sep 2012 08:52:27 +0100
+
+grub2 (2.00-4) experimental; urgency=low
+
+ * Fix platform postinsts to handle new core.img location.
+ * Only fix up powerpc key repeat on IEEE1275 machines. Fixes powerpc-emu
+ compilation.
+ * Move grub-install to grub2-common, since it's now common across
+ platforms but clashes with grub-legacy.
+ * Move grub-mknetdir to grub-common, since it's now common across
+ platforms.
+ * Make grub-install fall back to i386-pc if booted using EFI but the
+ relevant *-efi target is not available (because only grub-pc is
+ installed).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 14 Sep 2012 13:38:37 +0100
+
+grub2 (2.00-3) experimental; urgency=low
+
+ * Use dh-autoreconf.
+ * Bail out if trying to run grub-mkconfig during upgrade to 2.00 (e.g.
+ while configuring a kernel image), since the old /etc/grub.d/00_header
+ conffile breaks until such time as grub-common is configured.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 13 Sep 2012 17:07:18 +0100
+
+grub2 (2.00-2) experimental; urgency=low
+
+ * Add -Wno-error=unused-result to HOST_CFLAGS for the moment, since at
+ least grub-core/lib/crypto.c fails to compile on Ubuntu otherwise.
+ * Update default/grub.md5sum to include Ubuntu maverick's default md5sum.
+ * Autogenerate packaging files for grub-emu, in order that its postinst
+ does not contain unexpanded @PACKAGE@ symbols.
+ * Only try to install efiemu*.o into grub-emu on *-i386.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 08 Sep 2012 10:32:33 +0100
+
+grub2 (2.00-1) experimental; urgency=low
+
+ [ Jordi Mallach, Colin Watson ]
+ * New upstream release.
+ - Add LUKS and GELI encrypted disk support (closes: #463107).
+ - Lazy scanning to avoid accessing devices which aren't really used.
+ This avoids boot delay due to slow device scanning (closes: #549905,
+ #550015, #550083, #564252, #595059, #632408).
+ - Don't override more informative errors when loading kernel/initrd
+ (closes: #551630).
+ - Support 4K-sector NTFS (closes: #567728).
+ - Unify grub-mkrescue interface on powerpc with that on other
+ architectures (closes: #570119).
+ - Fix infinite recursion in gettext when translation fails (closes:
+ #611537, #612454, #616487, #619618, #626853, #643608).
+ - Add more missing quotes to grub-mkconfig (closes: #612417).
+ - Import gnulib change to fix argp_help segfault with help filter
+ (closes: #612692).
+ - Support %1$d syntax in grub_printf (closes: #630647).
+ - Use write-combining MTRR to speed up video with buggy BIOSes (closes:
+ #630926).
+ - Remove multiboot header from PXE images to avoid confusing ipxe
+ (closes: #635877).
+ - Fix crash when attempting to install to a non-BIOS disk (closes:
+ #637208).
+ - Fix handling of grub-mkrescue --xorriso= option (closes: #646788).
+ - Use umask rather than chmod to create grub.cfg.new to avoid insecure
+ grub.cfg (closes: #654599).
+ - Improve font installation logic (closes: #654645).
+ - Add grub-probe info documentation (closes: #666031).
+ - Don't crash on canonicalize_file_name failure in grub-probe (closes:
+ #677211).
+
+ [ Colin Watson ]
+ * Adjust debian/watch to point to xz-compressed tarballs.
+ * debian/grub.d/05_debian_theme: Source grub-mkconfig_lib from
+ /usr/share/grub, not the /usr/lib/grub compatibility link.
+ * Convert to source format 3.0 (quilt). Developers, note that patches are
+ stored applied in bzr; you may want to 'quilt pop -a' / 'quilt push -a'
+ around merges.
+ * Remove pointless debian/grub-mount-udeb.install.hurd-i386;
+ grub-mount-udeb is not built on the Hurd.
+ * Refactor debian/grub-common.install.hurd-i386 into .in files so that it
+ imposes less of a maintenance burden.
+ * Restore grub-mkdevicemap for now. While it's kind of a mess, requiring
+ lots of OS-specific code to iterate over all possible devices, we use it
+ in a number of scripts to discover devices and reimplementing those in
+ terms of something else would be very complicated.
+ * Add grub-efi-ia64-bin and grub-efi-ia64 packages. These are currently
+ experimental, and grub-efi-ia64 does not automatically run grub-install.
+ * Build-depend on gcc-4.6-multilib on kfreebsd-i386 and hurd-i386 as well
+ as the other i386 architectures, since we need it to build efiemu32.o
+ and efiemu64.o.
+ * Add per-platform *-dbg packages containing files needed to use GRUB's
+ GDB stub. These are relatively large and thus worth splitting out.
+ * Build-depend on ttf-dejavu-core for the starfield theme.
+ * Add a grub-theme-starfield package containing the starfield theme.
+ * Backport from upstream:
+ - Don't decrease efi_mmap_size (LP: #1046429).
+ * grub-common Suggests: console-setup for grub-kbdcomp (closes: #686815).
+ * Silence error messages when translations are unavailable.
+ * Don't pass *.module to dpkg-shlibdeps, avoiding lots of build-time
+ warnings.
+ * Move transitional package to Section: oldlibs.
+ * Acknowledge NMU (closes: #676609).
+
+ [ Debconf translations ]
+ * Lithuanian (Rimas Kudelis). Closes: #675628
+ * Galician (Jorge Barreiro). Closes: #677389
+ * Welsh (Daffyd Tomos).
+ * Greek (galaxico). Closes: #685201
+ * Romanian (Andrei POPESCU). Closes: #685477
+ * Finnish (Timo Jyrinki).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 06 Sep 2012 19:04:21 +0100
+
+grub2 (1.99-27.1) unstable; urgency=medium
+
+ * NMU
+ * Add entries for Windows Boot Manager found via UEFI in
+ os-prober. Closes: #698914 before the Wheezy release.
+
+ -- Steve McIntyre <93sam@debian.org> Fri, 26 Apr 2013 23:53:34 +0100
+
+grub2 (1.99-27) unstable; urgency=low
+
+ * Amend gfxpayload_keep_default.patch to no longer remove the call to
+ load_video when GRUB_GFXPAYLOAD_LINUX is empty (closes: #661789).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 20 Jan 2013 16:37:52 +0000
+
+grub2 (1.99-26) unstable; urgency=low
+
+ * Remove /boot/grub/unicode.pf2 on purge of grub-efi-{amd64,i386} (closes:
+ #697183).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 02 Jan 2013 11:54:50 +0000
+
+grub2 (1.99-25) unstable; urgency=low
+
+ * Ensure /boot/grub exists before copying files to it for EFI installs
+ (closes: #696962).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 29 Dec 2012 23:45:01 +0000
+
+grub2 (1.99-24) unstable; urgency=low
+
+ * Acknowledge NMU with thanks.
+ * Fix namespace of EFI boot failure patch file added in NMU.
+ * Copy unicode.pf2 to /boot/grub/ for EFI installs so that it is more
+ likely to be readable by GRUB (closes: #661789).
+ * Fix infinite recursion in gettext when translation fails (closes:
+ #611537, #612454, #616487, #619618, #626853, #643608).
+ * Fix grammar in Finnish translation (closes: #687681).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 28 Dec 2012 13:01:38 +0000
+
+grub2 (1.99-23.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Apply Ubuntu patch fixing some EFI boot failures (closes: #687320)
+ - Thanks to Colin Watson.
+
+ -- Michael Gilbert <mgilbert@debian.org> Sun, 14 Oct 2012 04:09:51 -0400
+
+grub2 (1.99-23) unstable; urgency=low
+
+ [ Debconf translations ]
+ * Lithuanian (Rimas Kudelis). Closes: #675628
+ * Galician (Jorge Barreiro). Closes: #677389
+ * Welsh (Daffyd Tomos).
+ * Greek (galaxico). Closes: #685201
+ * Romanian (Andrei POPESCU). Closes: #685477
+ * Finnish (Timo Jyrinki).
+
+ [ Cyril Brulebois ]
+ * Use xz compression for all binaries to save up some space on CD images
+ (closes: #688773).
+
+ [ Colin Watson ]
+ * Autogenerate packaging files for grub-emu (closes: #688727), in order
+ that its postinst does not contain unexpanded @PACKAGE@ symbols.
+ * Manually expand @PACKAGE@ symbols in grub-efi.postinst (closes:
+ #688725), grub-linuxbios.postinst (closes: #688726), and grub2.postinst
+ (closes: #688724).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 25 Sep 2012 18:59:18 +0100
+
+grub2 (1.99-22.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Apply upstream patches for hurd-i386:
+ - Test inode number (Closes: #634799).
+ - Disable zfs code on GNU/Hurd (Closes: #670069).
+ - Add userland partition support (Closes: #670186).
+ * Fix packages build without libfuse (Closes: #670189).
+
+ -- Samuel Thibault <sthibault@debian.org> Fri, 08 Jun 2012 01:19:00 +0200
+
+grub2 (1.99-22) unstable; urgency=low
+
+ [ Debconf translations ]
+ * Khmer added (Khoem Sokhem)
+ * Slovenian (Vanja Cvelbar). Closes: #670616
+ * Traditional Chinese (Vincent Chen).
+ * Vietnamese (Hai Lang).
+ * Marathi (Sampada Nakhare)
+ * Finnish (Timo Jyrinki). Closes: #673976
+ * Latvian (RÅ«dolfs Mazurs). Closes: #674697
+
+ [ Colin Watson ]
+ * Make apport hook compatible with Python 3.
+ * Add upstream r3476 (fix memory leak in grub_disk_read_small) to
+ 4k_sectors.patch, otherwise the larger disk cache due to
+ efi_disk_cache.patch can cause EFI systems to run out of memory.
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 30 May 2012 10:38:40 +0100
+
+grub2 (1.99-21) unstable; urgency=low
+
+ * Backport from upstream:
+ - Fix hook calling for unaligned segments (closes: #666992,
+ LP: #972250).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 03 Apr 2012 14:19:18 +0100
+
+grub2 (1.99-20) unstable; urgency=low
+
+ * Backport kFreeBSD support from upstream to 4k_sectors.patch.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 02 Apr 2012 21:53:02 +0100
+
+grub2 (1.99-19) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Add grub-probe to grub-mount-udeb (LP: #963471).
+ * Backport from upstream:
+ - Restore CFLAGS after efiemu check (closes: #665772).
+ - Include __ctzdi2 and __ctzsi2 from libgcc if present (closes:
+ #665993).
+ - Support non-512B sectors and agglomerate reads.
+
+ [ Debconf translations ]
+ * Croatian (Tomislav Krznar).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 02 Apr 2012 18:26:09 +0100
+
+grub2 (1.99-18) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Ensure that /sbin and /usr/sbin are in $PATH when running tests (closes:
+ #662916).
+ * mkconfig_loopback.patch: Use different GRUB loop devices for different
+ OS loop devices (thanks, bcbc; LP: #888281).
+ * Backport from upstream:
+ - Add support for LZO compression in btrfs (LP: #727535).
+ - Fix efiemu configure check.
+
+ [ Ilya Yanok ]
+ * Backport from upstream:
+ - Make FAT UUID uppercase to match Linux (LP: #948716).
+
+ [ Debconf translations ]
+ * Norwegian Bokmål (Hans Fredrik Nordhaug).
+ * Gujarati (Kartik Mistry). Closes: #663542
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 19 Mar 2012 18:24:33 +0000
+
+grub2 (1.99-17) unstable; urgency=low
+
+ * efi_disk_cache.patch: Fix incorrect GRUB_DISK_CACHE_BITS (LP: #944347).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 06 Mar 2012 17:43:42 +0000
+
+grub2 (1.99-16) unstable; urgency=low
+
+ * Backport from upstream:
+ - Build with -fno-asynchronous-unwind-tables to save space (closes:
+ #662787).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 06 Mar 2012 12:45:42 +0000
+
+grub2 (1.99-15) unstable; urgency=low
+
+ [ Adam Conrad ]
+ * grub.cfg_400.patch: Redirect grep stdout to /dev/null since
+ grub-mkconfig is "exec > grub.cfg.new", which causes grep's input
+ and output to be the same FD (LP: #934269) (closes: #652972)
+ * efi_disk_cache.patch: Bump the disk cache on EFI systems to
+ dramatically reduce load times for vmlinux/initrd (LP: #944347)
+
+ [ Colin Watson ]
+ * no_libzfs.patch: Use xasprintf rather than asprintf.
+ * Backport from upstream:
+ - Rewrite XFS btree parsing; fixes invalid BMAP (closes: #657776).
+ - Handle newer autotools, and add some missing quotes in the process.
+ (Note that this moves grub-mkconfig_lib and update-grub_lib to
+ /usr/share/grub; I added links in /usr/lib/grub for compatibility.)
+ - Fix incorrect identifiers in bash-completion (closes: #661415).
+ - Add support for GRUB_CMDLINE_GNUMACH (closes: #660493).
+ * Build with GCC 4.6 (closes: #654727).
+
+ [ Debconf translations ]
+ * Dutch (Jeroen Schot). Closes: #651275
+ * Bulgarian (Damyan Ivanov). Closes: #653356
+ * Icelandic (Sveinn í Felli).
+ * Ukrainian (Yatsenko Alexandr). Closes: #654294
+ * Italian (Luca Monducci). Closes: #654304
+ * Thai (Theppitak Karoonboonyanan). Closes: #656551
+ * Uyghur (Abduqadir Abliz)
+ * Indonesian (Mahyuddin Susanto). Closes: #656705
+ * Hebrew (Omer Zak). Closes: #656852
+ * Turkish (Atila KOÇ). Closes: #656907
+ * Polish (Michał Kułach). Closes: #657265
+ * Asturian (Mikel González).
+ * Dzongkha (Dawa Pemo)
+ * Tamil (Dr.T.Vasudevan).
+ * Belarusian (Viktar Siarhiejczyk). Closes: #662615
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 05 Mar 2012 16:58:01 +0000
+
+grub2 (1.99-14) unstable; urgency=low
+
+ * Rewrite no_libzfs.patch using a different approach. (Closes: #648539)
+
+ -- Robert Millan <rmh@debian.org> Sun, 13 Nov 2011 00:14:38 +0100
+
+grub2 (1.99-13) unstable; urgency=low
+
+ [ Debconf translations ]
+ * Portuguese (Miguel Figueiredo). Closes: #641226
+ * German (Martin Eberhard Schauer). Closes: #641630
+ * Sinhala (Danishka Navin). Closes: #644080
+ * Uyghur (Gheyret Tohti). Closes: #627011
+
+ [ Robert Millan ]
+ * LVM support for GNU/kFreeBSD.
+ - kfreebsd_lvm.patch
+ * Cherry-pick several ZFS updates from upstream Bazaar.
+ - zfs_update.patch
+ * Build without libzfs.
+
+ -- Robert Millan <rmh@debian.org> Fri, 11 Nov 2011 23:04:58 +0100
+
+grub2 (1.99-12) unstable; urgency=low
+
+ [ Robert Millan ]
+ * Fix grub-probe detection for LSI MegaRAID SAS devices on kFreeBSD.
+ - kfreebsd_mfi_devices.patch
+
+ [ Colin Watson ]
+ * Backport from upstream:
+ - Canonicalise the path argument to grub-probe (closes: #637768).
+ - Skip */README* as well as README* (LP: #537123).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 05 Sep 2011 15:17:20 +0100
+
+grub2 (1.99-11) unstable; urgency=low
+
+ * Backport from upstream:
+ - Honour GRUB_CMDLINE_LINUX_XEN_REPLACE and
+ GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT, which replace
+ GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT (complementing the
+ existing options which append; closes: #617538).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 08 Aug 2011 17:55:21 +0100
+
+grub2 (1.99-10) unstable; urgency=high
+
+ * Mark la_array as packed.
+ - zfs_packed_la_array.patch
+
+ -- Robert Millan <rmh@debian.org> Sun, 07 Aug 2011 20:16:31 +0000
+
+grub2 (1.99-9) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Adjust apport hook to attach /boot/grub/device.map if it exists.
+ * Fix regression in gfxterm background_color handling.
+ * Improve detection of invalid shell syntax in apport hook.
+
+ [ Debconf translations ]
+ * Esperanto (Felipe E. F. de Castro). Closes: #632157
+ * Slovak (Slavko).
+
+ [ Robert Millan ]
+ * Enable grub-mount on kfreebsd-any.
+ * Build grub-mount-udeb on kfreebsd-i386 and kfreebsd-amd64.
+
+ -- Robert Millan <rmh@debian.org> Mon, 25 Jul 2011 15:36:31 +0200
+
+grub2 (1.99-8) unstable; urgency=low
+
+ [ Robert Millan ]
+ * Avoid buggy versions of libgeom-dev (see #630107). Closes: #630197
+ * Fix grub-probe detection for ATA devices using `ata' driver on kFreeBSD 9.
+ - kfreebsd-9_ada_devices.patch
+
+ [ Colin Watson ]
+ * Update ntldr-img from grub-extras:
+ - Handle ext3 inode sizes other than 128.
+
+ [ Debconf translations ]
+ * Kazakh (Baurzhan Muftakhidinov). Closes: #630915
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 21 Jun 2011 02:10:10 +0100
+
+grub2 (1.99-7) unstable; urgency=low
+
+ [ Debconf translations ]
+ * Basque (Iñaki Larrañaga Murgoitio). Closes: #628716
+ * Swedish (Martin Bagge / brother). Closes: #628866
+ * Czech (Miroslav Kure). Closes: #628978
+ * Brazilian Portuguese (Flamarion Jorge). Closes: #629135
+ * Spanish (Francisco Javier Cuadrado). Closes: #629633
+
+ [ Colin Watson ]
+ * Cope with btrfs / inside an encrypted block device (thanks, alexeagar;
+ LP: #757631).
+ * Merge from Ubuntu:
+ - Give up scanning partitions after ten consecutive open failures
+ (LP: #787461).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 16 Jun 2011 00:13:14 +0100
+
+grub2 (1.99-6) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Update Vcs-* fields for Alioth changes.
+ * Backport from upstream, removing the need for Breaks: udev (<< 168-1):
+ - Don't stat devices unless we have to.
+
+ [ Debconf translations ]
+ * Catalan (Jordi Mallach).
+ * Farsi (Behrad Eslamifar). Closes: #628648
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 31 May 2011 09:20:54 +0100
+
+grub2 (1.99-5) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Change grub2/linux_cmdline and grub2/kfreebsd_cmdline descriptions to
+ indicate that the command line is allowed to be empty, since this is a
+ common source of confusion (thanks, Jordan Uggla).
+ * On non-Ubuntu-derived systems, add Breaks: udev (<< 168-1) to
+ grub-common, for the sake of (some?) users without initrds (closes:
+ #627587).
+
+ [ Debconf translations ]
+ * French (Christian Perrier)
+ * Russian (Yuri Kozlov). Closes: #628196
+ * Simplified Chinese (YunQiang Su). Closes: #628210
+ * Japanese (Hideki Yamane). Closes: #628382
+ * Danish (Joe Hansen). Closes: #628427
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 29 May 2011 21:58:55 +0100
+
+grub2 (1.99-4) unstable; urgency=low
+
+ * Make grub-<platform>-bin packages depend on grub-common rather than
+ grub2-common, and add grub2-common dependencies to grub-<platform>.
+ This ensures that grub-<platform>-bin packages are coinstallable with
+ grub-legacy, making it easier to use them as build-dependencies.
+ * Stop trying to install the non-existent grub-ofpathname(8) on sparc for
+ now. It will exist in the next upstream snapshot.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 19 May 2011 12:38:45 +0100
+
+grub2 (1.99-3) unstable; urgency=low
+
+ * Ship grub-mkrescue on non-Linux amd64/i386 architectures.
+ * Don't try to ship grub-mkrescue on sparc.
+ * Drop boot_blocklist_hack.patch, fixed differently upstream some time ago
+ by being smarter about filesystem-root-relative path conversion.
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 18 May 2011 14:06:51 +0100
+
+grub2 (1.99-2) unstable; urgency=low
+
+ * Include both old and new Lintian override styles for
+ statically-linked-binary tag, since ftp-master has not yet been updated
+ to 2.5.0~rc1.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 17 May 2011 01:36:10 +0100
+
+grub2 (1.99-1) unstable; urgency=low
+
+ * New upstream release.
+ - Ensure uniqueness of RAID array numbers even if some elements have a
+ name (closes: #609804).
+ - Remove unnecessary brackets from tr arguments (closes: #612564).
+ - Add grub-mkrescue info documentation (closes: #612585).
+ - Avoid generating invalid configuration when something that looks like
+ a Xen hypervisor is present without any Xen kernels (closes: #612898).
+ - Fix memory alignment when calling 'linux' multiple times on EFI
+ (closes: #616638).
+ - Fix grub-install on amd64 EFI systems (closes: #617388).
+ - Automatically export pager variable (closes: #612995).
+ - Fix parser error with "time" (closes: #612991).
+ - Ignore case of bitmap extensions (closes: #611123).
+ - Skip vmlinux-* on x86 platforms (closes: #536846, #546008).
+ - Accept old-style Xen kernels (closes: #610428).
+ - Skip damaged LVM volumes (closes: #544731).
+ - Handle LVM mirroring (closes: #598441).
+ - Detect spares and report them as not RAID members (closes: #611561).
+ - Don't enable localisation unless gfxterm is available (closes:
+ #604609).
+ - Fix partitioned RAID support (closes: #595071, #613444).
+ - Dynamically count the number of lines for the lower banner (closes:
+ #606494).
+ - Improve quoting in grub-mkconfig, to support background image file
+ names containing spaces (closes: #612417).
+ - Flush BIOS disk devices more accurately (closes: #623124).
+ - Identify RAID devices by their UUID rather than by their guessed name
+ (closes: #624232).
+ - Add "SEE ALSO" sections to most man pages (closes: #551428).
+
+ [ Christian Perrier ]
+ * Drop extra word in French debconf translation. Thanks to David
+ Prévôt.
+ * Fix spelling error in French debconf translation. Thanks to David
+ Prévôt.
+
+ [ Colin Watson ]
+ * Set PACKAGE_VERSION and PACKAGE_STRING using configure arguments rather
+ than sedding configure.ac in debian/rules (which sometimes has annoying
+ interactions with quilt, etc.).
+ * Update branch_embed-sectors.patch:
+ - Detect sector used by HighPoint RAID controller (closes: #394868).
+ * Add debian/README.source (from quilt).
+ * Make debian/rules more explicit about when autogen.sh is run. We need
+ to be careful that all full builds run it, since we use GRUB extras.
+ * Merge from Ubuntu:
+ - Handle filesystems loop-mounted on file images.
+ - On Wubi, don't ask for an install device, but just update wubildr
+ using the diverted grub-install.
+ - Add grub-mount-udeb, containing just grub-mount. This can be used by
+ os-prober and other parts of d-i.
+ - Artificially bump Replaces: grub-common versioning to account for
+ grub-reboot/grub-set-default movement in Ubuntu.
+ * Don't do a separate build pass for grub-common. It will be identical to
+ the build for the default platform for the CPU architecture anyway, so
+ reuse that.
+ * Build with GCC 4.5 on all architectures.
+ * Update Lintian overrides for changes in Lintian 2.5.0~rc1.
+ * Invert how files are split among binary packages: rather than code in
+ debian/rules to remove files we don't want, add dh_install configuration
+ to declare the files we do want. This means a little more repetition
+ for platform-specific programs, but it seems less confusing and easier
+ to extend.
+ * Drop versioned dependencies on base-files. GPL-3 has been there for two
+ Debian releases now, and the dependency was never upgrade-critical
+ anyway.
+ * Create grub2-common package containing files that are common among GRUB
+ platform packages but that would break GRUB Legacy, or that are too
+ confusing when coinstalled with GRUB Legacy (closes: #564167).
+ * Drop conflict on an ancient (pre-lenny/hardy) version of desktop-base.
+ * Move /etc/grub.d/05_debian_theme to grub-common, to go with the other
+ /etc/grub.d/* files.
+ * Drop redundant Suggests: os-prober from several platform packages, as
+ grub-common already Recommends: os-prober.
+ * Create grub-<platform>-bin packages corresponding to all grub-<platform>
+ packages (except for grub-emu). These do not automatically install the
+ boot loader or update grub.cfg, and they install their binaries to
+ /usr/lib/grub/<cpu>-<platform>/; this means that they can be installed
+ in parallel, making it easier to use them to build GRUB-based disk
+ images (e.g. d-i). The grub-<platform> packages now depend on these and
+ include symlinks, so their behaviour will remain as before.
+ * Make grub-emu depend on grub-common.
+ * Make the documentation directory in most binary packages be a symlink to
+ that in grub-common.
+ * Drop lenny compatibility from grub2-common's dpkg/install-info
+ dependency, since it produces a Lintian warning and using the current
+ packaging on lenny is probably rather a stretch anyway.
+
+ [ Updated translations ]
+ * Belarusian (Viktar Siarheichyk). Closes: #606864
+ * Danish (Joe Hansen). Closes: #606879
+ * Romanian (Andrei POPESCU). Closes: #606888
+ * Italian (Luca Monducci). Closes: #606891
+ * Brazilian Portuguese (Flamarion Jorge). Closes: #610613
+ * Greek (Emmanuel Galatoulas). Closes: #604847
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 16 May 2011 17:42:07 +0100
+
+grub2 (1.99~rc1-13) unstable; urgency=low
+
+ * Cherry-pick from upstream:
+ - Use correct limits for mips initrd.
+ * Run grub-install on install or upgrade of grub-yeeloong.
+ * Update branch_fuse.patch:
+ - Tell FUSE to run single-threaded, since GRUB code is not thread-safe
+ (LP: #756297).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 15 Apr 2011 12:11:21 +0100
+
+grub2 (1.99~rc1-12) unstable; urgency=low
+
+ * Update branch_butter.patch:
+ - Fix filename comparison.
+ - Take extent offset in account on uncompressed extents.
+ - Use filled extent size if available.
+ * Allow use of first sector on btrfs (LP: #757446).
+ * Merge from Ubuntu:
+ - Build part_msdos and vfat into EFI boot images (LP: #677758).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 11 Apr 2011 16:22:08 +0100
+
+grub2 (1.99~rc1-11) unstable; urgency=low
+
+ * Update branch_fuse.patch:
+ - Make grub-mount exit non-zero if opening the device or filesystem
+ fails.
+ - Translate GRUB error codes into OS error codes for FUSE (LP: #756456).
+ * Merge from Ubuntu:
+ - Fix use of freed memory when replacing existing loopback device
+ (LP: #742967).
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 10 Apr 2011 21:52:26 +0100
+
+grub2 (1.99~rc1-10) unstable; urgency=low
+
+ * Update branch_butter.patch, fixing RAID1/duplicated chunk size
+ calculation (thanks, Vladimir Serbinenko; LP: #732149).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 09 Apr 2011 21:22:15 +0100
+
+grub2 (1.99~rc1-9) unstable; urgency=low
+
+ * Update branch_parse-color.patch, to blend text when any background is
+ set as opposed to only when a stretched background is set (closes:
+ #613120).
+ * Make update-grub2 a symlink to update-grub, rather than bothering with a
+ wrapper script.
+ * Cherry-pick from upstream:
+ - Check RAID superblock offset (closes: #610184).
+ - Flush buffer cache on close and not on open (closes: #620663).
+ - Handle special naming of yeeloong directory (closes: #620420).
+ * Add grub-mount utility, from the upstream 'fuse' branch.
+ * efibootmgr is only available on Linux architectures, so only make
+ grub-efi-ia32 and grub-efi-amd64 depend on it on Linux.
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 09 Apr 2011 03:39:56 +0100
+
+grub2 (1.99~rc1-8) unstable; urgency=low
+
+ * Cherry-pick from upstream:
+ - Fix FreeBSD compilation problem.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 29 Mar 2011 15:13:51 +0100
+
+grub2 (1.99~rc1-7) unstable; urgency=low
+
+ * Add /proc/mdstat, LVM information, and listings of /dev/disk/by-id/ and
+ /dev/disk/by-uuid/ to bug reports, by request of upstream.
+ * Cherry-pick from upstream:
+ - Use libgeom on FreeBSD to detect partitions (closes: #612128).
+ - Copy the partition table zone if floppy support is disabled, even if
+ no partition table is found (LP: #741867).
+ - Fix an ext2 overflow affecting inodes past 2TiB.
+ - Fix RAID-0 disk size calculation for metadata 1.x (LP: #743136).
+ * Merge from Ubuntu:
+ - Build with gcc-4.5 on ppc64.
+ - Add apport hook for ProblemType = 'Package', thanks to Jean-Baptiste
+ Lallement (LP: #591753).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 29 Mar 2011 12:30:36 +0100
+
+grub2 (1.99~rc1-6) unstable; urgency=low
+
+ * Cherry-pick from upstream:
+ - Fix crash when extending menu entry line beyond 79 characters (closes:
+ #615893).
+ - Account for FreeBSD module headers when calculating allocation size.
+ - Switch back to framebuffer page zero before loading the kernel
+ (thanks, Felix Kuehling).
+ * Merge from Ubuntu:
+ - If we're upgrading and /boot/grub/core.img doesn't exist, then don't
+ ask where to install GRUB, since it probably means we're in some kind
+ of specialised environment such as a live USB stick (LP: #591202).
+ - Drop the default priority of grub2/linux_cmdline to medium. We only
+ need to ask it if we're upgrading from GRUB Legacy and found an empty
+ kopt in menu.lst (LP: #591202).
+ * Update branch_embed-sectors.patch, avoiding consuming lots of space and
+ time if the first partition is not near the start of the disk (closes:
+ #619458, LP: #691569).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 25 Mar 2011 19:23:04 +0000
+
+grub2 (1.99~rc1-5) unstable; urgency=low
+
+ * Update debian/legacy/update-grub to the version from grub 0.97-65.
+ * Mark binary packages as Multi-Arch: foreign (for example, an amd64
+ kernel installed on an i386 system could use the native architecture's
+ GRUB).
+ * Rewrite find_root_device_from_mountinfo to cope with move-mounts
+ (LP: #738345).
+
+ [ Updated translations ]
+ * Esperanto (Felipe Castro). Closes: #606524
+ * Thai (Theppitak Karoonboonyanan). Closes: #607706
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 23 Mar 2011 15:51:47 +0000
+
+grub2 (1.99~rc1-4) unstable; urgency=low
+
+ * Don't touch /boot/grub/grub2-installed if using the --root-directory
+ option to grub-install (thanks, Nicolas George; closes: #614927).
+ * Update branch_devmapper.patch, adding partitioned MD RAID support
+ (untested) and support for probing multipath disks.
+ * Update ntldr-img from grub-extras:
+ - Only call ntfs_fix_mmft if the attribute to find is AT_DATA. This
+ matches GRUB's NTFS module.
+ - Install grubinst as grub-ntldr-img.
+ * Fix loading GRUB from lnxboot (LP: #693671).
+ * Update branch_embed-sectors.patch to avoid straying into first partition
+ when embedding-area sectors are in use (closes: #613409, LP: #730225).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 15 Mar 2011 11:01:48 +0000
+
+grub2 (1.99~rc1-3) unstable; urgency=low
+
+ * Build for ppc64 (except for grub-emu, which doesn't build cleanly yet).
+ * Suppress output from debconf-communicate in upgrade-from-grub-legacy.
+ * Refer to the info documentation at the top of /etc/default/grub (closes:
+ #612538).
+ * We need at least freebsd-utils (>= 8.0-4) on kFreeBSD architectures for
+ camcontrol, so depend on it.
+ * Tolerate camcontrol failing to read capacity of IDE devices, until such
+ time as we know how to do this properly (see #612128).
+ * Adjust /etc/default/grub for rename of GRUB_DISABLE_LINUX_RECOVERY to
+ GRUB_DISABLE_RECOVERY (closes: #612777).
+ * Update ntldr-img from grub-extras:
+ - Install g2hdr.bin and g2ldr.mbr (closes: #613245).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 16 Feb 2011 13:11:11 +0000
+
+grub2 (1.99~rc1-2) unstable; urgency=low
+
+ * Merge 1.98+20100804-13 and 1.98+20100804-14, updating translations:
+ - Kazakh (Baurzhan Muftakhidinov / Timur Birsh).
+ * mkconfig_skip_dmcrypt.patch: Refer to GRUB_PRELOAD_MODULES rather than
+ suggesting people write a /etc/grub.d/01_modules script (thanks, Jordan
+ Uggla).
+ * Handle empty dir passed to grub_find_root_device_from_mountinfo; fixes
+ grub-mkrelpath on btrfs subvolumes (LP: #712029).
+ * Add rootflags=subvol=<name> if / is on a btrfs subvolume (LP: #712029).
+ * Upload to unstable.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 08 Feb 2011 11:39:26 +0000
+
+grub2 (1.99~rc1-1) experimental; urgency=low
+
+ [ Colin Watson ]
+ * New upstream release candidate.
+
+ [ Alexander Kurtz ]
+ * 05_debian_theme:
+ - If we find a background image and no colours were specified, use
+ upstream defaults for color_normal and color_highlight rather than
+ setting color_normal to black/black.
+ - Make the code more readable by replacing code for handling
+ alternatives.
+ - Make the code for searching for pictures in /boot/grub more readable
+ and robust (for example against newlines in the filename).
+ - Don't try the other alternatives when $GRUB_BACKGROUND is set; you can
+ now add GRUB_BACKGROUND= to /etc/default/grub to force no background
+ image (closes: #608263).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 17 Jan 2011 13:43:06 +0000
+
+grub2 (1.99~20110112-1) experimental; urgency=low
+
+ * New Bazaar snapshot.
+ - Disable ieee1275_fb on sparc (closes: #560823).
+ - Fix pf2 font generation on big-endian platforms (closes: #609818).
+ * branch_butter.patch: Resolve the device returned by
+ grub_find_root_device_from_mountinfo or find_root_device_from_libzfs
+ using grub_find_device (closes: #609590, #609814, LP: #700147).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 13 Jan 2011 00:12:41 +0000
+
+grub2 (1.99~20110111-1) experimental; urgency=low
+
+ * New Bazaar snapshot.
+ - Don't check amount of low memory, as reportedly INT 12h can be broken
+ and if low memory is too low we wouldn't have gotten into
+ grub_machine_init anyway (closes: #588293, LP: #513528).
+ - Submenu default support (LP: #691878).
+ - Fix optimisation-dependent grub-mklayout crash (closes: #609584).
+ * branch_butter.patch: Don't free an uninitialised pointer if /proc is
+ unmounted (LP: #697493).
+ * Add a po/LINGUAS file listing the translations we've synced from the TP
+ (closes: #609671).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 11 Jan 2011 17:11:44 +0000
+
+grub2 (1.99~20110106-1) experimental; urgency=low
+
+ * New Bazaar snapshot.
+ - Check that named RAID array devices exist before using them (closes:
+ #606035).
+ - Clear terminfo output on initialisation (closes: #569678).
+ - Fix grub-probe when btrfs is on / without a separate /boot.
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 06 Jan 2011 13:38:57 +0000
+
+grub2 (1.99~20110104-2) experimental; urgency=low
+
+ * Support long command lines as per the 2.06 Linux boot protocol, from the
+ upstream 'longlinuxcmd' branch.
+ * Add a background_color command, from the upstream 'parse-color' branch.
+ * Update branch_devmapper.patch, adding a #include to fix a build failure
+ on Ubuntu amd64.
+ * When embedding the core image in a post-MBR gap, check for and avoid
+ sectors matching any of a number of known signatures, from the upstream
+ 'embed-sectors' branch.
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 05 Jan 2011 13:31:05 +0000
+
+grub2 (1.99~20110104-1) experimental; urgency=low
+
+ * New Bazaar snapshot.
+ - Don't emit drivemap directive for Windows Server 2008 (closes:
+ #607687).
+ - Don't add spurious RAID array members (closes: #605357).
+ - Improve presentation of Xen menu entries (closes: #607867).
+ - Fix PCI probing hangs by skipping remaining functions on devices that
+ do not implement function 0 (closes: #594967).
+ - Fix typo in descriptions of extract_legacy_entries_source and
+ extract_legacy_entries_configfile (LP: #696721).
+ * Merge 1.98+20100804-12:
+ - Use semicolons rather than commas to separate size from model in
+ debconf disk and partition descriptions.
+ * Add full btrfs support, from the upstream 'butter' branch.
+ * Support partitioned loop devices and improve devmapper support, from the
+ upstream 'devmapper' branch.
+ * Add squashfs 4 support, from the upstream 'squash' branch.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 04 Jan 2011 16:12:45 +0000
+
+grub2 (1.99~20101221-1) experimental; urgency=low
+
+ * New Bazaar snapshot.
+ - Initialise next pointer when creating multiboot module (closes:
+ #605567).
+ - Fix gettext quoting to work with bash as /bin/sh, and make echo
+ UTF-8-clean so that (at least) Catalan boot messages are displayed
+ properly (closes: #605615).
+ - Fix use of uninitialised memory in Reed-Solomon recovery code
+ (LP: #686705).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 21 Dec 2010 17:43:52 +0000
+
+grub2 (1.99~20101210-2) experimental; urgency=low
+
+ * Automatically remove MD devices from device.map on upgrade, since the
+ BIOS cannot read from these and including them in device.map will break
+ GRUB's ability to read from such devices (LP: #690030).
+ * Merge 1.98+20100804-9, 1.98+20100804-10, and 1.98+20100804-11:
+ - Apply debconf template review by debian-l10n-english and mark several
+ more strings for translation, thanks to David Prévot and Justin B Rye.
+ - Incorporate rewritten 05_debian_theme by Alexander Kurtz, which works
+ when /usr is inaccessible by GRUB.
+
+ -- Colin Watson <cjwatson@debian.org> Sun, 19 Dec 2010 13:25:14 +0000
+
+grub2 (1.99~20101210-1) experimental; urgency=low
+
+ * New Bazaar snapshot.
+ - ZFS moved into grub-core.
+ - Extend gettext to fall back from ll_CC to ll, and set lang to include
+ country part by default so that Chinese works (LP: #686788).
+ * Remove grub-mknetdir from grub-emu.
+ * Exit silently from zz-update-grub kernel hook if update-grub does not
+ exist (e.g. if grub-pc has been removed but not purged; closes:
+ #606184).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 11 Dec 2010 01:22:26 +0000
+
+grub2 (1.99~20101126-1) experimental; urgency=low
+
+ * New Bazaar snapshot (mipsel build fix, LVM-on-RAID probing fix).
+ * Fix comma-separation in handling of grub-pc/install_devices.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 26 Nov 2010 13:08:52 +0000
+
+grub2 (1.99~20101124-1) experimental; urgency=low
+
+ * New Bazaar snapshot (command priorities, build fixes, grub-mkdevicemap
+ segfault).
+ * Don't try to build grub-efi-amd64 on kfreebsd-i386 or hurd-i386
+ (requires gcc-4.4-multilib).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 24 Nov 2010 12:12:33 +0000
+
+grub2 (1.99~20101123-1) experimental; urgency=low
+
+ * New Bazaar snapshot (build fixes).
+ * Build-depend on qemu-utils and parted on non-Hurd architectures.
+ * qemu_img_exists.patch: Skip partmap test if qemu-img doesn't exist (as
+ is the case on the Hurd).
+ * Make grub-efi-ia32 and grub-efi-amd64 depend on efibootmgr so that
+ grub-install works properly.
+ * Upgrade the installed core image when upgrading grub-efi-ia32 or
+ grub-efi-amd64, although only if /boot/efi/EFI/<id> (where <id> is an
+ identifier based on GRUB_DISTRIBUTOR, e.g. 'debian') already exists.
+ * Re-expand a couple of dpkg architecture wildcards to exclude certain
+ special cases: gcc-4.4-multilib is not available on kfreebsd-i386 or
+ hurd-i386, and qemu-system is not available on hurd-i386.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 23 Nov 2010 10:51:23 +0000
+
+grub2 (1.99~20101122-1) experimental; urgency=low
+
+ [ Colin Watson ]
+ * New Bazaar snapshot. Too many changes to list in full, but some of the
+ more user-visible ones are as follows:
+ - GRUB script:
+ + Function parameters, "break", "continue", "shift", "setparams",
+ "return", and "!".
+ + "export" command supports multiple variable names.
+ + Multi-line quoted strings support.
+ + Wildcard expansion.
+ - sendkey support.
+ - USB hotunplugging and USB serial support.
+ - Rename CD-ROM to cd on BIOS.
+ - Add new --boot-directory option to grub-install, grub-reboot, and
+ grub-set-default; the old --root-directory option is still accepted
+ but was often confusing.
+ - Basic btrfs detection/UUID support (but no file reading yet).
+ - bash-completion for utilities.
+ - If a device is listed in device.map, always assume that it is
+ BIOS-visible rather than using extra layers such as LVM or RAID.
+ - Add grub-mknetdir script (closes: #550658).
+ - Remove deprecated "root" command.
+ - Handle RAID devices containing virtio components.
+ - GRUB Legacy configuration file support (via grub-menulst2cfg).
+ - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
+ - Check generated grub.cfg for syntax errors before saving.
+ - Pause execution for at most ten seconds if any errors are displayed,
+ so that the user has a chance to see them.
+ - Support submenus.
+ - Write embedding zone using Reed-Solomon, so that it's robust against
+ being partially overwritten (closes: #550702, #591416, #593347).
+ - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
+ into a single GRUB_DISABLE_RECOVERY variable.
+ - Fix loader memory allocation failure (closes: #551627).
+ - Don't call savedefault on recovery entries (closes: #589325).
+ - Support triple-indirect blocks on ext2 (closes: #543924).
+ - Recognise DDF1 fake RAID (closes: #603354).
+
+ [ Robert Millan ]
+ * Use dpkg architecture wildcards.
+
+ [ Updated translations ]
+ * Slovenian (Vanja Cvelbar). Closes: #604003
+ * Dzongkha (dawa pemo via Tenzin Dendup). Closes: #604102
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 22 Nov 2010 12:24:56 +0000
+
+grub2 (1.98+20100804-14) unstable; urgency=low
+
+ [ Updated translations ]
+ * Kazakh (Baurzhan Muftakhidinov / Timur Birsh). Closes: #609187
+
+ [ Alexander Kurtz ]
+ * 05_debian_theme:
+ - If we find a background image and no colours were specified, use
+ upstream defaults for color_normal and color_highlight rather than
+ setting color_normal to black/black.
+ - Don't try the other alternatives when $GRUB_BACKGROUND is set; you can
+ now add GRUB_BACKGROUND= to /etc/default/grub to force no background
+ image (closes: #608263).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 17 Jan 2011 23:19:38 +0000
+
+grub2 (1.98+20100804-13) unstable; urgency=low
+
+ * Backport from upstream:
+ - Don't add spurious RAID array members (closes: #605357).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 04 Jan 2011 14:07:14 +0000
+
+grub2 (1.98+20100804-12) unstable; urgency=low
+
+ * Backport from upstream:
+ - Support big ext2 files (closes: #543924).
+ - Fix gettext quoting to work with bash as /bin/sh, and make echo
+ UTF-8-clean so that (at least) Catalan boot messages are displayed
+ properly (closes: #605615).
+ - Initialise next pointer when creating multiboot module (closes:
+ #605567).
+ - Fix PCI probing hangs by skipping remaining functions on devices that
+ do not implement function 0 (closes: #594967).
+ * Use semicolons rather than commas to separate size from model in debconf
+ disk and partition descriptions; commas are too easily confused with the
+ multiselect choice separator, and in particular make it impossible to
+ answer questions properly in the editor frontend (closes: #608449).
+ Unfuzzy all translations where possible.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 04 Jan 2011 00:42:29 +0000
+
+grub2 (1.98+20100804-11) unstable; urgency=low
+
+ * Exit silently from zz-update-grub kernel hook if update-grub does not
+ exist (e.g. if grub-pc has been removed but not purged; closes:
+ #606184).
+ * Apply debconf template review by debian-l10n-english and mark several
+ more strings for translation, thanks to David Prévot and Justin B Rye
+ (closes: #605748).
+ * Unfuzzy some translations that were not updated in this round (thanks,
+ David Prévot; closes: #606921).
+ * Incorporate rewritten 05_debian_theme by Alexander Kurtz, which works
+ when /usr is inaccessible by GRUB (closes: #605705).
+ * Backport from upstream:
+ - Recognise DDF1 DM-RAID (closes: #603354).
+
+ [ Updated translations ]
+ * Chinese (YunQiang Su). Closes: #606426
+ * Indonesian (Arief S Fitrianto). Closes: #606431
+ * Slovenian (Vanja Cvelbar). Closes: #606445
+ * Swedish (Martin Bagge / brother). Closes: #606455
+ * Ukrainian (Yatsenko Alexandr). Closes: #606538
+ * Basque (Iñaki Larrañaga Murgoitio). Closes: #606644
+ * Slovak (Slavko). Closes: #606663
+ * Catalan (Jordi Mallach).
+ * Bulgarian (Damyan Ivanov). Closes: #606452
+ * Persian (Morteza Fakhraee). Closes: #606672
+ * Russian (Yuri Kozlov). Closes: #606753
+ * Dutch (Paul Gevers). Closes: #606807
+ * Japanese (Hideki Yamane). Closes: #606836
+ * French (Christian Perrier). Closes: #606842
+ * Czech (Miroslav Kure). Closes: #606854
+ * Spanish (Francisco Javier Cuadrado). Closes: #606903
+ * Portuguese (Tiago Fernandes / Miguel Figueiredo). Closes: #606908
+ * German (Martin Eberhard Schauer). Closes: #606896
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 18 Dec 2010 17:20:09 +0000
+
+grub2 (1.98+20100804-10) unstable; urgency=low
+
+ * fix_crash_condition_in_kfreebsd_loader.patch: Import from upstream.
+ Fixes crash condition in case kfreebsd_* commands are used after
+ kfreebsd has (gracefully) failed.
+
+ -- Robert Millan <rmh@debian.org> Tue, 30 Nov 2010 19:40:11 +0100
+
+grub2 (1.98+20100804-9) unstable; urgency=low
+
+ [ Robert Millan ]
+ * Import from upstream:
+ - refuse_embedingless_cross_disk.patch: Refuse to do a cross-disk
+ embeddingless install rather than creating a broken install.
+ - fix_grub_install_error_msg.patch: Replace useless recomendation to
+ pass --modules with a recomendation to report a bug.
+ - message_refresh.patch: Make error messages visible again. (Closes: #605485)
+
+ [ Jordi Mallach ]
+ * Update Catalan translation with latest file from the Translation Project.
+
+ [ Updated translations ]
+ * Slovenian (Vanja Cvelbar). Closes: #604003
+ * Dzongkha (dawa pemo via Tenzin Dendup). Closes: #604102
+
+ -- Robert Millan <rmh@debian.org> Tue, 30 Nov 2010 15:44:02 +0100
+
+grub2 (1.98+20100804-8) unstable; urgency=low
+
+ [ Robert Millan ]
+ * increase_disk_limit.patch: Increase SCSI/IDE disk limits to cope with
+ Sun Fire X4500.
+ * linux_mdraid_1x.patch: Support for Linux MD RAID v1.x. (Closes: #593652)
+ * yeeloong_boot_info.patch: On Yeeloong, pass machine type information
+ to Linux.
+
+ [ Updated translations ]
+ * Portuguese fixed by Christian Perrier (variable names
+ were translated)
+
+ -- Robert Millan <rmh@debian.org> Fri, 05 Nov 2010 23:43:15 +0100
+
+grub2 (1.98+20100804-7) unstable; urgency=low
+
+ [ Robert Millan ]
+ * zfs_fix_mkrelpath.patch: Replace with proper fix from upstream Bazaar.
+ (Closes: #601087)
+
+ [ Updated translations ]
+ * Vietnamese (Clytie Siddall). Closes: #598327
+ * Icelandic (Sveinn í Felli). Closes: #600126
+
+ -- Robert Millan <rmh@debian.org> Sun, 24 Oct 2010 16:35:37 +0200
+
+grub2 (1.98+20100804-6) unstable; urgency=low
+
+ [ Robert Millan ]
+ * zfs_v23.patch: Accept ZFS up to v23 (no changes required).
+ * fix_usb_boot.patch: Fix boot on USB devices, for BIOSes that
+ expose them as floppies. (Closes: #600580)
+ * zfs_fix_mkrelpath.patch: Fix grub-mkrelpath for non-root ZFS.
+ (Closes: #600578)
+
+ [ Updated translations ]
+ * Kazakh (kk.po) by Baurzhan Muftakhidinov via Timur Birsh (closes:
+ #598188).
+ * Portuguese (pt.po) by Tiago Fernandes via Rui Branco (closes: #599767).
+ * Catalan (ca.po) by Jordi Mallach.
+
+ -- Robert Millan <rmh@debian.org> Thu, 21 Oct 2010 23:45:23 +0200
+
+grub2 (1.98+20100804-5) unstable; urgency=low
+
+ [ Updated translations ]
+ * Hebrew (he.po) by Omer Zak and Lior Kaplan (closes: #593855).
+ * Romanian (ro.po) by ioan-eugen STAN (closes: #595727).
+ * Esperanto (eo.po) by Felipe Castro (closes: #596171).
+
+ [ Colin Watson ]
+ * Make grub-efi-amd64 conflict with grub-pc as well as the other way
+ round.
+ * Backport upstream patches to fix DM-RAID support (closes: #594221,
+ LP: #634840).
+
+ [ Robert Millan ]
+ * enable_zfs.patch: Fix grub-fstest build problem.
+ * zfs_fix_label_arg.patch: Fix kfreebsd_device initialization on ZFS
+ for non-main filesystems.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 17 Sep 2010 23:45:10 +0100
+
+grub2 (1.98+20100804-4) unstable; urgency=low
+
+ [ Updated translations ]
+ * Italian (it.po) by Luca Monducci (closes: #593685).
+ * Finnish (fi.po) by Esko Arajärvi (closes: #593921).
+
+ [ Colin Watson ]
+ * Run update-grub from kernel hooks if DEB_MAINT_PARAMS is unset, for
+ compatibility with old kernel packages. This may produce duplicate runs
+ of update-grub, but that's better than not running it at all (closes:
+ #594037).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 23 Aug 2010 12:11:55 +0100
+
+grub2 (1.98+20100804-3) unstable; urgency=low
+
+ [ Updated translations ]
+ * Brazilian Portuguese (pt_BR.po) by Flamarion Jorge (closes: #592156).
+ * Asturian (ast.po) by Maacub (closes: #592313).
+ * Galician (gl.po) by Jorge Barreiro (closes: #592816).
+
+ [ Robert Millan ]
+ * Backport ZFS bugfixes from upstream Bazaar:
+ - zfs_fix_chroot.patch: Fix breakage when running grub-probe inside chroot.
+ - zfs_fix_label_arg.patch: Fix grub-probe fs_label argument.
+ - zfs_fix_pathname.patch: Fix pathname for non-root ZFS filesystems.
+ - zfs_fix_segfault.patch: Fix segfault when /dev is not mounted.
+
+ [ Colin Watson ]
+ * Escape single quotes when removing them from $mode in zz-update-grub, so
+ that this works when /bin/sh is bash (thanks, Will Dyson; closes:
+ #593242).
+ * Add support for ext2 root on GNU/kFreeBSD (thanks, Aurelien Jarno;
+ closes: #593467).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 19 Aug 2010 18:21:45 +0100
+
+grub2 (1.98+20100804-2) unstable; urgency=low
+
+ [ Colin Watson ]
+ * Make /etc/kernel/postrm.d/zz-update-grub a real file rather than a
+ symlink (closes: #592076).
+
+ [ Updated translations ]
+ * Norwegian Bokmål (nb.po) by Hans Nordhaug (closes: #591569).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 07 Aug 2010 17:53:34 +0100
+
+grub2 (1.98+20100804-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Fix grub-emu build on GNU/kFreeBSD (closes: #591490).
+
+ [ Colin Watson ]
+ * Add kernel hook scripts and remove any uses of update-grub as a
+ postinst_hook or postrm_hook in /etc/kernel-img.conf (closes: #554175).
+ Thanks to Ben Hutchings for advice and to Harald Braumann for an early
+ implementation.
+ * Extend the existing GRUB_LEGACY_0_BASED_PARTITIONS handling to avoid
+ new-style partition naming when generating output for GRUB Legacy
+ (closes: #590554).
+
+ [ Updated translations ]
+ * Slovak (sk.po) by Slavko (closes: #591458).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 04 Aug 2010 04:48:11 +0100
+
+grub2 (1.98+20100802-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Remove compatibility with terminal.mod prior to
+ terminal_input/terminal_output separation (LP: #519358).
+ - Enable `grub-probe -t device' resolution on ZFS.
+ - Don't use UUID for LVM root when generating Xen entries (closes:
+ #591093).
+ - Restore missing whitespace to commands' --help output (closes:
+ #590874).
+ - Select unique numbers for named RAID arrays, for use as keys in the
+ disk cache.
+
+ [ Updated translations ]
+ * German (Martin Eberhard Schauer). Closes: #590108
+ * Spanish (Francisco Javier Cuadrado). Closes: #590448
+ * Traditional Chinese (Tetralet). Closes: #591191
+ * Danish (Joe Hansen). Closes: #591223
+ * Dutch (Paul Gevers). Closes: #590864
+ * Japanese (Hideki Yamane). Closes: #591058
+
+ [ Robert Millan ]
+ * postinst.in: Fill in device size and model information on GNU/kFreeBSD,
+ using camcontrol.
+ * patches/enable_zfs.patch: New patch. Link ZFS from grub-extras into
+ grub-probe and grub-setup.
+ * control: Build-Depend on libzfs-dev and libnvpair-dev on kfreebsd-*.
+
+ [ Colin Watson ]
+ * Offer RAID devices as GRUB installation targets if they contain /,
+ /boot, or /boot/grub.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 03 Aug 2010 02:13:07 +0100
+
+grub2 (1.98+20100722-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Don't count named RAID arrays when looking for unused array numbers.
+
+ [ Colin Watson ]
+ * Merge from Ubuntu:
+ - grub-common Breaks: lupin-support (<< 0.30) due to a grub-mkimage
+ syntax change (lupin-support isn't in Debian, but this is harmless
+ anyway).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 22 Jul 2010 14:33:34 +0100
+
+grub2 (1.98+20100720-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Link to Info documentation on changes from GRUB Legacy in README
+ (closes: #502623).
+ - Add support for mdadm metadata formats 1.x (closes: #492897).
+
+ [ Aaron M. Ucko ]
+ * Compare -trunk kernels earlier than numeric ABIs (closes: #568160).
+
+ [ Colin Watson ]
+ * Remove /boot/grub/device.map, /boot/grub/grubenv,
+ /boot/grub/installed-version, and /boot/grub/locale/ on purge, if
+ permitted (closes: #547679).
+ * Convert from CDBS to dh.
+ * Use exact-version dependencies in grub2 and grub-efi, to reduce
+ potential confusion.
+ * Raise priority of grub-common and grub-pc to optional (also done in
+ archive overrides).
+ * Copy-edit debian/presubj.
+ * Use 'mktemp -t' rather than hardcoding /tmp (closes: #589537).
+
+ [ Mario 'BitKoenig' Holbe ]
+ * Update /etc/grub.d/05_debian_theme to handle multiple entries in
+ GRUB_TERMINAL_OUTPUT (closes: #589322).
+
+ [ Updated translations ]
+ * Simplified Chinese (zh_CN.po) by YunQiang Su (closes: #589013).
+ * Russian (ru.po) by Yuri Kozlov (closes: #589244).
+ * Swedish (sv.po) by Martin Bagge / brother (closes: #589259).
+ * Bulgarian (bg.po) by Damyan Ivanov (closes: #589272).
+ * Indonesian (id.po) by Arief S Fitrianto (closes: #589318).
+ * Arabic (ar.po) by Ossama M. Khayat.
+ * Basque (eu.po) by Iñaki Larrañaga Murgoitio (closes: #589489).
+ * Persian (fa.po) by Bersam Karbasion (closes: #589544).
+ * Czech (cs.po) by Miroslav Kure (closes: #589568).
+ * Belarusian (be.po) by Viktar Siarheichyk (closes: #589634).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 21 Jul 2010 09:11:14 +0100
+
+grub2 (1.98+20100710-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Handle degraded RAID arrays in grub-probe and grub-setup.
+ - Fix gfxterm pager handling.
+
+ [ Fabian Greffrath ]
+ * Get value of correct debconf question when deciding whether to purge
+ /boot/grub (closes: #588331).
+
+ [ Colin Watson ]
+ * Generate device.map in something closer to the old ordering (thanks,
+ Vadim Solomin).
+
+ [ Updated translations ]
+ * Croatian (hr.po) by Josip Rodin, closes: #588350.
+ * French (fr.po) by Christian Perrier (closes: #588695).
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 12 Jul 2010 11:46:53 +0100
+
+grub2 (1.98+20100706-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - USB hub support.
+ - Fix GRUB_BACKGROUND configuration ordering.
+ - Fix corruption of first entry name in a reiserfs directory.
+ - Don't include MD devices when generating device.map (if you're using
+ RAID and upgraded through 1.98+20100702-1 or 1.98+20100705-1, you may
+ need to fix this up manually).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 06 Jul 2010 18:06:40 +0100
+
+grub2 (1.98+20100705-1) unstable; urgency=medium
+
+ * New Bazaar snapshot.
+ - Bidi and diacritics support.
+ + Use terminfo for ieee1275 terminals (closes: #586953).
+ - Don't use empty grub_device in EFI grub-install (closes: #587838).
+ - Fix grub-setup core.img comparison when not embedding (thanks, Matt
+ Kraai and M. Vefa Bicakci; closes: #586621).
+
+ * Update Source: in debian/copyright (thanks, Jörg Sommer).
+ * Convert by-id disk device names from device.map to traditional device
+ names for display (closes: #587951).
+ * Set urgency=medium. We've cleared out most of the apparent regressions
+ at this point, and #550704 is getting more and more urgent to fix in
+ testing.
+
+ -- Colin Watson <cjwatson@debian.org> Mon, 05 Jul 2010 02:09:58 +0100
+
+grub2 (1.98+20100702-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Use video functions in Linux loader rather than hardcoding UGA; load
+ all available video backends (closes: #565576, probably).
+ - Add support for initrd images on Fedora 13.
+ - Output grub.cfg stanzas for Xen (closes: #505517).
+ - Add 'cat --dos' option to treat DOS-style "\r\n" line endings as
+ simple newlines (closes: #586358).
+ - Change grub-mkdevicemap to emit /dev/disk/by-id/ names where possible
+ on Linux.
+ - Return CF correctly in mmap e820/e801 int15 hook (closes: #584846).
+ - The info documentation now has no broken references, although of
+ course it could still use more work (closes: #553460).
+ - Support GRUB_BADRAM in grub-mkconfig.
+ - Skip LVM snapshots (closes: #574863).
+
+ [ Colin Watson ]
+ * Mention grub-rescue-usb.img in grub-rescue-pc description (closes:
+ #586462).
+ * Add instructions for using grub-rescue-usb.img (closes: #586463).
+ * Remove /usr/lib/grub/mips-* from grub-common rather than the incorrect
+ /usr/lib/grub/mipsel-*, so that it stops clashing with grub-yeeloong;
+ add a versioned Replaces to grub-yeeloong just in case (closes:
+ #586526).
+ * Remove qemu-system build-dependency on hurd-i386, where it doesn't seem
+ to exist. Disable tests if qemu-system-i386 isn't available.
+ * Mark "upgrade-from-grub-legacy" paragraph in
+ grub-pc/chainload_from_menu.lst as untranslatable.
+ * Update Homepage field (thanks, Sedat Dilek).
+ * On Linux, if /boot/grub/device.map exists on upgrade to this version,
+ regenerate it to use stable device names in /dev/disk/by-id/. If it had
+ more than one entry, then display a critical-priority debconf note
+ (sorry, but it's better than silently breaking boot menu entries)
+ advising people to check custom boot menu entries and update them if
+ necessary (closes: #583271).
+ * Use 'set -e' rather than '#! /bin/sh -e' or '#! /bin/bash -e', to avoid
+ accidents when debugging with 'sh -x'.
+ * Store grub-pc/install_devices as persistent device names under
+ /dev/disk/by-id/ (closes: #554790). Migrate previous device names to
+ that, with explicit confirmation in non-trivial cases to make sure we
+ got the right ones. If the devices we were told to install to ever go
+ away, ask again. (This is based on the implementation in Ubuntu.)
+ * If grub-install fails during upgrade-from-grub-legacy, allow the user to
+ try again with a different device, but failing that cancel the upgrade
+ (closes: #587790).
+ * Remove numbering from patch files. The order is now explicit in a quilt
+ series file, and renumbering from time to time is tedious.
+
+ [ Updated translations ]
+ * Ukrainian (uk.po) by Yatsenko Alexandr / Borys Yanovych (closes:
+ #586611).
+ * Indonesian (id.po) by Arief S Fitrianto (closes: #586799).
+ * Swedish (sv.po) by Martin Bagge (closes: #586827).
+ * Persian (fa.po) by Behrad Eslamifar (closes: #587085).
+ * French (fr.po) by Christian Perrier (closes: #587383).
+ * Galician (gl.po) by Jorge Barreiro (closes: #587796).
+
+ [ Robert Millan ]
+ * Add commented GRUB_BADRAM example in debian/default/grub.
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 02 Jul 2010 17:42:56 +0100
+
+grub2 (1.98+20100617-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Fix i386-pc prefix handling with nested partitions (closes: #585068).
+
+ * When running grub-pc.postinst from upgrade-from-grub-legacy, tell it to
+ disregard the fact that /boot/grub/stage2 and /boot/grub/menu.lst still
+ exist (closes: #550477).
+ * Touch a marker file when grub-install is run but GRUB Legacy files are
+ still around. If that marker file is present, pretend that GRUB Legacy
+ files are missing when upgrading.
+ * If GRUB Legacy files are present when upgrading, scan boot sectors of
+ all disks for GRUB 2. If we find GRUB 2 installed anywhere, then ask
+ the user if they want to finish conversion to GRUB 2, and warn them that
+ not doing so may render the system unbootable (closes: #586143). Thanks
+ to Sedat Dilek for helping to narrow down this bug.
+ * Leaving grub-pc/install_devices empty makes sense in some situations,
+ but more often than not is a mistake. On the other hand, automatically
+ selecting all disk devices would upset some people too. Compromise by
+ simply asking for explicit confirmation if grub-pc/install_devices is
+ left empty, defaulting to false so that simply selecting all the
+ defaults in debconf can't leave you with an unbootable system (closes:
+ #547944, #557425).
+
+ -- Colin Watson <cjwatson@debian.org> Sat, 19 Jun 2010 01:31:40 +0100
+
+grub2 (1.98+20100614-2) unstable; urgency=low
+
+ * Build-depend on gcc-4.4-multilib on i386 and kopensolaris-i386 too, in
+ order to build grub-efi-amd64.
+ * Ignore non-option arguments in grub-mkconfig (closes: #586056).
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 16 Jun 2010 17:58:48 +0100
+
+grub2 (1.98+20100614-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Make target-related error messages from grub-mkimage slightly more
+ helpful (closes: #584415).
+ - Fix underquoting that broke savedefault (thanks, Mario 'BitKoenig'
+ Holbe; closes: #584812).
+ - Expand 'info grub' substantially, including a new section on
+ configuring authentication (closes: #584822).
+ - Give all manual pages proper NAME sections (closes: #496706).
+
+ * Update 915resolution from grub-extras:
+ - Fix a hang with 945GME (thanks, Sergio Perticone; closes: #582142).
+
+ [ Colin Watson ]
+ * Disable grub-emu on sparc for the time being. We're currently trying to
+ use TARGET_* flags to build it, which won't work.
+ * Don't build-depend on libsdl1.2-dev on hurd-i386. Although
+ libsdl1.2-dev exists there, it's currently uninstallable due to missing
+ libpulse-dev, and we can happily live without it for now.
+ * kfreebsd-amd64 needs gcc-4.4-multilib too (closes: #585668).
+ * Warn and return without error from prepare_grub_to_access_device if
+ /boot is a dm-crypt device (thanks, Marc Haber; closes: #542165).
+ * Make /etc/grub.d/05_debian_theme usable by shells other than bash
+ (thanks, Alex Chiang; closes: #585561).
+ * Remove grub-mkisofs leftovers from debian/copyright.
+ * Fix reversed sense of DEB_BUILD_OPTIONS=nocheck handling.
+ * Build-depend on qemu-system for grub-pc tests.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 15 Jun 2010 12:45:35 +0100
+
+grub2 (1.98+20100602-2) unstable; urgency=low
+
+ * Only build-depend on libdevmapper-dev on Linux architectures.
+ * Don't build-depend on libusb-dev on hurd-i386, where it doesn't seem to
+ be available.
+ * Fix printf format mismatch in disk/usbms.c (closes: #584474).
+ * Fix verbose error output when device-mapper isn't supported by the
+ running kernel (closes: #584196).
+ * Prepend "part_" to partmap module names in grub-mkconfig, in line with
+ grub-install (closes: #584426).
+
+ -- Colin Watson <cjwatson@debian.org> Fri, 04 Jun 2010 14:01:58 +0100
+
+grub2 (1.98+20100602-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Add btrfs probing support, currently only in the single-device case
+ (closes: #540786).
+ - Fix grub-emu build on mips/powerpc/sparc.
+ - Add safety check to make sure that /boot/grub/locale exists before
+ trying to probe it (closes: #567211).
+ - Several 'info grub' improvements, including a new section on
+ configuration file generation using grub-mkconfig which documents the
+ available keys in /etc/default/grub (closes: #497085).
+ - Many USB fixes.
+
+ [ Colin Watson ]
+ * Reorganise configure and build targets in debian/rules to use stamp
+ files. configure/* never existed and build/* was always a directory, so
+ make never considered either of them up to date (closes: #450505).
+ * Remove config.h.in from AUTOGEN_FILES, since autoheader doesn't
+ necessarily update it.
+ * Remove conf/gcry.mk from AUTOGEN_FILES, and conf/gcry.rmk from their
+ dependencies. autogen.sh runs util/import_gcry.py after autoconf et al,
+ so conf/gcry.rmk's timestamp will be later than some of the
+ autogenerated outputs.
+ * Go back to shipping rescue images in the grub-rescue-pc .deb itself
+ rather than generating them in the postinst. This means that (a) they
+ get removed when the package is removed (closes: #584176); (b) they are
+ listed in package metadata, as is proper for files in /usr (closes:
+ #584218); (c) grub-rescue-pc can potentially be used as a
+ build-dependency for other packages that need to build GRUB images into
+ installation media etc., without having to build-depend on grub-pc which
+ isn't coinstallable with other platform variants and does invasive
+ things in its postinst.
+ * Add grub-mkrescue patch from Thomas Schmitt to allow reducing the size
+ of xorriso-created images. Use this to ensure that
+ grub-rescue-floppy.img fits well within size limits (closes: #548320).
+
+ -- Colin Watson <cjwatson@debian.org> Thu, 03 Jun 2010 11:24:41 +0100
+
+grub2 (1.98+20100527-2) unstable; urgency=low
+
+ * Always override statically-linked-binary Lintian tag for kernel.img;
+ dynamic linking makes no sense here.
+ * kernel.img is stripped upstream where it can be, but override Lintian's
+ error for the cases where it can't.
+ * Override binary-from-other-architecture for kernel.img as well as *.mod
+ when building grub-efi-amd64 on i386.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 01 Jun 2010 13:48:14 +0100
+
+grub2 (1.98+20100527-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Support multiple terminals in grub-mkconfig, e.g.
+ GRUB_TERMINAL='serial console' (closes: #506707).
+ - Speed up consecutive hostdisk operations on the same device (closes:
+ #508834, #574088).
+ - Fix grammar error in grub-setup warning (closes: #559005).
+ - Use xorriso for image creation rather than embedding a modified copy
+ of mkisofs (closes: #570156).
+ - Issue an error rather than segfaulting if only some LVM component
+ devices are in device.map (closes: #577808).
+ - Fix typo in make_device_name which caused grub-probe problems on
+ systems with BSD disk labels (closes: #578201).
+ - Add DM-RAID probe support (closes: #579919).
+ - Include all gnumach kernels on Hurd, not just gnumach and gnumach.gz
+ (closes: #581584).
+
+ [ Colin Watson ]
+ * Restore TEXTDOMAINDIR correction in grub.d files, lost by mistake in a
+ merge. Noticed by Anthony Fok.
+ * Don't fail on purge if the ucf association has already been taken over
+ by a different grub package (closes: #574176).
+ * Add debian/grub-extras/*/conf/*.mk to AUTOGEN_FILES.
+ * Remove support for the lpia architecture, now removed from Ubuntu.
+ * Conflict with grub (<< 0.97-54) as well as grub-legacy.
+ * Build-depend on libdevmapper-dev for DM-RAID probe support.
+ * Switch to quilt.
+ * Suggest xorriso (>= 0.5.6.pl00) in grub-common, since grub-mkrescue now
+ needs it. Depend on it in grub-rescue-pc.
+ * Move grub-mkimage to grub-common, now that it only has one
+ implementation.
+ * Clean up temporary files used while building grub-firmware-qemu.
+ * Make grub-probe work with symlinks under /dev/mapper (closes: #550704).
+ * When upgrading a system where GRUB 2 is chainloaded from GRUB Legacy and
+ upgrade-from-grub-legacy has not been run, upgrade the chainloaded image
+ rather than confusing the user by prompting them where they want to
+ install GRUB (closes: #546822).
+ * Build-depend on libsdl1.2-dev for SDL support in grub-emu.
+ * Don't leak debconf's file descriptor to update-grub, so that the LVM
+ tools called from os-prober don't complain about it (closes: #549976).
+ Other leaks are not this package's fault, may not be bugs at all, and in
+ any case os-prober 1.36 suppresses the warnings.
+ * Build-depend on flex (>= 2.5.35).
+ * Build-depend on gcc-4.4-multilib on amd64.
+
+ [ Updated translations ]
+ * Slovenian (sl.po) by Vanja Cvelbar (closes: #570110).
+ * Vietnamese (vi.po) by Clytie Siddall (closes: #574578).
+ * Tamil (ta.po) by Tirumurti Vasudevan (closes: #578282).
+ * Portuguese (pt.po) by Tiago Fernandes (closes: #580140).
+ * Romanian (ro.po) by Eddy Petrișor / Andrei Popescu (closes: #583185).
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 01 Jun 2010 11:24:38 +0100
+
+grub2 (1.98-1) unstable; urgency=low
+
+ * New upstream release (closes: #572898).
+ - Fix grub-script-check to handle empty lines (closes: #572302).
+ - Fix offset computation when reading last sectors. Partition reads and
+ writes within and outside a partition (closes: #567469, #567884).
+ - Fix script execution error handling bug that meant that an error in a
+ menuentry's last statement caused the whole menuentry to fail (closes:
+ #566538, LP: #464743).
+ - Support GRUB_GFXPAYLOAD_LINUX (closes: #536453, LP: #416772).
+
+ [ Samuel Thibault ]
+ * Add GRUB_INIT_TUNE example to /etc/default/grub (closes: #570340).
+
+ [ Colin Watson ]
+ * Build-depend on libusb-dev so that grub-emu is reliably built with USB
+ support (closes: #572854).
+ * Update directions in debian/rules on exporting grub-extras to account
+ for it being maintained in Bazaar nowadays.
+ * Add myself to Uploaders.
+ * Acknowledge NMUs, thanks to Torsten Landschoff and Julien Cristau.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 09 Mar 2010 13:25:35 +0000
+
+grub2 (1.98~20100128-1.2) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Stop setting gfxpayload=keep (closes: #567245).
+
+ -- Julien Cristau <jcristau@debian.org> Sun, 14 Feb 2010 20:37:51 +0100
+
+grub2 (1.98~20100128-1.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Apply trivial patch (already merged upstream) fixing the offset
+ computation for non-cached reads (closes: #567637).
+
+ -- Torsten Landschoff <torsten@debian.org> Mon, 08 Feb 2010 22:15:01 +0100
+
+grub2 (1.98~20100128-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Fix corruption problem when reading files from CDROM. (Closes: #567219)
+
+ [ Felix Zielcke ]
+ * Never strip kernel.img in rules. Upstream already does it when it
+ can be done. (Closes: #561933)
+ * Bump Standards-Version to 3.8.4.
+
+ [ Robert Millan ]
+ * rules: Run the testsuite (make check) when building grub-pc.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Thu, 28 Jan 2010 16:28:45 +0100
+
+grub2 (1.98~20100126-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Includes mipsel-yeeloong port.
+
+ [ Robert Millan ]
+ * config.in: Lower priority of grub2/linux_cmdline_default.
+
+ [ Felix Zielcke ]
+ * Drop `CFLAGS=-O0' workaround on powerpc. Should be fixed correctly now.
+ * Ship grub-bin2h and grub-script-check in grub-common.
+ * Terminate NEWS.Debian with a blank line like lintian would suggest
+ if that check would be working correctly.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 26 Jan 2010 19:26:25 +0100
+
+grub2 (1.98~20100115-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Includes savedefault / grub-reboot branch.
+ - Includes Multiboot video support (from latest 1.x draft).
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Fri, 15 Jan 2010 18:15:26 +0100
+
+grub2 (1.98~20100110-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+
+ [ Robert Millan ]
+ * grub-rescue-pc.postinst: Fix image generation during upgrades.
+ (Closes: #564261)
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Sun, 10 Jan 2010 02:45:52 +0100
+
+grub2 (1.98~20100107-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+
+ [ Robert Millan ]
+ * grub-rescue-pc.postinst: Use grub-mkrescue for floppy as well.
+
+ [ Updated translations ]
+ * Chinese (zh_TW.po) by Tetralet. (Closes: #564044)
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Thu, 07 Jan 2010 17:56:10 +0100
+
+grub2 (1.98~20100101-1) unstable; urgency=high
+
+ * New Bazaar snapshot.
+ - Fix FTBS on sparc.
+
+ [ Robert Millan ]
+ * rules: Auto-update version from debian/changelog.
+
+ [ Felix Zielcke ]
+ * Add -O0 to CFLAGS on powerpc to avoid the `_restgpr_31_x in boot is
+ not defined' FTBFS.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Fri, 01 Jan 2010 00:31:37 +0100
+
+grub2 (1.98~20091229-1) unstable; urgency=high
+
+ * New Bazaar snapshot.
+ - Fix slowness when $prefix uses an UUID.
+ (Closes: #541145, LP: #420933)
+ - Correctly set TARGET_CFLAGS. (Closes: #562953)
+
+ [ Robert Millan ]
+ * grub-rescue-pc.postinst: Build USB rescue image.
+ * rules: Invoke configure with relative path. This makes binaries smaller,
+ since dprintf strings are constructed using this path.
+
+ [ Felix Zielcke ]
+ * Urgency=high due to RC bug fix.
+ * Fix version comparison in grub-common.preinst for handling obsolete
+ /etc/grub.d/10_freebsd. (Closes: #562921)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 29 Dec 2009 16:05:00 +0100
+
+grub2 (1.98~20091222-1) unstable; urgency=low
+
+ * New Baazar snapshot.
+ - Make 30_os-prober again dash compatible. (Closes: #562034)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 22 Dec 2009 12:50:57 +0100
+
+grub2 (1.98~20091221-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - Fix search command failing on some broken BIOSes. (Closes: #530357)
+
+ [ Felix Zielcke ]
+ * Add Replaces:/Conflicts: grub-linuxbios to grub-coreboot. (Closes: #561811)
+ * Delete obsolete /etc/grub.d/10_freebsd if it has not been modified,
+ else disable it. (Closes: #560346)
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Mon, 21 Dec 2009 22:04:17 +0100
+
+grub2 (1.98~20091210-1) unstable; urgency=low
+
+ * Version bump.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Mon, 14 Dec 2009 14:52:59 +0100
+
+grub2 (1.97+20091210-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ - patches/02_fix_mountpoints_in_mkrelpath.diff: Remove (merged).
+ - Fixes FTBFS on powerpc (again) and sparc.
+ - patches/903_grub_legacy_0_based_partitions.diff: Resync (merged into
+ debian branch).
+
+ * Fix dpkg dependency for lenny compatibility.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Thu, 10 Dec 2009 00:35:20 +0100
+
+grub2 (1.97+20091130-1) unstable; urgency=low
+
+ * New Bazaar snapshot.
+ * Enable ntldr-img from grub-extras.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Mon, 30 Nov 2009 02:33:03 +0100
+
+grub2 (1.97+20091125-2) unstable; urgency=low
+
+ [ Updated translations ]
+ * Bulgarian (bg.po) by Damyan Ivanovi (Closes: #558039)
+
+ [ Robert Millan ]
+ * control: Remove genisoimage from Build-Depends/Suggests (no longer
+ used).
+ * grub.d/05_debian_theme: Make output string distro-agnostic.
+
+ [ Felix Zielcke ]
+ * patches/02_fix_mountpoints_in_mkrelpath.diff: New patch to handle
+ mount points like the old shell function did. (Closes: #558042)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sun, 29 Nov 2009 21:38:00 +0100
+
+grub2 (1.97+20091125-1) unstable; urgency=low
+
+ [ Robert Millan ]
+ * New upstream snapshot.
+ - Fixes script parser load error.
+
+ * Add gettext to Build-Depends and gettext-base to grub-common's
+ Depends.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 25 Nov 2009 19:22:51 +0100
+
+grub2 (1.97+20091124-1) unstable; urgency=low
+
+ * New upstream snapshot.
+ - Fix grub-mkisofs related FTBFS on powerpc. (Closes: #557704)
+ - Create fake GRUB devices for devices not listed in device.map.
+ This also makes dmraid and multipath work as long as
+ search --fs-uuid works. (Closes: #442382, #540549, LP: #392136)
+ - rules: grub-emu is now built as a port.
+
+ [ Felix Zielcke ]
+ * Change the bt-utf-source build dependency to xfonts-unifont. It's
+ more complete, better maintained and grub-mkfont supports actually
+ more then BDF fonts as input, thanks to libfreetype.
+ * Use grub-probe to get the GRUB device of /boot/grub instead of
+ passing (hd0) to grub-install when creating the core.img with
+ chainloading. This avoids the (UUID=) hack slowness in case
+ /boot/grub is on a different disk then (hd0) in device.map.
+ * patches/903_grub_legacy_0_based_partitions.diff: Update.
+ * Add a build dependency on automake and python.
+ * Set TARGET_CC=$(CC) to really use gcc-4.4 everywhere. Also pass it
+ and CC as arguments to ./configure instead of env vars so they get
+ preserved.
+ * Ship grub-mkrelpath in grub-common.
+ * Ship the locale files in grub-common.
+ * Add a dependency on 'dpkg (>= 1.15.4) | install-info' for grub-common
+ as recommended by Policy and lintian.
+
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 24 Nov 2009 21:20:00 +0100
+
+grub2 (1.97+20091115-1) unstable; urgency=low
+
+ * New upstream snapshot.
+ - Fix security problem with password checking. (Closes: #555195)
+ - Fix the generated GNU/Hurd menu entries and also add support for
+ it in 30_os-prober. (Closes: #555188)
+ - Same grub-mkrescue for grub-pc and grub-coreboot, used by
+ grub-rescue-pc during postinst now. (Closes: #501867)
+
+ [ Felix Zielcke ]
+ * Ship grub-mkisofs in grub-common.
+ * patches/002_grub.d_freebsd.in.diff: Remove (merged upstream).
+ * patches/906_grub_extras.diff: Remove. Superseded by GRUB_CONTRIB variable
+ in recent upstream trunk.
+ * rules: Export GRUB_CONTRIB to enable grub-extras add-ons.
+ * Pass --force to grub-install in the postinst. (Closes: #553415)
+ * Don't strip debug symbols from grub-emu. It's meant for debugging
+ and with them it's much more useful.
+ * Ship grub-mkfloppy in grub-pc.
+ * Revert the Replaces: grub-common to (<= 1.96+20080413-1) on the
+ grub-pc package. It was wrongly modified long ago.
+
+ [ Robert Millan ]
+ * copyright: Document mkisofs.
+ * control: Update Vcs- fields (moved to Bazaar).
+ * rules: Update debian/legacy/update-grub rule to Bazaar.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sun, 15 Nov 2009 19:13:31 +0100
+
+grub2 (1.97-1) unstable; urgency=low
+
+ [ Robert Millan ]
+ * patches/905_setup_force.diff: Remove, no longer needed as of
+ grub-installer >= 1.47.
+ * grub.d/05_debian_theme: Attempt to source grub_background.sh from
+ desktop-base (Needed for #495282, #495616, #500134, see also
+ #550984).
+
+ [ Felix Zielcke ]
+ * Add a build dependency on texinfo.
+ * Fix little typo in /etc/default/grub. (LP: #457703)
+
+ [ Updated translations ]
+ * Finnish (fi.po) by Esko Arajärvi. (Closes: #551912)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sun, 25 Oct 2009 19:50:21 +0100
+
+grub2 (1.97~beta4-1) unstable; urgency=low
+
+ * New upstream beta release.
+
+ [ Felix Zielcke ]
+ * Change the Recommends: os-prober to (>= 1.33).
+ * patches/907_grub.cfg_400.diff: Really add it. Somehow it was a 0 byte file.
+ (Closes: #547409)
+ * Convert newlines back to spaces when parsing kopt from
+ GRUB Legacy's menu.lst, before giving the value to Debconf.
+ Thanks to Colin Watson. (Closes: #547649)
+ * Ship the info docs in grub-common. (Closes: #484074)
+ * Remove generated /usr/share/info/dir* files.
+ * Update the presubj bug file and also install it for grub-common.
+
+ [ Robert Millan ]
+ * Enable ZFS and 915resolution in grub-extras (now requires explicit
+ switch).
+ * grub-common conflicts with grub-doc (<< 0.97-32) and grub-legacy-doc
+ (<< 0.97-59).
+ * Move grub-emu to a separate package.
+
+ [ Updated translations ]
+ * Japanese (ja.po) by Hideki Yamane. (Closes: #549599)
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Mon, 05 Oct 2009 20:03:04 +0200
+
+grub2 (1.97~beta3-1) unstable; urgency=high
+
+ * New upstream beta release.
+ - Make it more clear how to use /etc/grub.d/40_custom. (Closes: #545153)
+ - fix a serious memory corruption in the graphical subsystem.
+ (Closes: #545364, #544155, #544639, #544822, LP: #424503)
+ - patches/003_grub_probe_segfault.diff: Remove (merged).
+
+ * Change the watch file so upstream beta releases are recognized.
+ * Include /etc/default/grub in bug reports.
+ * Recommend os-prober (>= 1.32). (Closes: #491872)
+ * Change the gcc-multilib [sparc] build dependency to gcc-4.4-multilib
+ [sparc].
+ * patches/907_grub.cfg_400.diff: New patch to make grub.cfg again mode
+ 444 if it does not contain a password line.
+ * Use `su' in the bug reporting script to read grub.cfg in case the user
+ is not allowed to read it.
+ * Readd grub-pc/kopt-extracted template.
+
+ [ Updated translations ]
+ * Brazilian Portuguese (pt_BR.po) by Flamarion Jorge.
+ * Japanese (ja.po) by Hideki Yamane. (Closes: #545331)
+ * Spanish (es.po) by Francisco Javier Cuadrado. (Closes: #545566)
+ * Italian (it.po) by Luca Monducci. (Closes: #546035)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sat, 12 Sep 2009 15:28:20 +0200
+
+grub2 (1.97~beta2-2) unstable; urgency=low
+
+ [ Updated translations ]
+ * Dutch (nl.po) by Paul Gevers. (Closes: #545050)
+
+ [ Felix Zielcke ]
+ * Move GRUB Legacy's grub-set-default to /usr/lib/grub-legacy in
+ preparation for GRUB 2's grub-set-default.
+ * Remove password lines in bug script.
+
+ [ Robert Millan ]
+ * Do not conflict with `grub' dummy package (this prevented upgrades).
+ * patches/003_grub_probe_segfault.diff: Disable file test codepath, which
+ wasn't normally used before.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sat, 05 Sep 2009 00:27:22 +0200
+
+grub2 (1.97~beta2-1) unstable; urgency=low
+
+ * New upstream beta release.
+ - Fix loading of FreeBSD modules. (Closes: #544305)
+
+ [ Updated translations ]
+ * French (fr.po) by Christian Perrier. (Closes: #544320)
+ * Czech (cs.po) by Miroslav Kure. (Closes: #544327)
+ * Belarusian (be.po) by Hleb Rubanau.
+ * Arabic (ar.po) by Ossama M. Khayat.
+ * Catalan (ca.po) by Juan Andrés Gimeno Crespo.
+ * Russian (ru.po) by Yuri Kozlov. (Closes: #544730)
+ * Swedish (sv.po) by Martin Ã…gren. (Closes: #544759)
+ * Brazilian Portuguese (pt_BR.po) by Flamarion Jorge. (Closes: #544810)
+ * German (de.po) by Helge Kreutzmann. (Closes: #544912)
+
+ [ Robert Millan ]
+ * Build with GCC 4.4.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Fri, 04 Sep 2009 14:40:20 +0200
+
+grub2 (1.97~beta1-1) unstable; urgency=low
+
+ * New upstream beta release.
+
+ [ Updated translations ]
+ * German (de.po) by Helge Kreutzmann. (Closes: #544261)
+ * Asturian (ast.po) by Marcos.
+ * Georgian (ka.po) by Aiet Kolkhi.
+
+ [ Robert Millan ]
+ * Merge config, templates, postinst, postrm, dirs and install files
+ into a single source.
+ * Disable Linux-specific strings on GNU/kFreeBSD. Enable translations
+ in grub2/linux_cmdline_default. Add grub2/kfreebsd_* strings (still
+ unused).
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sun, 30 Aug 2009 18:01:40 +0200
+
+grub2 (1.96+20090829-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Fix filesystem mapping on GNU/kFreeBSD. (Closes: #543950)
+
+ * New grub-extras SVN snapshot.
+ - Add 915resolution support to the GMA500 (poulsbo) graphics chipset.
+ Thanks to Pedro Bulach Gapski. (Closes: #543917)
+
+ * Use `cp -p' to copy /usr/share/grub/default/grub to the temporary
+ file to preverse permissions.
+ * Remove also efiemu files from /boot/grub on purge if requested.
+ * Check that GRUB_CMDLINE_LINUX and GRUB_CMDLINUX_LINUX_DEFAULT is at
+ the start of line in *.postinst.
+ * Don't check that $GRUB_CMDLINE_LINUX{,DEFAULT} are non empty strings
+ in *.config.
+ * Add empty GRUB_CMDLINE_LINUX to /usr/share/grub/default/grub.
+ * Factorise the editing of the temporary file. Thanks to Martin F
+ Krafft.
+ * Read in /etc/default/grub in *.config files.
+
+ [ Updated translations ]
+ * French (fr.po) by Christian Perrier. (Closes: #544023)
+ * Russian (ru.po) by Yuri Kozlov. (Closes: #544077)
+ * Italian (it.po) by Luca Monducci. (Closes: #544200)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sat, 29 Aug 2009 17:01:17 +0200
+
+grub2 (1.96+20090826-3) unstable; urgency=low
+
+ * Add missing quotes in grub-pc.config and *.postinst.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 26 Aug 2009 19:14:23 +0200
+
+grub2 (1.96+20090826-2) unstable; urgency=low
+
+ * Really use the correct templates in grub-pc.config. ARGS.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 26 Aug 2009 14:10:41 +0200
+
+grub2 (1.96+20090826-1) unstable; urgency=low
+
+ * New SVN snapshot.
+
+ * Use the right templates in grub-pc.config. (Closes: #543615)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 26 Aug 2009 11:00:36 +0200
+
+grub2 (1.96+20090825-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Enable gfxterm only if there's a suitable video backend and don't
+ print an error if not. (Closes: #520846)
+
+ [ Felix Zielcke ]
+ * Copy unicode.pf2 instead of ascii.pf2 to /boot/grub in grub-pc
+ postinst (Closes: #542314).
+ * Update Standards version to 3.8.3.
+ * Use DEB_HOST_ARCH_CPU for the generation of the lintian overrides.
+ * Fix calling the grub-pc/postrm_purge_boot_grub template in
+ grub-pc.postinst.
+ * Handle GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT via
+ debconf. Thanks to Martin F. Krafft and Colin Watson for idea and
+ hints.
+ * Use ucfr --force when /etc/default/grub is registered to a grub-* package.
+ * Use #!/bin/sh in *.config and fix a small bashism in grub-pc.config.
+
+ [ Robert Millan ]
+ * patches/907_terminal_output_workaround.diff: Remove. It seems that
+ it wasn't really necessary.
+ * grub-pc.postinst: Avoid printing an error if /etc/kernel-img.conf
+ doesn't exist, because it is misleading. We simply refrain from
+ fixing it and move along.
+ * grub-pc.postinst: Don't schedule generation of grub.cfg via "grub-install"
+ code path unless we actually run grub-install.
+ * grub-pc.postinst: Only copy unicode.pf2 and moreblue-orbit-grub.png when
+ /boot/grub/grub.cfg is scheduled to be generated.
+ * legacy/upgrade-from-grub-legacy: Reset grub-pc/install_devices.
+ Thanks Colin Watson. (Closes: #541230)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 25 Aug 2009 21:45:24 +0200
+
+grub2 (1.96+20090808-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Fix XFS with inode size different then 256. (Closes: #528761)
+ - Add support for multiple LVM metadata areas. (LP: #408580)
+ - patches/008_dac_palette_width.diff: Remove. (merged)
+ - Prefer unicode over ascii font. (LP: #352034)
+
+ [ Felix Zielcke ]
+ * Fix the generation of the lintian override for efiemu64.o.
+ * Remove the Conflicts dmsetup.
+ * Use ?= for setting DEB_HOST_ARCH.
+ * Document GRUB_DISABLE_LINUX_RECOVERY in /etc/default/grub.
+ (Closes: #476536 LP: #190207)
+ * Add docs/grub.cfg to examples.
+ * patches/01_uuids_and_lvm_dont_play_along_nicely.diff: Updated to
+ also disable UUIDs on LVM over RAID.
+ * Add a debconf prompt to remove all grub2 files from /boot/grub on
+ purge. (Closes: #527068, #470400)
+ * Move the Suggests: os-prober from grub-pc to grub-common.
+ * patches/901_dpkg_version_comparison.diff: Updated.
+ * Update the Replaces on grub-common for the other packages to (<<
+ 1.96+20080831-1). (Closes: #540492)
+
+ [ Robert Millan ]
+ * Reorganize grub-pc.{config,postinst} logic. The idea being that if there's
+ no trace of GRUB Legacy, the grub-pc/install_devices template will be
+ shown even if this is the first install.
+ * When setting grub-pc/install_devices, obtain input dynamically from
+ grub-mkdevicemap (rather than devices.map). (Closes: #535525)
+ * Add a note to grub-pc/install_devices template that it's also possible
+ to install GRUB to a partition boot record.
+ * patches/002_grub.d_freebsd.in.diff: New patch. Reimplement
+ 10_freebsd.in to handle multiple kernel versions & acpi.ko.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Mon, 10 Aug 2009 18:49:52 +0200
+
+grub2 (1.96+20090725-1) unstable; urgency=high
+
+ * New SVN snapshot.
+ - Don't add drivemap call with Windows Vista/7. It breaks Win 7.
+ (LP: #402154)
+
+ [ Felix Zielcke ]
+ * Don't build grub-efi-amd64 on hurd-i386.
+ * Change DEB_BUILD_ARCH to DEB_HOST_ARCH in the check for sparc.
+ * Don't add the lintian override for kernel.img for sparc and grub-pc.
+ * Add a lintian override for binary-from-other-architecture for
+ grub-efi-amd64 and grub-pc on i386.
+ * Use wildcards in the lintian overrides.
+ * Add a Conflicts/Replaces for all packages except grub-common.
+ (Closes: #538177)
+
+ [ Robert Millan ]
+ * 008_dac_palette_width.diff: New patch. Fix blank screen when booting
+ Linux with vga= parameter set to a packed color mode (<= 8-bit).
+ (Closes: #535026)
+ * Set urgency=high because #535026 affects 1.96+20090709-1 which is in
+ testing now.
+ * patches/907_terminal_output_workaround.diff: Work around recent regression
+ with terminal_output command (not critical, just breaks gfxterm).
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Sat, 25 Jul 2009 19:00:53 +0200
+
+grub2 (1.96+20090721-4) unstable; urgency=low
+
+ * Place grub-ofpathname only in grub-common. (Closes: #537999)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 22 Jul 2009 13:38:24 +0200
+
+grub2 (1.96+20090721-3) unstable; urgency=low
+
+ * Don't strip kernel.img on sparc.
+ * Suggest efibootmgr on grub-efi-{amd64,ia32}.
+ * Pass --disable-grub-fstest to configure. (Closes: #537897)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 21 Jul 2009 21:46:01 +0200
+
+grub2 (1.96+20090721-2) unstable; urgency=low
+
+ * Add back Conflicts/Replaces grub.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 21 Jul 2009 11:24:45 +0200
+
+grub2 (1.96+20090721-1) unstable; urgency=low
+
+ * New SVN snapshot.
+
+ * Change License of my update-grub(8) and update-grub2(8) manpages to
+ GPL3+ to match new copyright file.
+ * Merge from Ubuntu: Don't build grub-efi-amd64 on lpia.
+ * Don't pass `--enable-efiemu' to configure. On kfreebsd-i386 it won't
+ compile and it should be now auto detected if it's compilable.
+ (Closes: #536783)
+ * Don't build grub-efi-amd64 on kfreebsd-i386. It lacks 64bit compiler
+ support.
+ * Rename the lintian override for kernel.elf to kernel.img.
+ * Strip kernel.img not kernel.elf, but not in the case of grub-pc.
+ * Rename the Conflicts/Replaces grub to grub-legacy. (Closes: #537824)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 21 Jul 2009 10:50:20 +0200
+
+grub2 (1.96+20090709-1) unstable; urgency=low
+
+ * New SVN snapshot.
+
+ * control (Build-Depends): Add gcc-multilib [sparc].
+ * copyright: Rewrite using DEP-5 format.
+ * Merge grub-extras into the package, and integrate it with GRUB's
+ build system.
+ - patches/906_grub_extras.diff
+ - rules
+ - copyright
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Thu, 09 Jul 2009 00:26:49 +0200
+
+grub2 (1.96+20090702-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ * rules: Remove duplicated files in sparc64-ieee1275 port.
+ * rules: Comment out -DGRUB_ASSUME_LINUX_HAS_FB_SUPPORT=1 setting. We'll
+ re-evaluate using it when it's more mature. (Closes: #535026).
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Thu, 02 Jul 2009 13:23:51 +0200
+
+grub2 (1.96+20090629-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Misc fixes in Linux loader.
+
+ * control (grub-firmware-qemu): Make it buildable only on i386/amd64.
+ * control: Add sparc (grub-ieee1275), remove remnants of ppc64.
+ * rules: Include all modules in grub-firmware-qemu build.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Mon, 29 Jun 2009 19:22:37 +0200
+
+grub2 (1.96+20090628-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ * Re-enable QEMU port.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Sun, 28 Jun 2009 01:11:10 +0200
+
+grub2 (1.96+20090627-2) unstable; urgency=low
+
+ * Disable QEMU port untill it goes through NEW.
+ * Upload to unstable.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Sat, 27 Jun 2009 18:40:17 +0200
+
+grub2 (1.96+20090627-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - Fix parsing of --output in grub-mkconfig. (Closes: #532956)
+
+ [ Felix Zielcke ]
+ * Use ucfr --force in grub-ieee1275.postinst in case we're upgrading
+ from previous version. It registered /etc/default/grub wrongly with
+ package iee1275.
+ * Drop the build dependency on libc6-dev-i386.
+ * Remove ppc64 from the Architectures. It's totally dead.
+ * Add a note to /etc/default/grub that update-grub needs to be run to
+ update grub.cfg. (Closes: #533026)
+ * Fix the svn-snapshot rule.
+ * Update Standards version to 3.8.2. No changes needed.
+
+ [ Robert Millan ]
+ * legacy/upgrade-from-grub-legacy: Invoke grub-pc.postinst directly rather
+ than dpkg-reconfigure. Since we pretend we're upgrading, it will DTRT.
+ * Add grub-firmware-qemu package.
+ - patches/008_qemu.diff: QEMU port (patch from upstream).
+ - control (grub-firmware-qemu): New package.
+ - rules: Add grub-firmware-qemu targets.
+ - debian/grub-firmware-qemu.dirs
+ - debian/grub-firmware-qemu.install
+ * patches/906_revert_to_linux16.diff: Remove, now that gfxpayload is
+ supported.
+
+ -- Robert Millan <rmh.debian@aybabtu.com> Sat, 27 Jun 2009 00:46:23 +0200
+
+grub2 (1.96+20090611-1) experimental; urgency=low
+
+ * New SVN snapshot.
+
+ * Append .diff to patches/01_uuids_and_lvm_dont_play_along_nicely so
+ it gets really applied.
+ * Drop completely the build dependency on gcc-multilib.
+ * Instead of arborting in the preinst if /etc/kernel-img.conf still
+ contains /sbin/update-grub, change the file with sed. Policy allows
+ thisi, because it's not a conffile, according to Colin Watson.
+ * Change /etc/default/grub to an ucf managed file instead of dpkg
+ conffile.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Fri, 12 Jun 2009 11:46:24 +0200
+
+grub2 (1.96+20090609-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - Fix variable parsing inside strings. (Closes: #486180)
+ - Add `true' command. (Closes: #530736)
+
+ [ Robert Millan ]
+ * Split grub-efi in grub-efi-ia32 and grub-efi-amd64, both available
+ on i386 and amd64. (Closes: #524756)
+ * Add kopensolaris-i386 to arch list.
+
+ [ Felix Zielcke ]
+ * Add a NEWS entry about the grub-efi split.
+ * Drop the build dependency on gcc-multilib for all *i386.
+ * Change upgrade-from-grub-legacy to use `dpkg-reconfigure grub-pc' to
+ install grub2 into MBR.
+
+ [ New translations ]
+ * Catalan (ca.po) by Jordi Mallach.
+
+ [ Updated translations ]
+ * Spanish (es.po) by Francisco Javier Cuadrado. (Closes: #532407)
+
+ -- Jordi Mallach <jordi@debian.org> Tue, 09 Jun 2009 19:21:15 +0200
+
+grub2 (1.96+20090603-1) unstable; urgency=low
+
+ * New SVN snapshot.
+
+ * Abort the install of grub-pc if /etc/kernel-img.conf still contains
+ /sbin/update-grub (Closes: #500631).
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 03 Jun 2009 20:01:11 +0200
+
+grub2 (1.96+20090602-1) unstable; urgency=low
+
+ * New SVN snapshot.
+
+ [ Felix Zielcke ]
+ * Skip floopies in the grub-install debconf prompt in grub-pc postinst.
+ Patch by Fabian Greffrath. (Closes: #530848)
+
+ [ Robert Millan ]
+ * Change Vcs-Browser field to viewsvn.
+
+ [ Felix Zielcke ]
+ * Change Vcs-Svn field to point to the trunk. (Closes: #531391)
+ * patches/01_uuids_and_lvm_dont_play_along_nicely: New patch.
+ On Debian root=UUID= with lvm still doestn't work so disable it.
+ (Closes: #530357)
+ * Remove Otavio Salvador from Uploaders with his permission.
+ * add grub-pc.preinst
+
+ -- Felix Zielcke <fzielcke@z-51.de> Wed, 03 Jun 2009 14:42:11 +0200
+
+grub2 (1.96+20090523-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Add drivemap command, similar to grub-legacy's map command.
+ (Closes: 503630)
+ - Export GRUB_TERMINAL_INPUT in grub-mkconfig. (Closes: #526741)
+
+ [ Robert Millan ]
+ * rules: Set GRUB_ASSUME_LINUX_HAS_FB_SUPPORT=1 in CFLAGS.
+ * patches/905_setup_force.diff: Relax blocklist warnings.
+ * patches/906_revert_to_linux16.diff: Keep using linux16 for now.
+
+ [ Felix Zielcke ]
+ * patches/07_core_in_fs.diff: Updated.
+ * Remove /etc/grub.d/10_hurd on non-Hurd systems in the grub-common
+ preinst. Likewise for 10_freebsd for non kFreebsd and 10_linux on
+ kFreebsd and Hurd. (Closes: #523777)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sat, 23 May 2009 20:05:10 +0200
+
+grub2 (1.96+20090504-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - Add support for parttool command, which can be used to hide partitions.
+ (Closes: #505905)
+ - Fix a segfault with LVM on RAID. (Closes: #520637)
+ - Add support for char devices on (k)FreeBSD. (Closes: #521292)
+ - patches/08_powerpc-ieee1275_build_fix.patch: Remove (merged).
+
+ [ Updated translations ]
+ * Basque (eu.po) by Piarres Beobide. (Closes: #522457)
+ * German (de.po) by Helge Kreutzmann. (Closes: #522815)
+
+ [ Robert Millan ]
+ * Update my email address.
+ * Remove 04_uuids_and_abstraction_dont_play_along_nicely.diff now that
+ bugs #435983 and #455746 in mdadm and dmsetup have been fixed.
+
+ [ Felix Zielcke ]
+ * Place new grub-dumpbios in grub-common.
+ * Add lpia to the archictectures to reduce the ubuntu delta.
+ * Add a manpage for the update-grub and update-grub2 stubs, written by
+ me. (Closes: #523876)
+ * Suggest genisoimage on grub-pc and grub-ieee1275, because grub-mkrescue
+ needs it to create a cd image. (Closes: #525845)
+ * Add a dependency on $(AUTOGEN_FILES) for the configure/grub-common target,
+ this is needed now that upstream removed the autogenerated files from SVN.
+ * Add `--enable-efiemu to' `./configure' flags.
+ * Add a build dependency on gcc-multilib for i386.
+ * Drop alternate build dependency on gcc-4.1 (<< 4.1.2).
+
+ -- Felix Zielcke <fzielcke@z-51.de> Mon, 04 May 2009 21:01:22 +0200
+
+grub2 (1.96+20090402-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - Fix regression in disk/raid.c. (Closes: #521897, #514338)
+ - Fix handling of filename string lengths in HFS.
+ (Really closes: #516458).
+ * Add myself to Uploaders.
+ * Add patch 08_powerpc-ieee1275_build_fix.patch to fix powerpc-ieee1275
+ builds which were lacking header files for kernel_elf_HEADERS. Thanks
+ Vladimir Serbinenko.
+
+ -- Jordi Mallach <jordi@debian.org> Fri, 03 Apr 2009 20:58:37 +0200
+
+grub2 (1.96+20090401-1) experimental; urgency=low
+
+ [ Felix Zielcke ]
+ * New SVN snapshot.
+ - Pass grub's gfxterm mode to Linux kernel. (Closes: #519506)
+ - Fix ext4 extents on powerpc. (Closes: #520286)
+
+ [ Robert Millan ]
+ * Remove grub-of transitional package (Lenny had grub-ieee1275 already).
+ * Fix kopt parsing in grub-pc.config. Thanks Marcus Obst. (Closes: #514837)
+ * Add debconf template to automatically run grub-install during upgrades
+ (prior user confirmation). (Closes: #514705)
+
+ -- Robert Millan <rmh@aybabtu.com> Wed, 01 Apr 2009 01:19:45 +0200
+
+grub2 (1.96+20090317-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Fix loading of files with underscore in HFS. (Closes: #516458)
+
+ * Update Standards version to 3.8.1. No changes needed.
+
+ [ Updated translations ]
+ * Brazilian Portuguese (pt_BR.po) by Flamarion Jorge. (Closes: #519417)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 17 Mar 2009 14:42:10 +0100
+
+grub2 (1.96+20090309-1) unstable; urgency=low
+
+ * New SVN snapshot.
+
+ -- Felix Zielcke <fzielcke@z-51.de> Mon, 09 Mar 2009 10:03:13 +0100
+
+grub2 (1.96+20090307-1) unstable; urgency=low
+
+ * New SVN snapshot.
+ - Add support for /dev/md/dNNpNN mdraid devices. (Closes: #509960)
+ - Add new PF2 fontengine. (Closes: #510344)
+ - Avoid mounting ext2 partitions with backward-incompatible features.
+ (Closes: #502333)
+ - Try to avoid false positives with FAT. (Closes: #514263)
+
+ [ Felix Zielcke ]
+ * Remove build-dependency on unifont package and add one for bf-utf-source
+ package and libfreetype6-dev
+ * grub-pc.postinst: Copy new ascii.pf2 instead of old ascii.pff to /boot/grub.
+ * Add `--enable-grub-mkfont' to configure flags.
+ * Put new grub-mkfont in grub-common package.
+ * Add a dependency for ${misc:Depends} to all packages to make lintian a bit
+ more happy.
+ * Detect when grub-setup leaves core.img in filesystem, and include that
+ info in bug report templates.
+ - debian/patches/07_core_in_fs.diff
+ - debian/script
+ * Add myself to Uploads and add `DM-Upload-Allowed: yes' tag.
+
+ [ Updated translations ]
+ * Asturian (ast.po) by Marcos Alvarez Costales. (Closes: #511144)
+ * Traditional Chinese (zh_TW.po) by Tetralet. (Closes: #513918)
+ * Belarusian (be.po) by Pavel Piatruk. (Closes: #516243)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Sat, 07 Mar 2009 11:54:43 +0100
+
+grub2 (1.96+20081201-1) experimental; urgency=low
+
+ * New SVN snapshot.
+
+ -- Robert Millan <rmh@aybabtu.com> Mon, 1 Dec 2008 00:07:31 +0100
+
+grub2 (1.96+20081120-1) experimental; urgency=low
+
+ * New SVN snapshot.
+
+ * Update to new debian theme.
+ - grub-pc.postinst: Switch to moreblue-orbit-grub.png.
+ - grub.d/05_debian_theme: Likewise.
+ * grub.d/05_debian_theme:
+ - Update to use new grub-mkconfig_lib instead of the deprecated
+ update-grub_lib.
+ - Update to check if `GRUB_TERMINAL_OUTPUT' is `gfxterm' instead of
+ `GRUB_TERMINAL'.
+
+ [ Updated translations ]
+ * Romanien (ro.po) by Eddy Petrișor. (Closes: #506039)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Thu, 20 Nov 2008 20:25:56 +0100
+
+grub2 (1.96+20081108-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - Add support for /dev/md/N style mdraid devices. (Closes: #475585)
+ - Handle LVM dash escaping. (Closes: #464215)
+ - Use case insensitive match in NTFS. (Closes: #497889)
+ - Use hd%d drive names in grub-mkdevicemap for all architectures.
+ (Closes: #465365)
+ - Handle LVM circular metadata. (Closes: #462835, #502953)
+ - Fix NULL dereference and failure paths in LVM. Thanks Guillem Jover.
+ (Closes: #500482)
+ - Provides GRUB header files (only in grub-common).
+
+ [ Updated translations ]
+ * Dutch (nl.po) by Paul Gevers. (Closes: #500514)
+ * French (fr.po) by Christian Perrier. (Closes: #503708)
+ * Georgian (ka.po) by Aiet Kolkhi. (Closes: #503715)
+ * Czech (cs.po) by Miroslav Kure. (Closes: #503809)
+ * German (de.po) by Helge Kreutzmann. (Closes: #503841)
+ * Japanese (ja.po) by Hideki Yamane. (Closes: #503869)
+ * Italian (it.po) by Luca Monducci. (Closes: #504076)
+ * Swedish (sv.po) by Martin Ã…gren. (Closes: #504207)
+ * Arabic (ar.po) by Ossama Khayat. (Closes: #504254)
+ * Portuguese (pt.po) by Miguel Figueiredo. (Closes: #504280)
+ * Russian (ru.po) by Yuri Kozlov. (Closes: #504324)
+ * Finnish (fi.po) by Esko Arajärvi. (Closes: #504310)
+ * Basque (eu.po) by Piarres Beobide. (Closes: #504466)
+ * Dutch (nl.po) by Paul Gevers. (Closes: #504683)
+
+ [ Felix Zielcke ]
+ * patches/01_grub_legacy_0_based_partitions.diff: Rename to
+ * patches/903_grub_legacy_0_based_partitions.diff: this and adapt for
+ s/biosdisk.c/hostdisk.c/ rename upstream.
+ * patches/03_disable_floppies.diff
+ patches/904_disable_floppies.diff: Likewise.
+ * update-grub has been renamed to grub-mkconfig, so provide a stub for
+ compatibility.
+ * Make grub-pc/linux_cmdline debconf template translatable. (Closes: #503478)
+ * Remove ro.po and ta.po. They don't contain a single translated
+ message.
+
+ [ Robert Millan ]
+ * control: Make grub-common dependency = ${binary:Version}.
+ * default/grub: Set GRUB_CMDLINE_LINUX=quiet to syncronize with
+ default D-I settings.
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 8 Nov 2008 13:54:10 +0100
+
+grub2 (1.96+20080831-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - patches/00_fix_double_prefix.diff: Remove (merged). (Closes: #487565)
+ - patches/00_getline.diff: Remove (merged). (Closes: #493289)
+ - Handle errors in RAID/LVM scan routine (rather than letting the upper
+ layer cope with them). (Closes: #494501, #495049)
+ - patches/901_linux_coreboot.diff: Remove (replaced).
+ - Add support for GFXMODE variable (Closes: #493106)
+ - Skips /dev/.* in grub-probe. (Closes: #486624)
+ - RAID code has various fixes. (Closes: #496573)
+ - Buffered file read is now used to read the background image faster.
+ (Closes: #490584)
+
+ * We are already using LZMA, because upstream includes it's own lzma encoder,
+ so drop completely the liblzo handling in control and rules files.
+
+ [ Felix Zielcke ]
+ * Remove the 1.95 partition numbering transition debconf warning
+ from grub2 package and removed it from all languages (*.po).
+ (Closes: #493744)
+ * Add a comment for the new GFXMODE in default/grub.
+ * debian/rules:
+ - Remove 2 ./configure options which it didn't understand.
+ - New grub-mkelfimage belongs to grub-common.
+ * debian/control:
+ - Change debhelper compat level to 7 and build depend on it >= 7.
+ - Remove ${misc:Depend} dependency on all packages except grub-pc which is
+ the only one using debconf.
+ - Replace deprecated ${Source-Version} with ${source:Version} for <<
+ dependency and with ${build:Version} for = ones.
+ - Remove versioned dependency of Build-Depends patchutils and cdbs,
+ because etch has newer versions then the one used.
+ - Remove dpkg-dev completely from Build-Depends because it's
+ build-essentail and a non versioned dependency results in a lintian error.
+ - Remove Conflict/Replaces pupa, it has been removed from Debian 2004.
+ - Change build-dependency of unifont-bin to unifont (>= 1:5.1.20080820),
+ it's the new package containing unifont.hex and that version to avoid
+ licensing problems (Closes: #496061)
+ - Remove Jason Thomas from Uploaders with his permission.
+ * Preserve arguments in update-grub2 stub. (Closes: #496610)
+
+ [ Updated translations ]
+ * Japanese (ja.po) by Hideki Yamane (Closes: #493347)
+
+ [ Robert Millan ]
+ * Move a few files to grub-common and remove them from the arch-
+ specific packages.
+ * patches/02_old_linux_version_comparison.diff: Replace with ...
+ * patches/901_dpkg_version_comparison.diff: ... this.
+ Use dpkg --compare-versions in update-grub. (Closes: #494158)
+ * patches/03_disable_floppies.diff: Free .drive struct member when skipping
+ floppy drives. (Closes: #496040)
+ * patches/902_boot_blocklist_hack.diff: Support separate /boot when using
+ blocklists. (Closes: #496820, #489287, #494589)
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 31 Aug 2008 18:40:09 +0200
+
+grub2 (1.96+20080730-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - patches/00_fix_overflow.diff: Remove (merged).
+ - patches/00_uuid_boot.diff: Remove (merged).
+ - patches/00_raid_duped_disks.diff: Remove (merged).
+ - patches/00_xfs.diff: Remove (merged).
+ - patches/00_strengthen_apple_partmap_check.diff: Remove (merged).
+ - patches/00_skip_dev_dm.diff: Remove (merged).
+
+ * patches/901_linux_coreboot.diff: Implements Linux load on Coreboot
+ (patch from Coresystems).
+
+ * grub-linuxbios -> grub-coreboot rename again.
+
+ -- Robert Millan <rmh@aybabtu.com> Wed, 30 Jul 2008 22:12:07 +0200
+
+grub2 (1.96+20080724-4) unstable; urgency=high
+
+ * patches/00_fix_overflow.diff: fix overflow with a big grub.cfg.
+ (Closes: #473543)
+
+ -- Felix Zielcke <fzielcke@z-51.de> Tue, 29 Jul 2008 17:10:59 +0200
+
+grub2 (1.96+20080724-3) unstable; urgency=low
+
+ [ Felix Zielcke ]
+ * changed dependency for debconf to also support debconf-2.0. (Closes: #492543)
+ * patches/00_xfs.diff: Fix "out of partition" error with XFS.
+ (Closes: #436943)
+
+ [ Robert Millan ]
+ * patches/00_raid_duped_disks.diff: Do not abort when two RAID disks with
+ the same number are found. (Closes: #492656)
+ * patches/00_strengthen_apple_partmap_check.diff: Be more strict when probing
+ for Apple partition maps (this prevents false positives on i386-pc
+ installs). (Closes: #475718)
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 29 Jul 2008 00:48:01 +0200
+
+grub2 (1.96+20080724-2) unstable; urgency=high
+
+ [ Felix Zielcke ]
+ * fixed lintian override for kernel.elf
+ * debian/rules: changed cvs targets to use svn
+
+ [ Robert Millan ]
+ * patches/00_skip_dev_dm.diff: Skip /dev/dm-[0-9] devices also (implicitly)
+ for RAID. (Closes: #491977)
+ * patches/00_uuid_boot.diff: Fix cross-disk installs by using UUIDs.
+ (Closes: #492204)
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 26 Jul 2008 01:06:07 +0200
+
+grub2 (1.96+20080724-1) unstable; urgency=high
+
+ * New SVN snapshot.
+ - Support for ext4dev extents.
+ - patches/00_speed_up_font_load.diff: Remove (merged).
+
+ [ Felix Zielcke ]
+ * upgrade-from-grub-legacy now calls update-grub if grub.cfg doestn't exist
+ and prints a big warning if it failed.
+ * Update Standards version to 3.8.0. No changes need.
+ * Added Build-Dep for po-debconf and a lintian override, to make it happy.
+
+ [ Updated translations ]
+ * Swedish (sv.po) by Martin Ã…gren (Closes: #492056)
+
+ [ Robert Millan ]
+ * Revert r844. grub-coreboot is stuck on NEW, and it was too early
+ for branching.
+
+ -- Robert Millan <rmh@aybabtu.com> Thu, 24 Jul 2008 13:27:53 +0200
+
+grub2 (1.96+20080717-1) experimental; urgency=low
+
+ * New SVN snapshot.
+ - Provides LZMA support (not yet used in the package).
+ - Fix grub-mkrescue manpage generation. (Closes: #489440)
+
+ * Rename grub-linuxbios to grub-coreboot (and leave a dummy grub-linuxbios
+ package to handle upgrades).
+
+ [ Updated translations ]
+ * Spanish (es.po) by Maria Germana Oliveira Blazetic (Closes: #489877)
+ * Portuguese (pt.po) by Ricardo Silva (Closes: #489807)
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 12 Jul 2008 17:47:09 +0200
+
+grub2 (1.96+20080704-2) unstable; urgency=high
+
+ * patches/02_old_linux_version_comparison.diff: Set interpreter to /bin/bash.
+ (Closes: #489426, #489446)
+
+ -- Robert Millan <rmh@aybabtu.com> Mon, 7 Jul 2008 15:17:58 +0200
+
+grub2 (1.96+20080704-1) unstable; urgency=high
+
+ * New SVN snapshot.
+ * default/grub: Add commented example to disable graphical terminal.
+ * Use substvars to support linking with liblzo1.
+ * Bring 03_disable_floppies.diff to pre-r805 state. (Closes: #488375)
+ * patches/02_old_linux_version_comparison.diff: New patch. Steal version
+ comparison code from GRUB Legacy's update-grub. (Closes: #464086, #489133)
+ * patches/00_speed_up_font_load.diff: New patch. Generate font files with
+ only the needed characters. (Closes: #476479, #477083)
+
+ -- Robert Millan <rmh@aybabtu.com> Fri, 4 Jul 2008 21:39:07 +0200
+
+grub2 (1.96+20080626-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Avoids passing UUID to Linux when not using initrd. (Closes: #484228)
+ - patches/04_uuids_and_abstraction_dont_play_along_nicely.diff: Resync.
+
+ -- Robert Millan <rmh@aybabtu.com> Thu, 26 Jun 2008 16:43:48 +0200
+
+grub2 (1.96+20080621-1) unstable; urgency=high
+
+ * Urgency set to "high" because of #482688.
+ * New CVS snapshot.
+ - Fix module load hook in prepare_grub_to_access_device().
+ (Closes: #486804)
+ - Call prepare_grub_to_access_device() before accessing devices, never
+ afterwards. (Closes: #487198)
+ * grub.d/05_debian_theme: Prefer /boot/grub over /usr for image
+ loading, since chances are it's less LVMed.
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 21 Jun 2008 15:52:48 +0200
+
+grub2 (1.96+20080617-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Supports IDA block devices. (Closes: #483858)
+ - Fixes some problems in ext2/ext3. (Closes: #485068, #485065)
+ - Uses EUID instead of UID in update-grub. (Closes: #486043, #486039,
+ #486040, #486041).
+ - Fixes incomplete I2O device support. Thanks Sven Mueller.
+ (Closes: #486505)
+ - Fixes recent regressions in fs/ext2.c. (Closes: #485279)
+ - Only use UUIDs when requested device is not the same as the one
+ providing /boot. (Closes: #486119)
+ - patches/02_libgcc_powerpc_hack.diff: Remove. Probably not needed
+ anymore.
+ - patches/04_uuids_and_abstraction_dont_play_along_nicely.diff: Update.
+ * patches/06_olpc_prefix_hack.diff: Hardcode prefix to (sd,1) on OLPC.
+ * Refurbish 03_disable_floppy_support_in_util_biosdisk.diff into
+ 03_disable_floppies.diff.
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 17 Jun 2008 01:07:52 +0200
+
+grub2 (1.96+20080601-2) unstable; urgency=low
+
+ * 04_run_grub_mkdevicemap_when_grub_probe_fails.diff: Remove. Argueably
+ makes grub-probe unreliable and is quite annoying.
+ * 04_uuids_and_abstraction_dont_play_along_nicely.diff: New patch. Disable
+ UUID parameter to Linux when LVM or dmRAID is in use. (Closes: #484228)
+ This is a workaround for bug #484297 in udev.
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 3 Jun 2008 16:29:53 +0200
+
+grub2 (1.96+20080601-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - patches/06_backward_compat_in_uuid_support.diff: Merged.
+ - Fixes NULL pointer dereference in biosdisk.c. (Closes: #483895, #483900)
+ - Extends UUID support for XFS and ReiserFS.
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 1 Jun 2008 15:44:08 +0200
+
+grub2 (1.96+20080531-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Work around BIOS bug affecting keyboard on macbooks. (Closes: #482860)
+ - Adjust grub.d/05_debian_theme to use the new UUID-compatible API.
+ - default/grub: Add commented GRUB_DISABLE_LINUX_UUID variable.
+ - patches/06_backward_compat_in_uuid_support.diff: New. Make update-grub
+ generate code that is compatible with older GRUB installs.
+ - util/biosdisk.c no longer complains about duplicated device.map entries.
+ (Closes: #481236)
+
+ [ Updated translations ]
+ * Galician (gl.po) by Jacobo Tarrio (Closes: #480977)
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 31 May 2008 00:02:54 +0200
+
+grub2 (1.96+20080512-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Adds support for default-only Linux cmdline options. (Closes: #460843)
+ - Supports Xen virtual block devices. (Closes: #456777)
+ - Supports Virtio block devices. (Closes: #479056)
+ - Supports CCISS block devices. (Closes: #479735)
+ - Fixes handling of more LVM abnormal conditions. (Closes: #474343,
+ #474931, #477175)
+
+ * Switch to liblzo2 now that it's GPLv3-compatible. (Closes: #466375)
+ * grub-pc.postinst: Escape \ and / in cmdline sed invokation.
+ (Closes: #479279)
+
+ [ Updated translations ]
+ * Italian (it.po) by Luca Monducci (Closes: #480740)
+
+ -- Robert Millan <rmh@aybabtu.com> Mon, 12 May 2008 17:46:38 +0200
+
+grub2 (1.96+20080429-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Includes sample grub.cfg file; we use it for grub-rescue-pc.
+ (Closes: #478324)
+ * grub-common: Upgrade Replaces to << 1.96+20080426-3. (Closes: #478224,
+ #478353, #478144)
+
+ [ Updated translations ]
+ * French (fr.po) by Christian Perrier (Closes: #471291)
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 29 Apr 2008 13:27:52 +0200
+
+grub2 (1.96+20080426-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Fixes syntax error when setting GRUB_PRELOAD_MODULES. (Closes: #476517)
+ * Move os-prober to Suggests, to avoid trouble with #476184.
+ (Closes: #476684)
+ * patches/04_run_grub_mkdevicemap_when_grub_probe_fails.diff: New patch,
+ does what its name says. (Closes: #467127)
+ - Also move grub-mkdevicemap from grub-pc to grub-common, so that GRUB
+ Legacy can use it.
+
+ [ Updated translations ]
+ * Basque (eu.po) by Piarres Beobide (Closes: #476708)
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 26 Apr 2008 20:06:55 +0200
+
+grub2 (1.96+20080413-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Provides 30_os-prober update-grub add-on. Thanks Fabian Greffrath.
+ (Closes: #461442)
+ - Improves robustness when handling LVM.
+ (Closes: #474931, #474343)
+ * patches/03_disable_floppy_support_in_util_biosdisk.diff: New. Does
+ what its name says. (Closes: #475177)
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 13 Apr 2008 13:53:28 +0200
+
+grub2 (1.96+20080408-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - grub-probe skips non-existant devices when processing device.map.
+ (Closes: #473209)
+ * control: Fix syntax error.
+
+ [ Updated translations ]
+ * Finnish (fi.po) by Esko Arajärvi (Closes: #468641)
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 8 Apr 2008 15:45:25 +0200
+
+grub2 (1.96+20080228-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ * Split grub-probe into grub-common package. Make all flavours depend on it.
+ (Closes: #241972)
+ * Suggest multiboot-doc.
+ * patches/01_grub_legacy_0_based_partitions.diff: New patch. Add a hack that
+ tells grub-probe you want 0-based partition count
+ (GRUB_LEGACY_0_BASED_PARTITIONS variable)
+ * Stop depending on lsb-release (too heavy! we don't need python in base).
+ Instead of assuming it's there, try calling it and otherwise just echo
+ Debian.
+
+ -- Robert Millan <rmh@aybabtu.com> Thu, 28 Feb 2008 16:43:40 +0100
+
+grub2 (1.96+20080219-3) unstable; urgency=low
+
+ * default/grub: Use lsb_release to support Debian derivatives.
+ (Closes: #466561)
+ * grub.d/05_debian_theme: Only setup background image when a reader for it
+ is present in /boot/grub. (Closes: #467111)
+
+ [ Updated translations ]
+ * Russian (ru.po) by Yuri Kozlov (Closes: #467181)
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 24 Feb 2008 15:39:50 +0100
+
+grub2 (1.96+20080219-2) unstable; urgency=high
+
+ * grub-pc.postinst: Create /boot/grub if it doesn't exist.
+
+ -- Robert Millan <rmh@aybabtu.com> Wed, 20 Feb 2008 07:15:14 +0100
+
+grub2 (1.96+20080219-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Improves GPT support, allowing it to work without blocklists.
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 19 Feb 2008 15:05:10 +0100
+
+grub2 (1.96+20080216-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Fixes offset calculation issue when installing on GPT (urgency set
+ to high because of this).
+ * Fix Vcs-Browser tag. Thanks James. (Closes: #465697)
+ * Only process grub-pc/linux_cmdline if /boot/grub/menu.lst exists.
+ (Closes: #465708)
+
+ [ Updated translations ]
+ * French (fr.po) by Christian Perrier (Closes: #465706)
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 16 Feb 2008 23:30:55 +0100
+
+grub2 (1.96+20080213-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Failure to read one device in a RAID-1 array no longer causes boot
+ to fail (so long as there's a member that works). (Closes: #426341)
+ * script: For /proc/mounts, only report lines that start with /dev/.
+ * Add new upgrade-from-grub-legacy script for the user to complete the upgrade
+ process from GRUB Legacy, and advertise it prominently in menu.lst.
+ (Closes: #464912)
+ * Add a hack to support gfxterm / background_image on systems where /usr
+ isn't accessible. (Closes: #464911, #463144)
+ - grub-pc.postinst
+ - grub.d/05_debian_theme
+ * Fix a pair of spelling mistakes in debconf. (Closes: #465296)
+ * Migrate kopt from menu.lst. (Closes: #461164, #464918)
+
+ [ Updated translations ]
+ * Portuguese (pt.po) by Ricardo Silva (Closes: #465137)
+ * German (de.po) by Helge Kreutzmann (Closes: #465295)
+
+ -- Robert Millan <rmh@aybabtu.com> Wed, 13 Feb 2008 16:37:13 +0100
+
+grub2 (1.96+20080210-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Errors that cause GRUB to enter rescue mode are displayed now.
+ (Closes: #425149)
+ - Build LVM/RAID modules into a few commands that were missing them
+ (notably, grub-setup). (Closes: #465033)
+ * Fix license violation (incompatibility between GRUB and LZO2).
+ (Closes: #465056)
+ - Urgency set to high.
+ - control: Move liblzo2-dev from Build-Depends to Build-Conflicts
+ (leaving liblzo-dev as the only option).
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 10 Feb 2008 17:09:15 +0100
+
+grub2 (1.96+20080209-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Fix a root device setting issue in grub-setup. (Closes: #463391)
+ - Fix partmap detection under LVM/RAID.
+ - Add scripting commands that would allow user to implement hiddenmenu-like
+ functionality (http://grub.enbug.org/Hiddenmenu).
+ - Provide manpages for grub-setup, grub-emu, grub-mkimage and others.
+ (Closes: #333516, #372890)
+ * Fix a pair of spelling errors in debconf templates. Thanks Christian
+ Perrier. (Closes: #464133)
+ * Run debconf-updatepo. (Closes: #463918)
+ * Lower base-files versioned dependency to >= 4.0.1~bpo40+1.
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 9 Feb 2008 13:43:49 +0100
+
+grub2 (1.96+20080203-1) unstable; urgency=low
+
+ * New CVS snapshot (and release, but we skipped that ;-))
+ - patches/01_regparm.diff: Delete.
+ - Improved XFS support.
+ - util/grub.d/00_header.in: Add runtime error detection (for gfxterm).
+ - Fixes problem when chainloading to Vista.
+ * Fix po-debconf errors. Thanks Thomas Huriaux. (Closes: #402972)
+ * grub.d/05_debian_theme:
+ - Add runtime error detection.
+ - Detect/Enable PNG background when it is present.
+ * control (grub-ieee1275): Remove versioned dependency on powerpc-ibm-utils.
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 3 Feb 2008 19:31:23 +0100
+
+grub2 (1.95+20080201-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ * presubj: Improve notice.
+ * patches/01_regparm.diff: Fix CPU context corruption affecting fs/xfs.c.
+ (Closes: #463081, #419766, #462159)
+ * patches/02_libgcc_powerpc_hack.diff: Fix FTBFS on powerpc. (Closes: #457491)
+ * patches/disable_xfs.diff: Actually remove this time...
+
+ -- Robert Millan <rmh@aybabtu.com> Fri, 1 Feb 2008 17:06:00 +0100
+
+grub2 (1.95+20080128-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Fixes bogus CLAIM problems on Apple firmware. (Closes: #449135, #422729)
+ - grub-probe performs sanity checks to make sure our filesystem drivers
+ are usable. (Closes: #462449)
+ - patches/disable_ata.diff: Remove. ATA module isn't auto-loaded in
+ rescue floppies now.
+ - patches/disable_xfs.diff: Remove. See above (about grub-probe).
+ * Bring back grub-emu; it can help a lot with debugging feedback.
+ - control
+ - rules
+
+ -- Robert Millan <rmh@aybabtu.com> Mon, 28 Jan 2008 00:01:11 +0100
+
+grub2 (1.95+20080116-2) unstable; urgency=low
+
+ * grub.d/05_debian_theme: Enable swirlish beauty.
+ * rules: Obtain debian/legacy/update-grub dynamicaly from GRUB Legacy svn.
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 19 Jan 2008 13:16:18 +0100
+
+grub2 (1.95+20080116-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - update-grub ignores stale *.dpkg-* files. (Closes: #422708, #424223)
+ - LVM/RAID now working properly (except when it affects /boot).
+ (Closes: #425666)
+ - Fixes flickery in timeout message. (Closes: #437275)
+ * grub-pc.postinst: Use `--no-floppy' whenever possible. Die, floppies,
+ die!
+ * Resync with latest version of GRUB Legacy's update-grub. This time,
+ using the $LET_US_TRY_GRUB_2 hack to reuse the same script both for
+ addition of core.img and its removal.
+ * grub-*.install: Add update-grub2 stub. Packages providing /etc/grub.d/
+ scripts should invoke update-grub2 in both postinst and postrm (whenever
+ it is found, of course).
+ * control: Reorganize a bit, including a complete rewrite of the
+ package descriptions.
+ * control (grub-ieee1275): Enable for i386/amd64.
+
+ -- Robert Millan <rmh@aybabtu.com> Wed, 16 Jan 2008 15:00:54 +0100
+
+grub2 (1.95+20080107-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Supports ReiserFS. (Closes: #430742)
+ - patches/disable_ata.diff: Resync.
+
+ -- Robert Millan <rmh@aybabtu.com> Mon, 7 Jan 2008 12:46:39 +0100
+
+grub2 (1.95+20080105-2) unstable; urgency=low
+
+ * grub-pc.postinst: Fix covered assumption that menu.lst exists.
+ (Closes: #459247)
+ * copyright: Fix copyright/license reference.
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 6 Jan 2008 18:02:28 +0100
+
+grub2 (1.95+20080105-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Fixes install on non-devfs systems with devfs-style paths (ouch).
+ (Closes: #450709).
+ - Fixes boot of "Linux" zImages (including memtest86+). (Closes: #436113).
+ - Corrects usage message in grub-setup. (Closes: #458600).
+ - patches/menu_color.diff: Remove. Made obsolete by `menu_color_normal'
+ and `menu_color_highlight' variables. Add/install grub.d/05_debian_theme
+ to make use of them.
+ * Reestructure grub-pc.postinst. Notably:
+ - Do not touch menu.lst unless user has confirmed it (via debconf).
+ (Closes: #459247)
+ - When we do, keep a backup in /boot/grub/menu.lst_backup_by_grub2_postinst.
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 5 Jan 2008 17:55:37 +0100
+
+grub2 (1.95+20080101-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - patches/disable_xfs.diff: Rewrite in a way that won't collide with
+ upstream changes so often.
+ - unifont.hex now processed by upstream.
+ - rules: Disable build of unifont.pff.
+ - *.install: Remove build/unifont.pff line.
+ - patches/menu_color.diff: Change menu color to our traditional blue theme.
+ * Support new dpkg fields (Homepage, Vcs-Svn, Vcs-Browser).
+ * patches/disable_ata.diff: Prevent ATA module from being built on i386-pc.
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 1 Jan 2008 19:45:30 +0100
+
+grub2 (1.95+20071101-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - patches/linuxbios.diff: Remove (supported in upstream now).
+
+ -- Robert Millan <rmh@aybabtu.com> Thu, 1 Nov 2007 13:18:51 +0100
+
+grub2 (1.95+20071004-2) unstable; urgency=low
+
+ * Rename debian/grub-of.* to debian/grub-ieee1275.*.
+ * Add debian/grub-linuxbios.{postinst,dirs,install}.
+ * rules: Fix/Overrride lintian warnings (unstripped-binary-or-object).
+ * Remove grub-linuxbios.postinst.
+
+ -- Robert Millan <rmh@aybabtu.com> Wed, 10 Oct 2007 23:56:35 +0200
+
+grub2 (1.95+20071004-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ * Add grub-linuxbios package.
+ - patches/linuxbios.diff
+ - control
+ - rules
+ * Rename grub-of to grub-ieee1275 to match with upstream conventions.
+ - control
+ - rules
+
+ -- Robert Millan <rmh@aybabtu.com> Thu, 4 Oct 2007 14:42:30 +0200
+
+grub2 (1.95+20070829-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Includes fix for parallel builds.
+ * rules: Append -j flag to $(MAKE) to take advantage of >1 processors.
+ * Add reference to /usr/share/common-licenses.
+ - debian/copyright
+ - debian/control (all packages): Add base-files (>= 4.0.1) dependency.
+
+ -- Robert Millan <rmh@debian.org> Sat, 1 Sep 2007 19:00:22 +0200
+
+grub2 (1.95+20070828-2) unstable; urgency=low
+
+ * control (grub-of): Make depends on powerpc-ibm-utils versioned as
+ >= 1.0.6 (older versions don't have -a flag).
+
+ -- Robert Millan <rmh@debian.org> Tue, 28 Aug 2007 23:32:32 +0200
+
+grub2 (1.95+20070828-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Adds ntfs support.
+ - Fixes a pair of issues indirectly breaking grub-probe on powerpc.
+ (Closes: #431488)
+ - patches/disable_xfs.diff: Resync.
+ - copyright: License upgraded to GPLv3.
+ * control (grub-of Depends): Add powerpc-utils (for nvsetenv) and bc.
+
+ -- Robert Millan <rmh@debian.org> Tue, 28 Aug 2007 21:24:14 +0200
+
+grub2 (1.95+20070626-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - More fixes to cope with unreadable /. (Closes: #427289)
+ - update-grub supports multiple terminals.
+ * control (Build-Depends): Add genisoimage.
+ * patches/partmap_fallback.diff: Remove. It didn't archieve anything as
+ it also needs support for proper identification of raid / lvm (this is
+ being worked on).
+ * patches/disable_xfs.diff: Disable xfs in grub-probe.
+ * grub-rescue-pc.README.Debian: New. Explain how to use the rescue
+ images.
+
+ -- Robert Millan <rmh@debian.org> Tue, 26 Jun 2007 08:39:14 +0200
+
+grub2 (1.95+20070614-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - update-grub is tollerant to unreadable / (as long as /boot is
+ accessible). (Closes: #427289)
+ * grub-pc.postinst: Generate new grub.cfg when menu.lst exists.
+ * New package grub-rescue-pc.
+ - control: Add it.
+ - README.Debian.in: Remove obsolete documentation.
+ - rules: Build rescue images using grub-mkrescue.
+ - grub-rescue-pc.dirs: Prepare their directory.
+ - grub-rescue-pc.install: Install them.
+ * legacy/update-grub: Fix core.img detection on separate /boot.
+
+ -- Robert Millan <rmh@debian.org> Thu, 14 Jun 2007 08:17:21 +0200
+
+grub2 (1.95+20070604-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - patches/grub_probe_for_everyone.diff: Remove (merged).
+ - update-grub exports user-defined GRUB_CMDLINE_LINUX. (Closes: #425453)
+ - Fix those nasty powerpc bugs. (Closes: #422729)
+
+ -- Robert Millan <rmh@aybabtu.com> Mon, 4 Jun 2007 21:30:55 +0200
+
+grub2 (1.95+20070520-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - LVM / RAID fixes. (Closes: #423648, #381150)
+ - Fix memory management bug. (Closes: #423409)
+ - patches/efi.diff: Remove (merged).
+ - patches/grub_probe_for_everyone.diff: Use the new paths for
+ util/grub-probe.c, util/biosdisk.c, util/getroot.c. Enable
+ grub-mkdevicemap. (Closes: #424985)
+ * legacy/update-grub: Get rid of all grub-set-default calls. (Closes: #425054)
+ * grub-{pc,efi,of}.postinst: Only run update-grub if grub.cfg already exists.
+ * grub-pc.postinst: Only run GRUB Legacy compat stuff if menu.lst is found.
+ * patches/partmap_fallback.diff: New. Implement fallback "pc gpt" for partmap
+ detection failures. (Closes: #423022)
+ * control: Update XS-Vcs-* fields. Thanks Sam Morris <sam@robots.org.uk>.
+ (Closes: #425146)
+ * grub-{pc,efi,of}.{dirs,postinst}: Move unifont.pff to /usr/share/grub.
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 20 May 2007 11:13:03 +0200
+
+grub2 (1.95+20070515-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Fix assumptions about /, /boot and /boot/grub being the same device.
+ (Closes: #423268, #422459)
+ - Proper sorting of Linux images. (Closes: #422580)
+ - update-grub lets /etc/default/grub override its variables now.
+ (Closes: #423649)
+ - update-grub mentions /etc/default/grub in the grub.cfg header.
+ (Closes: #423651)
+ - update-grub sets 800x600x16 as the default gfxmode. (Closes: #422794)
+ - update-grub runs grub-mkdevicemap before attempting to use grub-probe
+ (part of #423217)
+
+ [ Otavio Salvador ]
+ * Add support to DEB_BUILD_OPTIONS=noopt. Thanks to Sam Morris
+ <sam@robots.org.uk> for the patch. (Closes: #423005)
+ * Add Robert Millan as uploader.
+ * Change build-dependency from liblzo-dev to liblzo2-dev. (Closes: #423358)
+
+ [ Robert Millan ]
+ * grub-pc.postinst:
+ - Remove /boot/grub/device.map before running grub-install.
+ (Closes: #422851)
+ - Always run update-grub after grub-install. (part of #423217)
+ - Use grub-mkdevicemap instead of removing device.map, since update-grub
+ needs it but grub-install is not run unconditionaly.
+ - Redirect grub-install invocation to /dev/null, since it can mislead
+ users into thinking that MBR was overwritten. (part of #423217)
+ * default/grub: Stop exporting the variables (update-grub does that now).
+ * Misc EFI fixes, including new grub-install.
+ - patches/efi.diff: New.
+ - patches/grub_probe_for_everyone.diff: Move some bits to efi.diff.
+ - grub-efi.install: Stop installing dummy grub-install.
+ - grub-install: Remove.
+ * grub-pc.postinst: Avoid generating core.img when menu.lst is not present,
+ to avoid duplicated work (this is specialy important for d-i). (part of
+ #423217).
+ * See multiple references above. (Closes: #423217)
+ * grub-{pc,efi,of}.{dirs,install}: Install presubj in the right directory
+ to make it work again (oops).
+ * Add reportbug script to gather debugging information. (Closes: #423218)
+ - script: New.
+ - grub-{pc,efi,of}.install: Install it.
+ * Install the reportbug scripts for grub2 too, since users might still use
+ it for bugfiling.
+ - grub2.dirs
+ - grub2.install
+ * Fix some lintian warnings.
+ - control (grub2): Depend on debconf.
+ - README.Debian.in: Fix mispell.
+ - grub2.templates: Remove extra dot.
+
+ -- Robert Millan <rmh@aybabtu.com> Tue, 15 May 2007 22:08:53 +0200
+
+grub2 (1.95+20070507-1) unstable; urgency=low
+
+ [ Robert Millan ]
+ * New CVS snapshot.
+ - patches/build_neq_src.diff: Remove (merged).
+ * Fix debhelper files to ensure each package gets the right thing.
+ * Enable gfxterm/unifont support.
+ * On grub-pc, if there's no core.img setup, create one (but do not
+ risk writing to MBR).
+ * On grub-pc, if menu.lst is found, regenerate it to include our
+ core.img.
+
+ [ Otavio Salvador ]
+ * Move debian/update-grub to debian/legacy/update-grub otherwise the
+ source gets messy.
+
+ -- Otavio Salvador <otavio@ossystems.com.br> Mon, 07 May 2007 18:48:14 -0300
+
+grub2 (1.95+20070505.1-3) unstable; urgency=low
+
+ * Split postinst into grub2.postinst (with the transition warning) and
+ postinst.in, with update-grub invocation for grub-{pc,efi,of}.
+ - postinst.in
+ - grub2.postinst
+ - rules
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 6 May 2007 01:20:04 +0200
+
+grub2 (1.95+20070505.1-2) unstable; urgency=low
+
+ * Add EFI build of GRUB.
+ - control: Restructure to provide 3 packages: grub-pc (x86),
+ grub-efi (x86) and grub-of (powerpc).
+ - rules: Handle a separate build for each package.
+ - patches/build_neq_src.diff: Fix builddir == srcdir assumptions.
+ - patches/grub_probe_for_everyone.diff: New (superceds
+ powerpc_probe.diff). Enable grub-probe on powerpc and i386-efi.
+ - grub-install: Dummy informational grub-install for EFI.
+ - grub-efi.install: Installs it.
+
+ -- Robert Millan <rmh@aybabtu.com> Sun, 6 May 2007 00:23:56 +0200
+
+grub2 (1.95+20070505.1-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ * patches/powerpc_probe.diff: Add partmap/gpt.c to grub-probe.
+ * control (Architecture): Temporarily disable powerpc. Sorry, but runtime
+ is currently broken and we don't have the hardware to debug it. Will be
+ re-enabled in next upload.
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 5 May 2007 21:52:49 +0200
+
+grub2 (1.95+20070505-1) unstable; urgency=low
+
+ * New CVS snapshot.
+ - Improved grub.cfg parser. (Closes: #381215)
+ - patches/fix-grub-install.diff: Remove (merged).
+ - control (Build-Depends): Remove libncurses5-dev (no longer needed).
+ - provides update-grub2. (Closes: #419151)
+ - Supports GPT in PC/BIOS systems. (Closes: #409073)
+ * control (Build-Depends): Add gcc-multilib to fix FTBFS.
+ * control (Description): Make it less scary, and more informative.
+ * postinst: Run update-grub to ensure the latest improvements always are
+ applied.
+ * patches/powerpc_probe.diff: Attempt at making grub-probe build/install
+ on powerpc (and hopefuly update-grub).
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 5 May 2007 01:49:07 +0200
+
+grub2 (1.95-5) unstable; urgency=low
+
+ * Fix FTBFS on kFreeBSD. Thanks to Aurelien Jarno <aurel32@debian.org>
+ by providing the patch. Closes: #416408
+
+ -- Otavio Salvador <otavio@ossystems.com.br> Fri, 30 Mar 2007 19:20:48 -0300
+
+grub2 (1.95-4) unstable; urgency=low
+
+ * Fix powerpc grub-install binary path. Closes: #402838
+
+ -- Otavio Salvador <otavio@ossystems.com.br> Thu, 22 Mar 2007 23:45:56 -0300
+
+grub2 (1.95-3) unstable; urgency=low
+
+ [ Christian Perrier ]
+ * Switch to po-debconf for debconf templates. Closes: #402972
+ * Depend on ${misc:Depends} and not "debconf" to allow cdebconf to be used
+ * Debconf translations:
+ - French
+ - Czech. Closes: #413327
+ - Galician. Closes: #413323
+ - Swedish. Closes: #413325
+ - Portuguese. Closes: #413332
+ - German. Closes: #413365
+ - Tamil. Closes: #413478
+ - Russian. Closes: #413542
+ - Italian. Closes: #413904
+ - Romanian. Closes: #414443
+
+ -- Otavio Salvador <otavio@ossystems.com.br> Tue, 20 Mar 2007 23:46:38 -0300
+
+grub2 (1.95-2) unstable; urgency=low
+
+ [ Robert Millan ]
+ * update-grub: Fix for Xen hypervisor entries, thanks Aaron Schrab.
+ (Closes: #394706)
+ * Transition to new numbering scheme for partitions. (Closes: #395019)
+ - update-grub: Don't substract 1 when converting partition device names to
+ grub drives.
+ - Add debconf warning explaining the situation.
+ * Rewrite Architecture line back to hardcoded list :(. (Closes: #398060)
+
+ -- Otavio Salvador <otavio@debian.org> Mon, 11 Dec 2006 05:08:41 -0200
+
+grub2 (1.95-1) unstable; urgency=low
+
+ * New upstream release.
+ - patches/03_revert_partition_numbering.diff: Delete (obsoleted).
+
+ -- Robert Millan <rmh@aybabtu.com> Sat, 14 Oct 2006 21:19:21 +0200
+
+grub2 (1.94+20061003-1) unstable; urgency=high
+
+ * New CVS snapshot.
+
+ [ Otavio Salvador ]
+ * Change debhelper compatibility mode to 5:
+ - debian/compat: setted to 5;
+ * control (Build-Depends): Add lib32ncurses5-dev for ppc64.
+ Closes: #389873
+ * Set urgency=high since it's experimental stuff and tagged likewise. It
+ also solved a serious bug on PowerPC that leave users with a black
+ screen.
+
+ [ Robert Millan ]
+ * control (Depends): Add powerpc-ibm-utils for powerpc/ppc64.
+ (Closes: #372186)
+
+ -- Otavio Salvador <otavio@debian.org> Tue, 3 Oct 2006 16:49:32 -0300
+
+grub2 (1.94+20060926-1) unstable; urgency=high
+
+ * New CVS snapshot.
+ - Command-line editting fix (Closes: #381214).
+ - Fixes runtime breakage on amd64 (not in BTS).
+ - Delete a few patches (merged).
+
+ [ Robert Millan ]
+ * Set urgency=high. Might seem like a rush, but it can't possibly be worse than
+ 1.94-5 (broken on systems that use udev, broken on amd64...).
+ * Pure ppc64 support.
+ - control (Architecture): Add any-ppc64.
+ - control (Build-Depends): Add libc6-dev-powerpc [ppc64].
+ * rules: Remove moddep.lst install command (no longer needed).
+ * patches/03_revert_partition_numbering.diff: New. Revert a commit that
+ broke grub-probefs.
+ * Add bug template to encourage sending upstream stuff directly to
+ upstream.
+ - presubj: New.
+
+ [ Otavio Salvador ]
+ * Add XS-X-Vcs-Svn on control file and point it to our current svn
+ repository.
+ * Add cvs-snapshot to rules.
+
+ -- Otavio Salvador <otavio@debian.org> Tue, 26 Sep 2006 16:14:36 -0300
+
+grub2 (1.94-6) unstable; urgency=low
+
+ [ Robert Millan ]
+ * update-grub: Set interpreter to /bin/bash to cope with non-POSIX
+ extensions. (mentioned in #361929)
+ * patches/03_avoid_recursing_into_dot_static.diff: New. Avoid recursing into
+ dotdirs (e.g. ".static").
+ * patches/04_mkdevicemap_dont_assume_floppies.diff: New. Don't assume
+ /dev/fd0 exists when generating device.map.
+
+ -- Otavio Salvador <otavio@debian.org> Thu, 14 Sep 2006 16:07:30 -0300
+
+grub2 (1.94-5) unstable; urgency=low
+
+ [ Robert Millan ]
+ * control (Build-Depends): s/any-amd64/amd64 kfreebsd-amd64/g (this seems to
+ confuse buildds).
+ * 02_not_remove_menu_lst.patch: New patch. Skip menu.lst removal in
+ grub-install. (Closes: #372934)
+
+ -- Otavio Salvador <otavio@debian.org> Sun, 20 Aug 2006 12:02:13 -0300
+
+grub2 (1.94-4) unstable; urgency=low
+
+ [ Otavio Salvador ]
+ * 01_fix_amd64_building.patch: dropped since it now supports amd64
+ native building.
+ * Remove convert_kernel26 usage since it's not necessary anymore and due
+ initramfs-tools changes it's bug too.
+
+ [ Robert Millan ]
+ * Fork update-grub from grub legacy, and tweak a few commands in output to
+ make it work for grub2.
+ * Update README.Debian.in with more recent (and easier) install instructions.
+ * Add grub to Conflicts/Replaces. Too many commands with the same name,
+ even if they don't use the same path yet (but will likely do in the
+ future, see #361929).
+ * Get rid of control.in, which I introduced in 0.6+20040805-1 and turned out
+ to be an endless source of problems (and forbidden by policy as well).
+ * Fix FTBFS on amd64. Really closes: #372548.
+
+ -- Otavio Salvador <otavio@debian.org> Fri, 18 Aug 2006 15:38:25 -0300
+
+grub2 (1.94-3) unstable; urgency=low
+
+ * Fix FTBFS in amd64. Closes: 372548
+
+ -- Otavio Salvador <otavio@debian.org> Sat, 10 Jun 2006 19:57:01 -0300
+
+grub2 (1.94-2) unstable; urgency=low
+
+ * Update grub images paths in README.Debian
+ * 01_fix_grub-install.patch: add to fix a problem with PowerPC
+ installation. Refs: #371069
+ * Fix FTBFS in amd64. Closes: #370803
+
+ -- Otavio Salvador <otavio@debian.org> Fri, 9 Jun 2006 09:29:40 -0300
+
+grub2 (1.94-1) unstable; urgency=low
+
+ * New upstream release.
+ - Fix powerpc building. Closes: #370259
+ - 01_fix_grub-install.patch: merged upstream.
+ - Moved modules to /usr/lib/grub since they are architecture
+ dependent.
+ * Leave CDBS set debhelper compatibility level.
+ * Allow amd64 build to happen. Closes: #364956
+ * Enforce building in 32bits while running in x86_64 machines.
+ * Update Standards version to 3.7.2. No changes need.
+
+ -- Otavio Salvador <otavio@debian.org> Mon, 5 Jun 2006 12:49:09 -0300
+
+grub2 (1.93-1) unstable; urgency=low
+
+ * New upstream release.
+ - Added support to PowerPC. Closes: #357853
+ - 01_fix_grub-install.patch: rediff.
+ * Update Standards version to 3.6.2. No changes need.
+ * Start to use new dpkg architecture definition. Closes: #360134
+
+ -- Otavio Salvador <otavio@debian.org> Sat, 1 Apr 2006 10:07:17 -0300
+
+grub2 (1.92-2) unstable; urgency=low
+
+ * Add bison on build-depends field. Closes: #346178
+ * Add more fixes in 01_fix_grub-install.patch. Closes: #346177
+
+ -- Otavio Salvador <otavio@debian.org> Fri, 6 Jan 2006 09:48:08 -0200
+
+grub2 (1.92-1) unstable; urgency=low
+
+ * New upstream release.
+ - Add support for GPT partition table format.
+ - Add a new command "play" to play an audio file on PC.
+ - Add support for Linux/ADFS partition table format.
+ - Add support for BASH-like scripting.
+ - Add support for Apple HFS+ filesystems.
+ * 01_fix_grub-install.patch: Added. Fix grub-install to use
+ /bin/grub-mkimage instead of /sbin/grub-mkimage. Closes: #338824
+ * Do not use CDBS tarball mode anymore. Closes: #344272
+
+ -- Otavio Salvador <otavio@debian.org> Thu, 5 Jan 2006 15:20:40 -0200
+
+grub2 (1.91-0) unstable; urgency=low
+
+ * New upstream release. Closes: #331211
+ * debian/watch: added.
+ * debian/control.in, debian/control: Add libncurses5-dev in
+ Build-Depends. Closes: #304638
+ * Remove Robert Millan as uploader;
+ * Add myself as uploader;
+
+ -- Otavio Salvador <otavio@debian.org> Sat, 12 Nov 2005 16:35:18 -0200
+
+grub2 (0.6+20050203-2) unstable; urgency=low
+
+ * Disable for powerpc. Reportedly it fails to boot.
+
+ -- Robert Millan <rmh@debian.org> Fri, 4 Feb 2005 01:52:09 +0100
+
+grub2 (0.6+20050203-1) unstable; urgency=low
+
+ * New upstream snapshot.
+ * Install moddep.lst properly in a cpu-independant way. (Closes: #264115)
+ * Use cdbs debian/control autogeneration.
+ - Set DEB_AUTO_UPDATE_DEBIAN_CONTROL = yes.
+ - Move control to control.in.
+ - Add a @cdbs@ tag and replace Architecture with Cpu/System.
+ * control.in (Build-Depends): Add ruby.
+
+ -- Robert Millan <rmh@debian.org> Thu, 3 Feb 2005 22:33:39 +0100
+
+grub2 (0.6+20040805-1) unstable; urgency=low
+
+ * New upstream snapshot.
+ * Uploading to unstable so that powerpc users can be blessed by GRUB too.
+ * Use type-handling to generate dpkg arch list.
+ - control.in
+ - rules
+
+ -- Robert Millan <rmh@debian.org> Thu, 5 Aug 2004 20:50:16 +0200
+
+grub2 (0.6+20040502-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - Fix FTBFS on powerpc.
+
+ -- Robert Millan <rmh@debian.org> Sun, 2 May 2004 18:16:29 +0200
+
+grub2 (0.6+20040429-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - control (Architecture): Add powerpc.
+
+ -- Robert Millan <rmh@debian.org> Thu, 29 Apr 2004 20:41:31 +0200
+
+grub2 (0.6+20031125-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - patches/multiboot.diff: Nuked.
+ - install,docs: Update directory name.
+ * control (Maintainer): Set to pkg-grub-devel mailing list.
+ * control (Uploaders): Add myself.
+ * control (Architecture): Add freebsd-i386 and netbsd-i386.
+
+ -- Robert Millan <rmh@debian.org> Tue, 25 Nov 2003 23:48:18 +0100
+
+grub2 (0.6+20031114-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ - README.Debian: s/fat/ext2/g (We now have ext2fs support).
+ * Add multiboot support, thanks to Jeroen Dekkers for his patch.
+ - patches/multiboot.diff: New.
+ - control (Architecture): Add hurd-i386 (which needed multiboot).
+ * Rename package to grub2 (to follow upstream tendency).
+ - control: Ditto.
+ - README.Debian: Likewise.
+ * Switch to tarball mode.
+ - rules: Ditto.
+ - docs: Prefix paths in order to workaround dh_installdocs bug.
+ - install: Likewise, but not because of bug (should be in rules, actualy).
+ * Fix FTBFS. (Closes: #213868)
+ - control (Build-Depends): Add autoconf.
+ - control (Build-Conflicts): Add autoconf2.13.
+
+ -- Robert Millan <rmh@debian.org> Fri, 14 Nov 2003 13:16:12 +0100
+
+pupa (0.6+20031008-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ * Uploading to experimental.
+ * debian/control: Add Jason Thomas to Uploaders.
+
+ -- Robert Millan <rmh@debian.org> Wed, 8 Oct 2003 13:22:50 +0000
+
+pupa (0.6+20030915-1) unstable; urgency=low
+
+ * Initial Release. (Closes: #211030)
+
+ -- Robert Millan <rmh@debian.org> Mon, 15 Sep 2003 14:58:42 +0000
diff --git a/debian/clean b/debian/clean
new file mode 100644
index 0000000..c3bf84a
--- /dev/null
+++ b/debian/clean
@@ -0,0 +1,17 @@
+debian/grub-common.install
+debian/prep-bootdev
+grub-core/lib/libgcrypt-grub/mpi/mpi-asm-defs.h
+grub-core/lib/libgcrypt-grub/mpi/mpih-add1.c
+grub-core/lib/libgcrypt-grub/mpi/mpih-sub1.c
+grub-core/lib/libgcrypt-grub/mpi/mpih-mul1.c
+grub-core/lib/libgcrypt-grub/mpi/mpih-mul2.c
+grub-core/lib/libgcrypt-grub/mpi/mpih-mul3.c
+grub-core/lib/libgcrypt-grub/mpi/mpih-lshift.c
+grub-core/lib/libgcrypt-grub/mpi/mpih-rshift.c
+docs/*.info
+docs/stamp-vti
+docs/version.texi
+docs/stamp-1
+docs/version-dev.texi
+include/grub/gcrypt/g10lib.h
+po/grub.pot
diff --git a/debian/config.in b/debian/config.in
new file mode 100644
index 0000000..2922e4e
--- /dev/null
+++ b/debian/config.in
@@ -0,0 +1,92 @@
+#!/bin/sh
+set -e
+
+case `dpkg --print-architecture` in
+ kfreebsd-*)
+ # No migration from GRUB Legacy, no Linux cmdline
+ exit 0
+ ;;
+esac
+
+. /usr/share/debconf/confmodule
+
+priority=medium
+
+case @PACKAGE@ in
+ grub-pc)
+ if test -e /boot/grub/stage2 && test -e /boot/grub/menu.lst && ! test -e /boot/grub/core.img ; then
+
+ db_input high grub-pc/chainload_from_menu.lst || true
+
+ db_get grub-pc/kopt_extracted || true
+ # this check ensures we only do this once
+ if [ "$RET" = "false" ] ; then
+ kopt=`sed -ne "s/^# kopt=//p" /boot/grub/menu.lst | tr -s " " "\n" | grep -vx "\(ro\|root=[^ ]*\)" | paste -s -d ' '` || true
+ db_set grub2/linux_cmdline "${kopt}" || true
+ db_set grub-pc/kopt_extracted true || true
+ if [ "${kopt}" = "" ] ; then
+ # something smells bad. give user a chance to correct it.
+ priority=high
+ else
+ # if we got something from menu.lst, it must be correct?
+ priority=medium
+ fi
+ timeout=`sed -ne "s/^timeout[[:space:]][[:space:]]*//p" /boot/grub/menu.lst` || true
+ if [ "${timeout}" != "" ]; then
+ db_set grub-pc/timeout "${timeout}" || true
+ fi
+ if grep -q '^hiddenmenu\([[:space:]]\|$\)' /boot/grub/menu.lst; then
+ db_set grub-pc/hidden_timeout true || true
+ else
+ db_set grub-pc/hidden_timeout false || true
+ fi
+ fi
+ fi
+ ;;
+esac
+
+# This deliberately doesn't include /etc/default/grub.d/*.cfg, since we're
+# only sourcing this configuration file in order to prompt for values to
+# write back to /etc/default/grub.
+if [ -e /etc/default/grub ]; then
+ . /etc/default/grub
+fi
+
+if [ "${GRUB_CMDLINE_LINUX+set}" = set ]; then
+ db_set grub2/linux_cmdline "$GRUB_CMDLINE_LINUX"
+fi
+if [ "${GRUB_CMDLINE_LINUX_DEFAULT+set}" = set ]; then
+ db_set grub2/linux_cmdline_default "$GRUB_CMDLINE_LINUX_DEFAULT"
+fi
+# Watch for the inverted logic here...
+if [ "${GRUB_DISABLE_OS_PROBER+set}" = set ]; then
+ db_set grub2/enable_os_prober "false"
+fi
+
+case @PACKAGE@ in
+ grub-pc)
+ if [ "${GRUB_TIMEOUT}" != "" ]; then
+ db_set grub-pc/timeout "$GRUB_TIMEOUT"
+ fi
+ if [ "${GRUB_HIDDEN_TIMEOUT}" != "" ]; then
+ db_set grub-pc/hidden_timeout true
+ elif egrep -qs '^#?[[:space:]]*GRUB_HIDDEN_TIMEOUT=' /etc/default/grub; then
+ db_set grub-pc/hidden_timeout false
+ fi
+ ;;
+esac
+
+db_input ${priority} grub2/linux_cmdline || true
+db_input medium grub2/linux_cmdline_default || true
+db_input low grub2/enable_os_prober || true
+case @PACKAGE@ in
+ grub-*efi*)
+ db_input low grub2/force_efi_extra_removable || true
+ ;;
+esac
+case @PACKAGE@ in
+ grub-*efi*|grub-ieee1275)
+ db_input low grub2/update_nvram || true
+ ;;
+esac
+db_go
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..1c48f28
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,779 @@
+Source: grub2
+Section: admin
+Priority: optional
+Maintainer: GRUB Maintainers <pkg-grub-devel@alioth-lists.debian.net>
+Uploaders: Felix Zielcke <fzielcke@z-51.de>, Jordi Mallach <jordi@debian.org>, Steve McIntyre <93sam@debian.org>, Julian Andres Klode <jak@debian.org>
+Build-Depends: debhelper-compat (= 13),
+ patchutils,
+ python3,
+ flex,
+ bison,
+ po-debconf,
+ help2man,
+ texinfo,
+ gcc-12,
+ gcc-12-multilib [i386 kopensolaris-i386 any-amd64 any-ppc64 any-sparc],
+ xfonts-unifont,
+ libfreetype6-dev,
+ gettext,
+ libdevmapper-dev [linux-any],
+ libgeom-dev (>= 8.2+ds1-1~) [kfreebsd-any] | libgeom-dev (<< 8.2) [kfreebsd-any],
+ libsdl1.2-dev [!hurd-any],
+ xorriso,
+ qemu-system [i386 kfreebsd-i386 kopensolaris-i386 any-amd64],
+ cpio [i386 kopensolaris-i386 amd64 x32],
+ parted [!hurd-any],
+ libfuse-dev (>= 2.8.4-1.4) [linux-any kfreebsd-any],
+ fonts-dejavu-core,
+ liblzma-dev,
+ dosfstools [any-i386 any-amd64 any-arm64],
+ mtools [any-i386 any-amd64 any-arm64],
+ wamerican,
+ libparted-dev [any-powerpc any-ppc64 any-ppc64el],
+ pkg-config,
+ bash-completion,
+ libefiboot-dev [i386 amd64 ia64 x32 armel armhf arm64],
+ libefivar-dev [i386 amd64 ia64 x32 armel armhf arm64],
+Build-Conflicts: autoconf2.13, libzfs-dev, libnvpair-dev
+Standards-Version: 3.9.6
+Homepage: https://www.gnu.org/software/grub/
+Vcs-Git: https://salsa.debian.org/grub-team/grub.git
+Vcs-Browser: https://salsa.debian.org/grub-team/grub
+Rules-Requires-Root: no
+
+Package: grub2
+Section: oldlibs
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: grub-pc (= ${binary:Version}) [any-i386 any-amd64] | grub-ieee1275 (= ${binary:Version}) [any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64], ${misc:Depends}
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (dummy package)
+ This is a dummy transitional package to handle GRUB 2 upgrades. It can be
+ safely removed.
+
+Package: grub-linuxbios
+Section: oldlibs
+Architecture: any-i386 any-amd64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: grub-coreboot (= ${binary:Version}), ${misc:Depends}
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (dummy package)
+ This is a dummy transitional package that depends on grub-coreboot.
+
+Package: grub-efi
+Architecture: any-i386 any-amd64 any-arm64 any-ia64 any-arm
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${misc:Depends}, grub-efi-ia32 (= ${binary:Version}) [any-i386], grub-efi-amd64 (= ${binary:Version}) [any-amd64], grub-efi-arm64 (= ${binary:Version}) [any-arm64], grub-efi-ia64 (= ${binary:Version}) [any-ia64], grub-efi-arm (= ${binary:Version}) [any-arm]
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (dummy package)
+ This is a dummy package that depends on the grub-efi-$ARCH package most likely
+ to be appropriate for each architecture.
+
+Package: grub-common
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, gettext-base, ${lsb-base-depends}
+Replaces: grub-pc (<< 2.00-4), grub-ieee1275 (<< 2.00-4), grub-efi (<< 1.99-1), grub-coreboot (<< 2.00-4), grub-linuxbios (<< 1.96+20080831-1), grub-efi-ia32 (<< 2.00-4), grub-efi-amd64 (<< 2.00-4), grub-efi-ia64 (<< 2.00-4), grub-yeeloong (<< 2.00-4), init-select
+Recommends: os-prober (>= 1.33)
+Suggests: multiboot-doc, grub-emu [any-i386 any-amd64 any-powerpc], mtools [any-i386 any-amd64 any-ia64 any-arm any-arm64], xorriso (>= 0.5.6.pl00), desktop-base (>= 4.0.6), console-setup
+Conflicts: init-select
+# mdadm: See bugs #435983 and #455746
+Breaks: mdadm (<< 2.6.7-2), lupin-support (<< 0.55), friendly-recovery (<< 0.2.13), apport (<< 2.1.1)
+Multi-Arch: foreign
+Description: GRand Unified Bootloader (common files)
+ This package contains common files shared by the distinct flavours of GRUB.
+ It is shared between GRUB Legacy and GRUB 2, although a number of files
+ specific to GRUB 2 are here as long as they do not break GRUB Legacy.
+ .
+ grub-mkrescue needs the suggested packages mtools (for UEFI targets) and
+ xorriso.
+
+Package: grub2-common
+# Not Architecture: any because this package contains some things which are
+# only built when there is a real platform (e.g. grub-install), and the rest
+# of the package is not very useful in a utilities-only build.
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64 any-mipsel any-ia64 any-arm any-arm64
+Depends: grub-common (= ${binary:Version}), dpkg (>= 1.15.4), ${shlibs:Depends}, ${misc:Depends}
+Replaces: grub, grub-legacy, ${legacy-doc-br}, grub-common (<< 1.99-1), grub-pc (<< 2.02+dfsg1-7), grub-coreboot (<< 2.02+dfsg1-7), grub-efi-ia32 (<< 2.02+dfsg1-7), grub-efi-amd64 (<< 2.02+dfsg1-7), grub-efi-ia64 (<< 2.02+dfsg1-7), grub-efi-arm (<< 2.02+dfsg1-7), grub-efi-arm64 (<< 2.02+dfsg1-7), grub-ieee1275 (<< 2.02+dfsg1-7), grub-uboot (<< 2.02+dfsg1-7), grub-xen (<< 2.02+dfsg1-7), grub-yeeloong (<< 2.02+dfsg1-7), grub-cloud-amd64 (<< 0.0.4)
+Conflicts: grub-legacy
+Breaks: grub (<< 0.97-54), ${legacy-doc-br}, shim (<< 0.9+1474479173.6c180c6-0ubuntu1~), grub-pc (<< 2.02+dfsg1-7), grub-coreboot (<< 2.02+dfsg1-7), grub-efi-ia32 (<< 2.02+dfsg1-7), grub-efi-amd64 (<< 2.02+dfsg1-7), grub-efi-ia64 (<< 2.02+dfsg1-7), grub-efi-arm (<< 2.02+dfsg1-7), grub-efi-arm64 (<< 2.02+dfsg1-7), grub-ieee1275 (<< 2.02+dfsg1-7), grub-uboot (<< 2.02+dfsg1-7), grub-xen (<< 2.02+dfsg1-7), grub-yeeloong (<< 2.02+dfsg1-7), grub-cloud-amd64 (<< 0.0.4)
+Multi-Arch: foreign
+Description: GRand Unified Bootloader (common files for version 2)
+ This package contains common files shared by the distinct flavours of GRUB.
+ The files in this package are specific to GRUB 2, and would break GRUB
+ Legacy if installed on the same system.
+
+Package: grub-emu
+Architecture: any-i386 any-amd64 any-powerpc
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Replaces: grub-common (<= 1.97~beta3-1)
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (emulated version)
+ This package contains grub-emu, an emulated version of GRUB. It is only
+ provided for debugging purposes.
+
+Package: grub-emu-dbg
+Section: debug
+Architecture: any-i386 any-amd64 any-powerpc
+Depends: ${misc:Depends}, grub-emu (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (emulated debug files)
+ This package contains debugging files for grub-emu. You only need these if
+ you are trying to debug GRUB using its GDB stub.
+
+Package: grub-pc-bin
+Architecture: any-i386 any-amd64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Replaces: grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-pc (<< 1.99-1)
+Suggests: desktop-base (>= 4.0.6)
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (PC/BIOS modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ - VESA-based graphical mode with background image support and complete 24-bit
+ color set.
+ - Support for extended charsets. Users can write UTF-8 text to their menu
+ entries.
+ .
+ This package contains GRUB modules that have been built for use with the
+ traditional PC/BIOS architecture. It can be installed in parallel with
+ other flavours, but will not automatically install GRUB as the active boot
+ loader nor automatically update grub.cfg on upgrade unless grub-pc is also
+ installed.
+
+Package: grub-pc-dbg
+Section: debug
+Architecture: any-i386 any-amd64
+Depends: ${misc:Depends}, grub-pc-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (PC/BIOS debug files)
+ This package contains debugging files for grub-pc-bin. You only need these
+ if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-pc
+Architecture: any-i386 any-amd64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-pc-bin (= ${binary:Version}), ucf, freebsd-utils (>= 8.0-4) [kfreebsd-any], ${gfxpayload-depends}
+Replaces: grub, grub-legacy, grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-efi-amd64, grub-efi-ia32, grub-coreboot, grub-ieee1275
+Conflicts: grub (<< 0.97-54), grub-legacy, grub-efi-amd64, grub-efi-ia32, grub-coreboot, grub-ieee1275, grub-xen
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (PC/BIOS version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ - VESA-based graphical mode with background image support and complete 24-bit
+ color set.
+ - Support for extended charsets. Users can write UTF-8 text to their menu
+ entries.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with the traditional PC/BIOS architecture. Installing this package
+ indicates that this version of GRUB should be the active boot loader.
+
+Package: grub-rescue-pc
+Architecture: any-i386 any-amd64
+Depends: ${misc:Depends}
+Multi-Arch: foreign
+Description: GRUB bootable rescue images, version 2 (PC/BIOS version)
+ This package contains three GRUB rescue images that have been built for use
+ with the traditional PC/BIOS architecture:
+ .
+ - grub-rescue-floppy.img: floppy image.
+ - grub-rescue-cdrom.iso: El Torito CDROM image.
+ - grub-rescue-usb.img: USB image.
+
+Package: grub-coreboot-bin
+Architecture: any-i386 any-amd64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Replaces: grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-linuxbios, grub-coreboot (<< 1.99-1)
+Conflicts: grub-linuxbios (<< ${source:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Coreboot modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with
+ platforms running the Coreboot firmware. It can be installed in parallel
+ with other flavours, but will not automatically install GRUB as the active
+ boot loader nor automatically update grub.cfg on upgrade unless
+ grub-coreboot is also installed.
+
+Package: grub-coreboot-dbg
+Section: debug
+Architecture: any-i386 any-amd64
+Depends: ${misc:Depends}, grub-coreboot-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Coreboot debug files)
+ This package contains debugging files for grub-coreboot-bin. You only need
+ these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-coreboot
+Architecture: any-i386 any-amd64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-coreboot-bin (= ${binary:Version}), ucf
+Replaces: grub-legacy, grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-linuxbios, grub-efi-amd64, grub-efi-ia32, grub-pc, grub-ieee1275
+Conflicts: grub (<< 0.97-54), grub-legacy, grub-linuxbios (<< ${source:Version}), grub-efi-amd64, grub-efi-ia32, grub-pc, grub-ieee1275, grub-xen
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Coreboot version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with platforms running the Coreboot firmware. Installing this package
+ indicates that this version of GRUB should be the active boot loader.
+
+Package: grub-efi-ia32-bin
+Architecture: any-i386 any-amd64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Recommends: grub-efi-ia32-signed [i386], efibootmgr [linux-any]
+Replaces: grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-efi, grub-efi-ia32 (<< 1.99-1)
+Multi-Arch: foreign
+XB-Efi-Vendor: ${efi:Vendor}
+Description: GRand Unified Bootloader, version 2 (EFI-IA32 modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with the
+ EFI-IA32 architecture, as used by Intel Macs (unless a BIOS interface has
+ been activated). It can be installed in parallel with other flavours, but
+ will not automatically install GRUB as the active boot loader nor
+ automatically update grub.cfg on upgrade unless grub-efi-ia32 is also
+ installed.
+
+Package: grub-efi-ia32-dbg
+Section: debug
+Architecture: any-i386 any-amd64
+Depends: ${misc:Depends}, grub-efi-ia32-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (EFI-IA32 debug files)
+ This package contains debugging files for grub-efi-ia32-bin. You only need
+ these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-efi-ia32
+Architecture: any-i386 any-amd64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-ia32-bin (= ${binary:Version}), ucf
+Replaces: grub, grub-legacy, grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-efi, grub-efi-amd64, grub-pc, grub-coreboot, grub-ieee1275
+Conflicts: grub (<< 0.97-54), grub-legacy, grub-efi-amd64, grub-pc, grub-coreboot, grub-ieee1275, grub-xen, elilo
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (EFI-IA32 version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with the EFI-IA32 architecture, as used by Intel Macs (unless a BIOS
+ interface has been activated). Installing this package indicates that this
+ version of GRUB should be the active boot loader.
+
+Package: grub-efi-ia32-signed-template
+Architecture: i386
+Depends: ${misc:Depends}
+Description: GRand Unified Bootloader, version 2 (EFI-IA32 signing template)
+ This package contains template files for grub-efi-ia32-signed.
+ This is only needed for Secure Boot signing.
+
+Package: grub-efi-amd64-bin
+Architecture: i386 kopensolaris-i386 any-amd64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Recommends: grub-efi-amd64-signed [amd64], efibootmgr [linux-any]
+Replaces: grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-efi-amd64 (<< 1.99-1)
+Multi-Arch: foreign
+XB-Efi-Vendor: ${efi:Vendor}
+Description: GRand Unified Bootloader, version 2 (EFI-AMD64 modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with the
+ EFI-AMD64 architecture, as used by Intel Macs (unless a BIOS interface has
+ been activated). It can be installed in parallel with other flavours, but
+ will not automatically install GRUB as the active boot loader nor
+ automatically update grub.cfg on upgrade unless grub-efi-amd64 is also
+ installed.
+
+Package: grub-efi-amd64-dbg
+Section: debug
+Architecture: i386 kopensolaris-i386 any-amd64
+Depends: ${misc:Depends}, grub-efi-amd64-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (EFI-AMD64 debug files)
+ This package contains debugging files for grub-efi-amd64-bin. You only
+ need these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-efi-amd64
+Architecture: i386 kopensolaris-i386 any-amd64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-amd64-bin (= ${binary:Version}), ucf
+Replaces: grub, grub-legacy, grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-pc, grub-efi-ia32, grub-coreboot, grub-ieee1275
+Conflicts: grub, grub-legacy, grub-efi-ia32, grub-pc, grub-coreboot, grub-ieee1275, grub-xen, elilo
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (EFI-AMD64 version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with the EFI-AMD64 architecture, as used by Intel Macs (unless a BIOS
+ interface has been activated). Installing this package indicates that this
+ version of GRUB should be the active boot loader.
+
+Package: grub-efi-amd64-signed-template
+Architecture: amd64
+Depends: ${misc:Depends}
+Description: GRand Unified Bootloader, version 2 (EFI-AMD64 signing template)
+ This package contains template files for grub-efi-amd64-signed.
+ This is only needed for Secure Boot signing.
+
+Package: grub-efi-ia64-bin
+Architecture: any-ia64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Multi-Arch: foreign
+XB-Efi-Vendor: ${efi:Vendor}
+Description: GRand Unified Bootloader, version 2 (IA64 modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use on IA64.
+ It can be installed in parallel with other flavours, but will not
+ automatically install GRUB as the active boot loader nor automatically
+ update grub.cfg on upgrade unless grub-efi-ia64 is also installed.
+
+Package: grub-efi-ia64-dbg
+Section: debug
+Architecture: any-ia64
+Depends: ${misc:Depends}, grub-efi-ia64-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (IA64 debug files)
+ This package contains debugging files for grub-efi-ia64-bin. You only need
+ these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-efi-ia64
+Architecture: any-ia64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-ia64-bin (= ${binary:Version}), ucf
+Conflicts: elilo
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (IA64 version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use on IA64. Installing this package indicates that this version of GRUB
+ should be the active boot loader.
+
+Package: grub-efi-arm-bin
+Architecture: any-arm
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Recommends: efibootmgr [linux-any]
+Multi-Arch: foreign
+XB-Efi-Vendor: ${efi:Vendor}
+Description: GRand Unified Bootloader, version 2 (ARM UEFI modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use on ARM
+ systems with UEFI. It can be installed in parallel with other flavours,
+ but will not automatically install GRUB as the active boot loader nor
+ automatically update grub.cfg on upgrade unless grub-efi-arm is also
+ installed.
+
+Package: grub-efi-arm-dbg
+Section: debug
+Architecture: any-arm
+Depends: ${misc:Depends}, grub-efi-arm-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM UEFI debug files)
+ This package contains debugging files for grub-efi-arm-bin. You only need
+ these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-efi-arm
+Architecture: any-arm
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-arm-bin (= ${binary:Version}), ucf
+Conflicts: grub-uboot
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM UEFI version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use on ARM systems with UEFI. Installing this package indicates that this
+ version of GRUB should be the active boot loader.
+
+Package: grub-efi-arm64-bin
+Architecture: any-arm64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Recommends: grub-efi-arm64-signed [arm64], efibootmgr [linux-any]
+Multi-Arch: foreign
+XB-Efi-Vendor: ${efi:Vendor}
+Description: GRand Unified Bootloader, version 2 (ARM64 UEFI modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use on ARM64
+ systems with UEFI. It can be installed in parallel with other flavours,
+ but will not automatically install GRUB as the active boot loader nor
+ automatically update grub.cfg on upgrade unless grub-efi-arm64 is also
+ installed.
+
+Package: grub-efi-arm64-dbg
+Section: debug
+Architecture: any-arm64
+Depends: ${misc:Depends}, grub-efi-arm64-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM64 UEFI debug files)
+ This package contains debugging files for grub-efi-arm64-bin. You only
+ need these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-efi-arm64
+Architecture: any-arm64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-arm64-bin (= ${binary:Version}), ucf
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM64 UEFI version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use on ARM64 systems with UEFI. Installing this package indicates that
+ this version of GRUB should be the active boot loader.
+
+Package: grub-efi-arm64-signed-template
+Architecture: arm64
+Depends: ${misc:Depends}
+Description: GRand Unified Bootloader, version 2 (ARM64 UEFI signing template)
+ This package contains template files for grub-efi-arm64-signed.
+ This is only needed for Secure Boot signing.
+
+Package: grub-ieee1275-bin
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Replaces: grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-ieee1275 (<< 1.99-1)
+Suggests: genisoimage [any-powerpc any-ppc64 any-ppc64el]
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Open Firmware modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with Open
+ Firmware implementations. It can be installed in parallel with other
+ flavours, but will not automatically install GRUB as the active boot loader
+ nor automatically update grub.cfg on upgrade unless grub-ieee1275 is also
+ installed.
+
+Package: grub-ieee1275-dbg
+Section: debug
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64
+Depends: ${misc:Depends}, grub-ieee1275-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Open Firmware debug files)
+ This package contains debugging files for grub-ieee1275-bin. You only
+ need these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-ieee1275
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-ieee1275-bin (= ${binary:Version}), ucf, powerpc-ibm-utils (>= 1.2.12-1) [any-powerpc any-ppc64 any-ppc64el], powerpc-utils [any-powerpc any-ppc64 any-ppc64el]
+Replaces: grub-legacy, grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-efi-amd64, grub-efi-ia32, grub-coreboot, grub-pc
+Conflicts: grub (<< 0.97-54), grub-legacy, grub-efi-amd64, grub-efi-ia32, grub-coreboot, grub-pc, grub-xen
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Open Firmware version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with Open Firmware implementations. Installing this package indicates
+ that this version of GRUB should be the active boot loader.
+
+Package: grub-firmware-qemu
+Architecture: any-i386 any-amd64
+Depends: ${misc:Depends}
+Recommends: qemu-system-x86
+Enhances: qemu-system-x86
+Multi-Arch: foreign
+Description: GRUB firmware image for QEMU
+ This package contains a binary of GRUB that has been built for use as
+ firmware for QEMU. It can be used as a replacement for other PC BIOS
+ images provided by seabios, bochsbios, and so on.
+ .
+ In order to make QEMU use this firmware, simply add `-bios grub.bin' when
+ invoking it.
+ .
+ This package behaves in the same way as GRUB for coreboot, but doesn't
+ contain any code from coreboot itself, and is only suitable for QEMU. If
+ you want to install GRUB as firmware on real hardware, you need to use the
+ grub-coreboot package, and manually combine that with coreboot.
+
+Package: grub-uboot-bin
+Architecture: any-arm
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM U-Boot modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with ARM
+ systems with U-Boot. It can be installed in parallel with other flavours,
+ but will not automatically install GRUB as the active boot loader nor
+ automatically update grub.cfg on upgrade unless grub-uboot is also
+ installed.
+
+Package: grub-uboot-dbg
+Section: debug
+Architecture: any-arm
+Depends: ${misc:Depends}, grub-uboot-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM U-Boot debug files)
+ This package contains debugging files for grub-uboot-bin. You only need
+ these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-uboot
+Architecture: any-arm
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-uboot-bin (= ${binary:Version}), ucf
+Conflicts: grub-efi-arm
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (ARM U-Boot version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with ARM systems with U-Boot. Installing this package indicates that
+ this version of GRUB should be the active boot loader.
+
+Package: grub-xen-bin
+Architecture: i386 amd64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Xen modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with the
+ Xen hypervisor (i.e. PV-GRUB). It can be installed in parallel with other
+ flavours, but will not automatically install GRUB as the active boot loader
+ nor automatically update grub.cfg on upgrade unless grub-xen is also
+ installed.
+
+Package: grub-xen-dbg
+Section: debug
+Architecture: i386 amd64
+Depends: ${misc:Depends}, grub-xen-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Xen debug files)
+ This package contains debugging files for grub-xen-bin. You only need
+ these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-xen
+Architecture: i386 amd64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-xen-bin (= ${binary:Version}), ucf
+Conflicts: grub (<< 0.97-54), grub-legacy, grub-efi-amd64, grub-efi-ia32, grub-coreboot, grub-ieee1275, grub-pc
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Xen version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with the Xen hypervisor (i.e. PV-GRUB). Installing this package
+ indicates that this version of GRUB should be the active boot loader.
+
+Package: grub-xen-host
+Architecture: i386 amd64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-xen-bin (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Xen host version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package arranges for GRUB binary images which can be used to boot a Xen
+ guest (i.e. PV-GRUB) to be present in the control domain filesystem.
+
+Package: grub-yeeloong-bin
+Architecture: any-mipsel
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Replaces: grub-common (<< 1.98+20100617-2), grub-yeeloong (<< 1.99-1)
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Yeeloong modules)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains GRUB modules that have been built for use with the
+ Lemote Yeeloong laptop. It can be installed in parallel with other
+ flavours, but will not automatically install GRUB as the active boot loader
+ nor automatically update grub.cfg on upgrade unless grub-yeeloong is also
+ installed.
+
+Package: grub-yeeloong-dbg
+Section: debug
+Architecture: any-mipsel
+Depends: ${misc:Depends}, grub-yeeloong-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Yeeloong debug files)
+ This package contains debugging files for grub-yeeloong-bin. You only
+ need these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-yeeloong
+Architecture: any-mipsel
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-yeeloong-bin (= ${binary:Version}), ucf
+Replaces: grub-common (<< 1.98+20100617-2)
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (Yeeloong version)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use with the Lemote Yeeloong laptop. Installing this package indicates
+ that this version of GRUB should be the active boot loader.
+
+Package: grub-theme-starfield
+# Could be Architecture: any, but in practice this package is useless in a
+# utilities-only build.
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64 any-mipsel any-ia64 any-arm any-arm64
+Depends: ${misc:Depends}, grub-common (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (starfield theme)
+ This is the default theme for GRUB's graphical menu.
+
+Package: grub-mount-udeb
+Package-Type: udeb
+Section: debian-installer
+Architecture: linux-any kfreebsd-any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: export GRUB filesystems using FUSE
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..20be383
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,375 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: GNU GRUB
+Source: https://www.gnu.org/software/grub/
+
+Files: *
+Copyright: 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc
+License: GPL-3+
+
+
+Files: debian/*
+Copyright: 2003, 2004, 2005, 2006, 2007, 2008, 2009, Robert Millan
+ 2005, 2006, 2007, Otavio Salvador
+ 2008, 2009, Felix Zielcke
+ 2009, Jordi Mallach
+License: GPL-3+
+
+Files: debian/grub-extras/*
+Copyright: Nathan Coulson
+ 2003, 2007 Free Software Foundation, Inc
+ 2003 NIIBE Yutaka
+License: GPL-3+
+
+Files: themes/starfield/*
+Copyright: 2012 Free Software Foundation, Inc
+License: CC-BY-SA-3.0
+
+Files: themes/starfield/theme.txt
+Copyright: 2011 Daniel Tschudi
+License: Expat
+
+License: GPL-3+
+ On Debian systems the full text of the GNU General Public
+ License can be found in the `/usr/share/common-licenses/GPL-3'
+ file.
+
+License: CC-BY-SA-3.0
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL
+ SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT
+ RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS"
+ BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION
+ PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
+ .
+ License
+ .
+ THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+ COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+ COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+ AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+ .
+ BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO
+ BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE
+ CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED
+ HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
+ .
+ 1. Definitions
+ "Adaptation" means a work based upon the Work, or upon the Work and
+ other pre-existing works, such as a translation, adaptation, derivative
+ work, arrangement of music or other alterations of a literary or
+ artistic work, or phonogram or performance and includes cinematographic
+ adaptations or any other form in which the Work may be recast,
+ transformed, or adapted including in any form recognizably derived from
+ the original, except that a work that constitutes a Collection will not
+ be considered an Adaptation for the purpose of this License. For the
+ avoidance of doubt, where the Work is a musical work, performance or
+ phonogram, the synchronization of the Work in timed-relation with a
+ moving image ("synching") will be considered an Adaptation for the
+ purpose of this License.
+ "Collection" means a collection of literary or artistic works, such as
+ encyclopedias and anthologies, or performances, phonograms or
+ broadcasts, or other works or subject matter other than works listed in
+ Section 1(f) below, which, by reason of the selection and arrangement of
+ their contents, constitute intellectual creations, in which the Work is
+ included in its entirety in unmodified form along with one or more other
+ contributions, each constituting separate and independent works in
+ themselves, which together are assembled into a collective whole. A work
+ that constitutes a Collection will not be considered an Adaptation (as
+ defined below) for the purposes of this License.
+ "Creative Commons Compatible License" means a license that is listed at
+ http://creativecommons.org/compatiblelicenses that has been approved by
+ Creative Commons as being essentially equivalent to this License,
+ including, at a minimum, because that license: (i) contains terms that
+ have the same purpose, meaning and effect as the License Elements of
+ this License; and, (ii) explicitly permits the relicensing of
+ adaptations of works made available under that license under this
+ License or a Creative Commons jurisdiction license with the same License
+ Elements as this License.
+ "Distribute" means to make available to the public the original and
+ copies of the Work or Adaptation, as appropriate, through sale or other
+ transfer of ownership.
+ "License Elements" means the following high-level license attributes as
+ selected by Licensor and indicated in the title of this License:
+ Attribution, ShareAlike.
+ "Licensor" means the individual, individuals, entity or entities that
+ offer(s) the Work under the terms of this License.
+ "Original Author" means, in the case of a literary or artistic work, the
+ individual, individuals, entity or entities who created the Work or if
+ no individual or entity can be identified, the publisher; and in
+ addition (i) in the case of a performance the actors, singers,
+ musicians, dancers, and other persons who act, sing, deliver, declaim,
+ play in, interpret or otherwise perform literary or artistic works or
+ expressions of folklore; (ii) in the case of a phonogram the producer
+ being the person or legal entity who first fixes the sounds of a
+ performance or other sounds; and, (iii) in the case of broadcasts, the
+ organization that transmits the broadcast.
+ "Work" means the literary and/or artistic work offered under the terms
+ of this License including without limitation any production in the
+ literary, scientific and artistic domain, whatever may be the mode or
+ form of its expression including digital form, such as a book, pamphlet
+ and other writing; a lecture, address, sermon or other work of the same
+ nature; a dramatic or dramatico-musical work; a choreographic work or
+ entertainment in dumb show; a musical composition with or without words;
+ a cinematographic work to which are assimilated works expressed by a
+ process analogous to cinematography; a work of drawing, painting,
+ architecture, sculpture, engraving or lithography; a photographic work
+ to which are assimilated works expressed by a process analogous to
+ photography; a work of applied art; an illustration, map, plan, sketch
+ or three-dimensional work relative to geography, topography,
+ architecture or science; a performance; a broadcast; a phonogram; a
+ compilation of data to the extent it is protected as a copyrightable
+ work; or a work performed by a variety or circus performer to the extent
+ it is not otherwise considered a literary or artistic work.
+ "You" means an individual or entity exercising rights under this License
+ who has not previously violated the terms of this License with respect
+ to the Work, or who has received express permission from the Licensor to
+ exercise rights under this License despite a previous violation.
+ "Publicly Perform" means to perform public recitations of the Work and
+ to communicate to the public those public recitations, by any means or
+ process, including by wire or wireless means or public digital
+ performances; to make available to the public Works in such a way that
+ members of the public may access these Works from a place and at a place
+ individually chosen by them; to perform the Work to the public by any
+ means or process and the communication to the public of the performances
+ of the Work, including by public digital performance; to broadcast and
+ rebroadcast the Work by any means including signs, sounds or images.
+ "Reproduce" means to make copies of the Work by any means including
+ without limitation by sound or visual recordings and the right of
+ fixation and reproducing fixations of the Work, including storage of a
+ protected performance or phonogram in digital form or other electronic
+ medium.
+ .
+ 2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+ limit, or restrict any uses free from copyright or rights arising from
+ limitations or exceptions that are provided for in connection with the
+ copyright protection under copyright law or other applicable laws.
+ .
+ 3. License Grant. Subject to the terms and conditions of this License,
+ Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+ perpetual (for the duration of the applicable copyright) license to
+ exercise the rights in the Work as stated below:
+ .
+ to Reproduce the Work, to incorporate the Work into one or more
+ Collections, and to Reproduce the Work as incorporated in the
+ Collections;
+ to create and Reproduce Adaptations provided that any such Adaptation,
+ including any translation in any medium, takes reasonable steps to
+ clearly label, demarcate or otherwise identify that changes were made to
+ the original Work. For example, a translation could be marked "The
+ original work was translated from English to Spanish," or a modification
+ could indicate "The original work has been modified.";
+ to Distribute and Publicly Perform the Work including as incorporated in
+ Collections; and,
+ to Distribute and Publicly Perform Adaptations.
+ .
+ For the avoidance of doubt:
+ Non-waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme cannot be waived, the Licensor reserves
+ the exclusive right to collect such royalties for any exercise by
+ You of the rights granted under this License;
+ Waivable Compulsory License Schemes. In those jurisdictions in which
+ the right to collect royalties through any statutory or compulsory
+ licensing scheme can be waived, the Licensor waives the exclusive
+ right to collect such royalties for any exercise by You of the
+ rights granted under this License; and,
+ Voluntary License Schemes. The Licensor waives the right to collect
+ royalties, whether individually or, in the event that the Licensor
+ is a member of a collecting society that administers voluntary
+ licensing schemes, via that society, from any exercise by You of the
+ rights granted under this License.
+ .
+ The above rights may be exercised in all media and formats whether now
+ known or hereafter devised. The above rights include the right to make such
+ modifications as are technically necessary to exercise the rights in other
+ media and formats. Subject to Section 8(f), all rights not expressly
+ granted by Licensor are hereby reserved.
+ .
+ 4. Restrictions. The license granted in Section 3 above is expressly made
+ subject to and limited by the following restrictions:
+ .
+ You may Distribute or Publicly Perform the Work only under the terms of
+ this License. You must include a copy of, or the Uniform Resource
+ Identifier (URI) for, this License with every copy of the Work You
+ Distribute or Publicly Perform. You may not offer or impose any terms on
+ the Work that restrict the terms of this License or the ability of the
+ recipient of the Work to exercise the rights granted to that recipient
+ under the terms of the License. You may not sublicense the Work. You
+ must keep intact all notices that refer to this License and to the
+ disclaimer of warranties with every copy of the Work You Distribute or
+ Publicly Perform. When You Distribute or Publicly Perform the Work, You
+ may not impose any effective technological measures on the Work that
+ restrict the ability of a recipient of the Work from You to exercise the
+ rights granted to that recipient under the terms of the License. This
+ Section 4(a) applies to the Work as incorporated in a Collection, but
+ this does not require the Collection apart from the Work itself to be
+ made subject to the terms of this License. If You create a Collection,
+ upon notice from any Licensor You must, to the extent practicable,
+ remove from the Collection any credit as required by Section 4(c), as
+ requested. If You create an Adaptation, upon notice from any Licensor
+ You must, to the extent practicable, remove from the Adaptation any
+ credit as required by Section 4(c), as requested.
+ You may Distribute or Publicly Perform an Adaptation only under the
+ terms of: (i) this License; (ii) a later version of this License with
+ the same License Elements as this License; (iii) a Creative Commons
+ jurisdiction license (either this or a later license version) that
+ contains the same License Elements as this License (e.g.,
+ Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible
+ License. If you license the Adaptation under one of the licenses
+ mentioned in (iv), you must comply with the terms of that license. If
+ you license the Adaptation under the terms of any of the licenses
+ mentioned in (i), (ii) or (iii) (the "Applicable License"), you must
+ comply with the terms of the Applicable License generally and the
+ following provisions: (I) You must include a copy of, or the URI for,
+ the Applicable License with every copy of each Adaptation You Distribute
+ or Publicly Perform; (II) You may not offer or impose any terms on the
+ Adaptation that restrict the terms of the Applicable License or the
+ ability of the recipient of the Adaptation to exercise the rights
+ granted to that recipient under the terms of the Applicable License;
+ (III) You must keep intact all notices that refer to the Applicable
+ License and to the disclaimer of warranties with every copy of the Work
+ as included in the Adaptation You Distribute or Publicly Perform; (IV)
+ when You Distribute or Publicly Perform the Adaptation, You may not
+ impose any effective technological measures on the Adaptation that
+ restrict the ability of a recipient of the Adaptation from You to
+ exercise the rights granted to that recipient under the terms of the
+ Applicable License. This Section 4(b) applies to the Adaptation as
+ incorporated in a Collection, but this does not require the Collection
+ apart from the Adaptation itself to be made subject to the terms of the
+ Applicable License.
+ If You Distribute, or Publicly Perform the Work or any Adaptations or
+ Collections, You must, unless a request has been made pursuant to
+ Section 4(a), keep intact all copyright notices for the Work and
+ provide, reasonable to the medium or means You are utilizing: (i) the
+ name of the Original Author (or pseudonym, if applicable) if supplied,
+ and/or if the Original Author and/or Licensor designate another party or
+ parties (e.g., a sponsor institute, publishing entity, journal) for
+ attribution ("Attribution Parties") in Licensor's copyright notice,
+ terms of service or by other reasonable means, the name of such party or
+ parties; (ii) the title of the Work if supplied; (iii) to the extent
+ reasonably practicable, the URI, if any, that Licensor specifies to be
+ associated with the Work, unless such URI does not refer to the
+ copyright notice or licensing information for the Work; and (iv) ,
+ consistent with Ssection 3(b), in the case of an Adaptation, a credit
+ identifying the use of the Work in the Adaptation (e.g., "French
+ translation of the Work by Original Author," or "Screenplay based on
+ original Work by Original Author"). The credit required by this Section
+ 4(c) may be implemented in any reasonable manner; provided, however,
+ that in the case of a Adaptation or Collection, at a minimum such credit
+ will appear, if a credit for all contributing authors of the Adaptation
+ or Collection appears, then as part of these credits and in a manner at
+ least as prominent as the credits for the other contributing authors.
+ For the avoidance of doubt, You may only use the credit required by this
+ Section for the purpose of attribution in the manner set out above and,
+ by exercising Your rights under this License, You may not implicitly or
+ explicitly assert or imply any connection with, sponsorship or
+ endorsement by the Original Author, Licensor and/or Attribution Parties,
+ as appropriate, of You or Your use of the Work, without the separate,
+ express prior written permission of the Original Author, Licensor and/or
+ Attribution Parties.
+ Except as otherwise agreed in writing by the Licensor or as may be
+ otherwise permitted by applicable law, if You Reproduce, Distribute or
+ Publicly Perform the Work either by itself or as part of any Adaptations
+ or Collections, You must not distort, mutilate, modify or take other
+ derogatory action in relation to the Work which would be prejudicial to
+ the Original Author's honor or reputation. Licensor agrees that in those
+ jurisdictions (e.g. Japan), in which any exercise of the right granted
+ in Section 3(b) of this License (the right to make Adaptations) would be
+ deemed to be a distortion, mutilation, modification or other derogatory
+ action prejudicial to the Original Author's honor and reputation, the
+ Licensor will waive or not assert, as appropriate, this Section, to the
+ fullest extent permitted by the applicable national law, to enable You
+ to reasonably exercise Your right under Section 3(b) of this License
+ (right to make Adaptations) but not otherwise.
+ .
+ 5. Representations, Warranties and Disclaimer
+ .
+ UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+ OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+ KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+ INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT
+ OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER
+ OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF
+ IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+ .
+ 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+ LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY
+ SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING
+ OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ .
+ 7. Termination
+ .
+ This License and the rights granted hereunder will terminate
+ automatically upon any breach by You of the terms of this License.
+ Individuals or entities who have received Adaptations or Collections
+ from You under this License, however, will not have their licenses
+ terminated provided such individuals or entities remain in full
+ compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+ survive any termination of this License.
+ Subject to the above terms and conditions, the license granted here is
+ perpetual (for the duration of the applicable copyright in the Work).
+ Notwithstanding the above, Licensor reserves the right to release the
+ Work under different license terms or to stop distributing the Work at
+ any time; provided, however that any such election will not serve to
+ withdraw this License (or any other license that has been, or is
+ required to be, granted under the terms of this License), and this
+ License will continue in full force and effect unless terminated as
+ stated above.
+ .
+ 8. Miscellaneous
+ .
+ Each time You Distribute or Publicly Perform the Work or a Collection,
+ the Licensor offers to the recipient a license to the Work on the same
+ terms and conditions as the license granted to You under this License.
+ Each time You Distribute or Publicly Perform an Adaptation, Licensor
+ offers to the recipient a license to the original Work on the same terms
+ and conditions as the license granted to You under this License.
+ If any provision of this License is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of
+ the remainder of the terms of this License, and without further action
+ by the parties to this agreement, such provision shall be reformed to
+ the minimum extent necessary to make such provision valid and
+ enforceable.
+ No term or provision of this License shall be deemed waived and no
+ breach consented to unless such waiver or consent shall be in writing
+ and signed by the party to be charged with such waiver or consent.
+ This License constitutes the entire agreement between the parties with
+ respect to the Work licensed here. There are no understandings,
+ agreements or representations with respect to the Work not specified
+ here. Licensor shall not be bound by any additional provisions that may
+ appear in any communication from You. This License may not be modified
+ without the mutual written agreement of the Licensor and You.
+ The rights granted under, and the subject matter referenced, in this
+ License were drafted utilizing the terminology of the Berne Convention
+ for the Protection of Literary and Artistic Works (as amended on
+ September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+ Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and
+ the Universal Copyright Convention (as revised on July 24, 1971). These
+ rights and subject matter take effect in the relevant jurisdiction in
+ which the License terms are sought to be enforced according to the
+ corresponding provisions of the implementation of those treaty
+ provisions in the applicable national law. If the standard suite of
+ rights granted under applicable copyright law includes additional rights
+ not granted under this License, such additional rights are deemed to be
+ included in the License; this License is not intended to restrict the
+ license of any rights under applicable law.
+
+License: Expat
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
diff --git a/debian/default/grub b/debian/default/grub
new file mode 100644
index 0000000..03f98ec
--- /dev/null
+++ b/debian/default/grub
@@ -0,0 +1,39 @@
+# If you change this file, run 'update-grub' afterwards to update
+# /boot/grub/grub.cfg.
+# For full documentation of the options in this file, see:
+# info -f grub -n 'Simple configuration'
+
+GRUB_DEFAULT=0
+GRUB_TIMEOUT=@DEFAULT_TIMEOUT@
+GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
+GRUB_CMDLINE_LINUX_DEFAULT="@DEFAULT_CMDLINE@"
+GRUB_CMDLINE_LINUX=""
+
+# If your computer has multiple operating systems installed, then you
+# probably want to run os-prober. However, if your computer is a host
+# for guest OSes installed via LVM or raw disk devices, running
+# os-prober can cause damage to those guest OSes as it mounts
+# filesystems to look for things.
+GRUB_DISABLE_OS_PROBER=true
+
+# Uncomment to enable BadRAM filtering, modify to suit your needs
+# This works with Linux (no patch required) and with any kernel that obtains
+# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
+#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
+
+# Uncomment to disable graphical terminal
+#GRUB_TERMINAL=console
+
+# The resolution used on graphical terminal
+# note that you can use only modes which your graphic card supports via VBE
+# you can see them in real GRUB with the command `vbeinfo'
+#GRUB_GFXMODE=640x480
+
+# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
+#GRUB_DISABLE_LINUX_UUID=true
+
+# Uncomment to disable generation of recovery mode menu entries
+#GRUB_DISABLE_RECOVERY="true"
+
+# Uncomment to get a beep at grub start
+#GRUB_INIT_TUNE="480 440 1"
diff --git a/debian/default/grub.md5sum b/debian/default/grub.md5sum
new file mode 100644
index 0000000..e8265dc
--- /dev/null
+++ b/debian/default/grub.md5sum
@@ -0,0 +1,3 @@
+dfad90339e4227d432636ed7d4483744 experimental_1.96+20081129-1
+e916b60d7de71969dd7bad5a809fb9dc lenny_1.96+20080724-16
+965e5137eff659cded3adb640357c33d maverick_1.98+20100705-1ubuntu1
diff --git a/debian/dirs.in b/debian/dirs.in
new file mode 100644
index 0000000..e53f2b0
--- /dev/null
+++ b/debian/dirs.in
@@ -0,0 +1,3 @@
+usr/bin
+usr/sbin
+usr/share/grub
diff --git a/debian/grub-common.bash-completion.in b/debian/grub-common.bash-completion.in
new file mode 100644
index 0000000..cd2acce
--- /dev/null
+++ b/debian/grub-common.bash-completion.in
@@ -0,0 +1 @@
+debian/tmp-grub-@COMMON_PLATFORM@/etc/bash_completion.d/grub
diff --git a/debian/grub-common.dirs b/debian/grub-common.dirs
new file mode 100644
index 0000000..3d70df4
--- /dev/null
+++ b/debian/grub-common.dirs
@@ -0,0 +1,2 @@
+usr/sbin
+var/lib/grub/ucf
diff --git a/debian/grub-common.examples b/debian/grub-common.examples
new file mode 100644
index 0000000..5237b2a
--- /dev/null
+++ b/debian/grub-common.examples
@@ -0,0 +1 @@
+docs/grub.cfg
diff --git a/debian/grub-common.init b/debian/grub-common.init
new file mode 100644
index 0000000..fd8314f
--- /dev/null
+++ b/debian/grub-common.init
@@ -0,0 +1,39 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides: grub-common
+# Required-Start: $all
+# Required-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: Record successful boot for GRUB
+# Description: GRUB displays the boot menu at the next boot if it
+# believes that the previous boot failed. This script
+# informs it that the system booted successfully.
+### END INIT INFO
+
+command -v grub-editenv >/dev/null || exit 0
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+case $1 in
+ start|restart|force-reload)
+ log_action_msg "Recording successful boot for GRUB"
+ [ -s /boot/grub/grubenv ] || rm -f /boot/grub/grubenv
+ mkdir -p /boot/grub
+ grub-editenv /boot/grub/grubenv unset recordfail
+ log_end_msg $?
+ ;;
+ stop)
+ ;;
+ status)
+ exit 0
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|status|restart|force-reload}" >&2
+ exit 3
+ ;;
+esac
+
+exit 0
diff --git a/debian/grub-common.install.in b/debian/grub-common.install.in
new file mode 100644
index 0000000..420a61e
--- /dev/null
+++ b/debian/grub-common.install.in
@@ -0,0 +1,51 @@
+../../debian/apport/source_grub2.py usr/share/apport/package-hooks/
+../../debian/grub.d etc
+../../debian/init-select.cfg etc/default/grub.d
+
+etc/grub.d
+usr/bin/grub-editenv
+usr/bin/grub-file
+usr/bin/grub-fstest
+usr/bin/grub-glue-efi
+usr/bin/grub-kbdcomp
+usr/bin/grub-menulst2cfg
+usr/bin/grub-mkfont
+usr/bin/grub-mkimage
+usr/bin/grub-mklayout
+usr/bin/grub-mknetdir
+usr/bin/grub-mkpasswd-pbkdf2
+usr/bin/grub-mkrelpath
+usr/bin/grub-mkrescue
+usr/bin/grub-mkstandalone
+usr/bin/grub-render-label
+usr/bin/grub-script-check
+usr/bin/grub-syslinux2cfg
+usr/sbin/grub-macbless
+usr/sbin/grub-mkconfig
+usr/sbin/grub-mkdevicemap
+usr/sbin/grub-probe
+usr/share/grub/*.h
+usr/share/grub/*.pf2
+usr/share/grub/grub-mkconfig_lib
+usr/share/locale
+usr/share/man/man1/grub-editenv.1
+usr/share/man/man1/grub-file.1
+usr/share/man/man1/grub-fstest.1
+usr/share/man/man1/grub-glue-efi.1
+usr/share/man/man1/grub-kbdcomp.1
+usr/share/man/man1/grub-menulst2cfg.1
+usr/share/man/man1/grub-mkfont.1
+usr/share/man/man1/grub-mkimage.1
+usr/share/man/man1/grub-mklayout.1
+usr/share/man/man1/grub-mknetdir.1
+usr/share/man/man1/grub-mkpasswd-pbkdf2.1
+usr/share/man/man1/grub-mkrelpath.1
+usr/share/man/man1/grub-mkrescue.1
+usr/share/man/man1/grub-mkstandalone.1
+usr/share/man/man1/grub-render-label.1
+usr/share/man/man1/grub-script-check.1
+usr/share/man/man1/grub-syslinux2cfg.1
+usr/share/man/man8/grub-macbless.8
+usr/share/man/man8/grub-mkconfig.8
+usr/share/man/man8/grub-mkdevicemap.8
+usr/share/man/man8/grub-probe.8
diff --git a/debian/grub-common.install.kfreebsd.in b/debian/grub-common.install.kfreebsd.in
new file mode 100644
index 0000000..a1fc71c
--- /dev/null
+++ b/debian/grub-common.install.kfreebsd.in
@@ -0,0 +1,2 @@
+usr/bin/grub-mount
+usr/share/man/man1/grub-mount.1
diff --git a/debian/grub-common.install.linux.in b/debian/grub-common.install.linux.in
new file mode 100644
index 0000000..a1fc71c
--- /dev/null
+++ b/debian/grub-common.install.linux.in
@@ -0,0 +1,2 @@
+usr/bin/grub-mount
+usr/share/man/man1/grub-mount.1
diff --git a/debian/grub-common.install.sparc.in b/debian/grub-common.install.sparc.in
new file mode 100644
index 0000000..849845c
--- /dev/null
+++ b/debian/grub-common.install.sparc.in
@@ -0,0 +1,2 @@
+usr/sbin/grub-ofpathname
+usr/share/man/man8/grub-ofpathname.8
diff --git a/debian/grub-common.install.sparc64.in b/debian/grub-common.install.sparc64.in
new file mode 100644
index 0000000..849845c
--- /dev/null
+++ b/debian/grub-common.install.sparc64.in
@@ -0,0 +1,2 @@
+usr/sbin/grub-ofpathname
+usr/share/man/man8/grub-ofpathname.8
diff --git a/debian/grub-common.links b/debian/grub-common.links
new file mode 100644
index 0000000..ebc883d
--- /dev/null
+++ b/debian/grub-common.links
@@ -0,0 +1,10 @@
+usr/share/grub/grub-mkconfig_lib usr/lib/grub/grub-mkconfig_lib
+
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-editenv
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-mkconfig
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-mkfont
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-mkimage
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-mkpasswd-pbkdf2
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-mkrescue
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-probe
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-script-check
diff --git a/debian/grub-common.maintscript.hurd.in b/debian/grub-common.maintscript.hurd.in
new file mode 100644
index 0000000..39105f7
--- /dev/null
+++ b/debian/grub-common.maintscript.hurd.in
@@ -0,0 +1,3 @@
+# Removed in 1.96+20090307-1.
+rm_conffile /etc/grub.d/10_freebsd 2.00-14~
+rm_conffile /etc/grub.d/10_linux 2.00-14~
diff --git a/debian/grub-common.maintscript.in b/debian/grub-common.maintscript.in
new file mode 100644
index 0000000..54154e1
--- /dev/null
+++ b/debian/grub-common.maintscript.in
@@ -0,0 +1 @@
+rm_conffile /etc/bash_completion.d/grub 2.02+dfsg1-9~
diff --git a/debian/grub-common.maintscript.kfreebsd.in b/debian/grub-common.maintscript.kfreebsd.in
new file mode 100644
index 0000000..bfca9c8
--- /dev/null
+++ b/debian/grub-common.maintscript.kfreebsd.in
@@ -0,0 +1,3 @@
+# Removed in 1.96+20090307-1.
+rm_conffile /etc/grub.d/10_hurd 2.00-14~
+rm_conffile /etc/grub.d/10_linux 2.00-14~
diff --git a/debian/grub-common.maintscript.linux.in b/debian/grub-common.maintscript.linux.in
new file mode 100644
index 0000000..0fd762d
--- /dev/null
+++ b/debian/grub-common.maintscript.linux.in
@@ -0,0 +1,3 @@
+# Removed in 1.96+20090307-1.
+rm_conffile /etc/grub.d/10_freebsd 2.00-14~
+rm_conffile /etc/grub.d/10_hurd 2.00-14~
diff --git a/debian/grub-common.pm-sleep b/debian/grub-common.pm-sleep
new file mode 100644
index 0000000..eaedb04
--- /dev/null
+++ b/debian/grub-common.pm-sleep
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Tell grub that resume was successful
+
+case "$1" in
+ thaw)
+ [ -s /boot/grub/grubenv ] || rm -f /boot/grub/grubenv
+ mkdir -p /boot/grub
+ grub-editenv /boot/grub/grubenv unset recordfail
+ ;;
+esac
diff --git a/debian/grub-coreboot-bin.install.amd64.in b/debian/grub-coreboot-bin.install.amd64.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-coreboot-bin.install.amd64.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-coreboot-bin.install.kopensolaris-i386.in b/debian/grub-coreboot-bin.install.kopensolaris-i386.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-coreboot-bin.install.kopensolaris-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-coreboot-bin.install.linux-i386.in b/debian/grub-coreboot-bin.install.linux-i386.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-coreboot-bin.install.linux-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-efi-amd64-signed-template.lintian-overrides b/debian/grub-efi-amd64-signed-template.lintian-overrides
new file mode 100644
index 0000000..5a7a28d
--- /dev/null
+++ b/debian/grub-efi-amd64-signed-template.lintian-overrides
@@ -0,0 +1 @@
+grub-efi-amd64-signed-template: missing-dep-for-interpreter
diff --git a/debian/grub-efi-arm64-signed-template.lintian-overrides b/debian/grub-efi-arm64-signed-template.lintian-overrides
new file mode 100644
index 0000000..4125655
--- /dev/null
+++ b/debian/grub-efi-arm64-signed-template.lintian-overrides
@@ -0,0 +1 @@
+grub-efi-arm64-signed-template: missing-dep-for-interpreter
diff --git a/debian/grub-efi-ia32-signed-template.lintian-overrides b/debian/grub-efi-ia32-signed-template.lintian-overrides
new file mode 100644
index 0000000..c883651
--- /dev/null
+++ b/debian/grub-efi-ia32-signed-template.lintian-overrides
@@ -0,0 +1 @@
+grub-efi-ia32-signed-template: missing-dep-for-interpreter
diff --git a/debian/grub-emu-dbg.install.in b/debian/grub-emu-dbg.install.in
new file mode 100644
index 0000000..05719dc
--- /dev/null
+++ b/debian/grub-emu-dbg.install.in
@@ -0,0 +1,4 @@
+usr/lib/grub/*-*/*.exec
+usr/lib/grub/*-*/*.module
+usr/lib/grub/*-*/gdb_grub
+usr/lib/grub/*-*/gmodule.pl
diff --git a/debian/grub-emu.install.in b/debian/grub-emu.install.in
new file mode 100644
index 0000000..41ff95e
--- /dev/null
+++ b/debian/grub-emu.install.in
@@ -0,0 +1,8 @@
+usr/bin/grub-emu
+usr/bin/grub-emu-lite
+usr/lib/grub/*-*/*.img
+usr/lib/grub/*-*/*.lst
+usr/lib/grub/*-*/*.mod
+usr/lib/grub/*-*/config.h
+usr/lib/grub/*-*/modinfo.sh
+usr/share/man/man1/grub-emu.1
diff --git a/debian/grub-emu.install.kopensolaris-i386.in b/debian/grub-emu.install.kopensolaris-i386.in
new file mode 100644
index 0000000..ec0b148
--- /dev/null
+++ b/debian/grub-emu.install.kopensolaris-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/*-*/*.o
diff --git a/debian/grub-emu.install.linux-i386.in b/debian/grub-emu.install.linux-i386.in
new file mode 100644
index 0000000..ec0b148
--- /dev/null
+++ b/debian/grub-emu.install.linux-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/*-*/*.o
diff --git a/debian/grub-emu.maintscript.in b/debian/grub-emu.maintscript.in
new file mode 100644
index 0000000..57b6806
--- /dev/null
+++ b/debian/grub-emu.maintscript.in
@@ -0,0 +1 @@
+dir_to_symlink /usr/share/doc/@PACKAGE@ grub-common 2.00-2~
diff --git a/debian/grub-extras/915resolution/915resolution.c b/debian/grub-extras/915resolution/915resolution.c
new file mode 100644
index 0000000..0091a66
--- /dev/null
+++ b/debian/grub-extras/915resolution/915resolution.c
@@ -0,0 +1,1081 @@
+/* 915resolution - Utility to change vbemodes on the intel
+ * integrated video chipset */
+
+/*
+ * Based on Nathan Coulson's http://nathancoulson.com/proj/eee/grub-1.96-915resolution-0.5.2-3.patch
+ * Oct 10, 2008, Released as 915
+ * Oct 10, 2008, Updated to include support for 945GM thanks to Scot Doyle
+ */
+
+/* Copied from 915 resolution created by steve tomjenovic
+ * 915 resolution was in the public domain.
+ *
+ * All I have done, was make the above program run within
+ * the grub2 environment.
+ *
+ * Some of the checks are still commented, as I did not find
+ * easy replacement for memmem.
+ *
+ * Slightly edited by Nathan Coulson (conathan@gmail.com)
+ */
+
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007 Free Software Foundation, Inc.
+ * Copyright (C) 2003 NIIBE Yutaka <gniibe@m17n.org>
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+/* 915 resolution by steve tomljenovic
+ *
+ * This was tested only on Sony VGN-FS550. Use at your own risk
+ *
+ * This code is based on the techniques used in :
+ *
+ * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
+ * for demonstrating how to shadow the VBIOS into system RAM
+ * and then modify it.
+ *
+ * - 1280patch by Andrew Tipton (andrewtipton null li).
+ *
+ * - 855resolution by Alain Poirier
+ *
+ * This source code is into the public domain.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/i386/io.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define printf grub_printf
+#define malloc grub_malloc
+#define free grub_free
+#define strcmp grub_strcmp
+#define fprintf(stream, ...) grub_printf(__VA_ARGS__)
+#define strtol(x,y,z) grub_strtoul(x,y,z)
+#define atoi(x) grub_strtoul(x,NULL,10)
+#define assert(x)
+#define memset grub_memset
+#define outl grub_outl
+#define outb grub_outb
+#define inl grub_inl
+#define inb grub_inb
+
+#define NEW(a) ((a *)(malloc(sizeof(a))))
+#define FREE(a) (free(a))
+
+#define VBIOS_START 0xc0000
+#define VBIOS_SIZE 0x10000
+
+#define VBIOS_FILE "/dev/mem"
+
+#define FALSE 0
+#define TRUE 1
+
+#define MODE_TABLE_OFFSET_845G 617
+
+#define RES915_VERSION "0.5.3"
+
+#define ATI_SIGNATURE1 "ATI MOBILITY RADEON"
+#define ATI_SIGNATURE2 "ATI Technologies Inc"
+#define NVIDIA_SIGNATURE "NVIDIA Corp"
+#define INTEL_SIGNATURE "Intel Corp"
+
+#define DEBUG 0
+
+typedef unsigned char * address;
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned char boolean;
+typedef unsigned int cardinal;
+
+typedef enum {
+ CT_UNKWN, CT_830, CT_845G, CT_855GM, CT_865G, CT_915G, CT_915GM, CT_945G, CT_945GM, CT_945GME,
+ CT_946GZ, CT_G965, CT_Q965, CT_965GM, CT_G33, CT_Q33, CT_Q35, CT_500GMA,
+ CT_GM45, CT_GMA3150, CT_HD3000
+} chipset_type;
+
+const char *const chipset_type_names[] = {
+ "UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME",
+ "946GZ", "G965", "Q965", "965GM", "G33", "Q33", "Q35", "500GMA",
+ "GM45", "GMA3150", "HD3000"
+};
+
+typedef enum {
+ BT_UNKWN, BT_1, BT_2, BT_3
+} bios_type;
+
+const char *const bios_type_names[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};
+
+int freqs[] = { 60, 75, 85 };
+
+typedef struct {
+ byte mode;
+ byte bits_per_pixel;
+ word resolution;
+ byte unknown;
+} __attribute__((packed)) vbios_mode;
+
+typedef struct {
+ byte unknow1[2];
+ byte x1;
+ byte x_total;
+ byte x2;
+ byte y1;
+ byte y_total;
+ byte y2;
+} __attribute__((packed)) vbios_resolution_type1;
+
+typedef struct {
+ unsigned long clock;
+
+ word x1;
+ word htotal;
+ word x2;
+ word hblank;
+ word hsyncstart;
+ word hsyncend;
+
+ word y1;
+ word vtotal;
+ word y2;
+ word vblank;
+ word vsyncstart;
+ word vsyncend;
+} __attribute__((packed)) vbios_modeline_type2;
+
+typedef struct {
+ byte xchars;
+ byte ychars;
+ byte unknown[4];
+
+ vbios_modeline_type2 modelines[];
+} __attribute__((packed)) vbios_resolution_type2;
+
+typedef struct {
+ unsigned long clock;
+
+ word x1;
+ word htotal;
+ word x2;
+ word hblank;
+ word hsyncstart;
+ word hsyncend;
+
+ word y1;
+ word vtotal;
+ word y2;
+ word vblank;
+ word vsyncstart;
+ word vsyncend;
+
+ word timing_h;
+ word timing_v;
+
+ byte unknown[6];
+} __attribute__((packed)) vbios_modeline_type3;
+
+typedef struct {
+ unsigned char unknown[6];
+
+ vbios_modeline_type3 modelines[];
+} __attribute__((packed)) vbios_resolution_type3;
+
+
+typedef struct {
+ cardinal chipset_id;
+ chipset_type chipset;
+ bios_type bios;
+
+ int bios_fd;
+ address bios_ptr;
+
+ vbios_mode * mode_table;
+ cardinal mode_table_size;
+
+ byte b1, b2;
+
+ boolean unlocked;
+} vbios_map;
+
+
+static cardinal get_chipset_id(void) {
+ outl(0x80000000, 0xcf8);
+ return inl(0xcfc);
+}
+
+static chipset_type get_chipset(cardinal id) {
+ chipset_type type;
+
+ switch (id) {
+ case 0x35758086:
+ type = CT_830;
+ break;
+
+ case 0x25608086:
+ type = CT_845G;
+ break;
+
+ case 0x35808086:
+ type = CT_855GM;
+ break;
+
+ case 0x25708086:
+ type = CT_865G;
+ break;
+
+ case 0x25808086:
+ type = CT_915G;
+ break;
+
+ case 0x25908086:
+ type = CT_915GM;
+ break;
+
+ case 0x27708086:
+ type = CT_945G;
+ break;
+
+ case 0x27a08086:
+ type = CT_945GM;
+ break;
+
+ case 0x27ac8086:
+ type = CT_945GME;
+ break;
+
+ case 0x29708086:
+ type = CT_946GZ;
+ break;
+
+ case 0x29a08086:
+ type = CT_G965;
+ break;
+
+ case 0x29908086:
+ type = CT_Q965;
+ break;
+
+ case 0x2a008086:
+ type = CT_965GM;
+ break;
+
+ case 0x29c08086:
+ type = CT_G33;
+ break;
+
+ case 0x29b08086:
+ type = CT_Q35;
+ break;
+
+ case 0x29d08086:
+ type = CT_Q33;
+ break;
+
+ case 0x81008086:
+ type = CT_500GMA;
+ break;
+
+ case 0xa0008086:
+ type = CT_GMA3150;
+ break;
+
+ case 0xa0108086:
+ type = CT_GMA3150;
+ break;
+
+ case 0x01048086:
+ type = CT_HD3000;
+ break;
+
+ case 0x2a408086:
+ type = CT_GM45;
+ break;
+
+ case 0x2a018086:
+ type = CT_965GM;
+ break;
+
+ case 0x2a028086:
+ type = CT_965GM;
+ break;
+
+ default:
+ type = CT_UNKWN;
+ break;
+ }
+
+ return type;
+}
+
+
+static vbios_resolution_type1 * map_type1_resolution(vbios_map * map, word res) {
+ vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res));
+ return ptr;
+}
+
+static vbios_resolution_type2 * map_type2_resolution(vbios_map * map, word res) {
+ vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res));
+ return ptr;
+}
+
+static vbios_resolution_type3 * map_type3_resolution(vbios_map * map, word res) {
+ vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res));
+ return ptr;
+}
+
+
+static boolean detect_bios_type(vbios_map * map, int entry_size) {
+ unsigned i;
+ short int r1, r2;
+
+ r1 = r2 = 32000;
+
+ for (i=0; i < map->mode_table_size; i++) {
+ if (map->mode_table[i].resolution <= r1) {
+ r1 = map->mode_table[i].resolution;
+ }
+ else {
+ if (map->mode_table[i].resolution <= r2) {
+ r2 = map->mode_table[i].resolution;
+ }
+ }
+
+ /*printf("r1 = %d r2 = %d\n", r1, r2);*/
+ }
+
+ return (r2-r1-6) % entry_size == 0;
+}
+
+
+static void close_vbios(vbios_map * map);
+
+
+static vbios_map * open_vbios(chipset_type forced_chipset) {
+ vbios_map * map = NEW(vbios_map);
+ memset (map, 0, sizeof(vbios_map));
+
+ /*
+ * Determine chipset
+ */
+
+ if (forced_chipset == CT_UNKWN) {
+ map->chipset_id = get_chipset_id();
+
+ map->chipset = get_chipset(map->chipset_id);
+ }
+ else if (forced_chipset != CT_UNKWN) {
+ map->chipset = forced_chipset;
+ }
+ else {
+ map->chipset = CT_915GM;
+ }
+
+ /*
+ * Map the video bios to memory
+ */
+
+ map->bios_ptr = (unsigned char *) VBIOS_START;
+
+#if 0
+ /*
+ * check if we have ATI Radeon
+ */
+
+ if (memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE1, strlen(ATI_SIGNATURE1)) ||
+ memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE2, strlen(ATI_SIGNATURE2)) ) {
+ fprintf(stderr, "ATI chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\n");
+ close(map->bios_fd);
+ exit(2);
+ }
+
+ /*
+ * check if we have NVIDIA
+ */
+
+ if (memmem(map->bios_ptr, VBIOS_SIZE, NVIDIA_SIGNATURE, strlen(NVIDIA_SIGNATURE))) {
+ fprintf(stderr, "NVIDIA chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\n");
+ close(map->bios_fd);
+ exit(2);
+ }
+
+ /*
+ * check if we have Intel
+ */
+
+ if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) {
+ fprintf(stderr, "Intel chipset detected. However, 915resolution was unable to determine the chipset type.\n");
+
+ fprintf(stderr, "Chipset Id: %x\n", map->chipset_id);
+
+ fprintf(stderr, "Please report this problem to stomljen@yahoo.com\n");
+
+ close_vbios(map);
+ exit(2);
+ }
+#endif
+
+ /*
+ * check for others
+ */
+
+ if (map->chipset == CT_UNKWN) {
+ fprintf(stderr, "Unknown chipset type and unrecognized bios.\n");
+ fprintf(stderr, "915resolution only works with Intel 800/900 series graphic chipsets.\n");
+
+ fprintf(stderr, "Chipset Id: %x\n", map->chipset_id);
+ close_vbios(map);
+ return 0;
+ }
+
+ /*
+ * Figure out where the mode table is
+ */
+
+ {
+ address p = map->bios_ptr + 16;
+ address limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));
+
+ while (p < limit && map->mode_table == 0) {
+ vbios_mode * mode_ptr = (vbios_mode *) p;
+
+ if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&
+ ((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {
+
+ map->mode_table = mode_ptr;
+ }
+
+ p++;
+ }
+
+ if (map->mode_table == 0) {
+ fprintf(stderr, "Unable to locate the mode table.\n");
+ fprintf(stderr, "Please run the program 'dump_bios' as root and\n");
+ fprintf(stderr, "email the file 'vbios.dmp' to stomljen@yahoo.com.\n");
+
+ fprintf(stderr, "Chipset: %s\n", chipset_type_names[map->chipset]);
+ close_vbios(map);
+ return 0;
+ }
+ }
+
+ /*
+ * Determine size of mode table
+ */
+
+ {
+ vbios_mode * mode_ptr = map->mode_table;
+
+ while (mode_ptr->mode != 0xff) {
+ map->mode_table_size++;
+ mode_ptr++;
+ }
+ }
+
+ /*
+ * Figure out what type of bios we have
+ * order of detection is important
+ */
+
+ if (detect_bios_type(map, sizeof(vbios_modeline_type3))) {
+ map->bios = BT_3;
+ }
+ else if (detect_bios_type(map, sizeof(vbios_modeline_type2))) {
+ map->bios = BT_2;
+ }
+ else if (detect_bios_type(map, sizeof(vbios_resolution_type1))) {
+ map->bios = BT_1;
+ }
+ else {
+ fprintf(stderr, "Unable to determine bios type.\n");
+ fprintf(stderr, "Please run the program 'dump_bios' as root and\n");
+ fprintf(stderr, "email the file 'vbios.dmp' to stomljen@yahoo.com.\n");
+
+ fprintf(stderr, "Chipset: %s\n", chipset_type_names[map->chipset]);
+ fprintf(stderr, "Mode Table Offset: $C0000 + $%x\n", ((cardinal)map->mode_table) - ((cardinal)map->bios_ptr));
+ fprintf(stderr, "Mode Table Entries: %u\n", map->mode_table_size);
+ return 0;
+ }
+
+ return map;
+}
+
+static void close_vbios(vbios_map * map) {
+ assert(!map->unlocked);
+
+ FREE(map);
+}
+
+static void unlock_vbios(vbios_map * map) {
+
+ assert(!map->unlocked);
+
+ map->unlocked = TRUE;
+
+ switch (map->chipset) {
+ case CT_UNKWN:
+ break;
+ case CT_830:
+ case CT_855GM:
+ outl(0x8000005a, 0xcf8);
+ map->b1 = inb(0xcfe);
+
+ outl(0x8000005a, 0xcf8);
+ outb(0x33, 0xcfe);
+ break;
+ case CT_845G:
+ case CT_865G:
+ case CT_915G:
+ case CT_915GM:
+ case CT_945G:
+ case CT_945GM:
+ case CT_945GME:
+ case CT_946GZ:
+ case CT_G965:
+ case CT_Q965:
+ case CT_965GM:
+ case CT_G33:
+ case CT_Q35:
+ case CT_Q33:
+ case CT_500GMA:
+ case CT_GM45:
+ case CT_GMA3150:
+ case CT_HD3000:
+ outl(0x80000090, 0xcf8);
+ map->b1 = inb(0xcfd);
+ map->b2 = inb(0xcfe);
+
+ outl(0x80000090, 0xcf8);
+ outb(0x33, 0xcfd);
+ outb(0x33, 0xcfe);
+ break;
+ }
+
+#if DEBUG
+ {
+ cardinal t = inl(0xcfc);
+ printf("unlock PAM: (0x%08x)\n", t);
+ }
+#endif
+}
+
+static void relock_vbios(vbios_map * map) {
+
+ assert(map->unlocked);
+ map->unlocked = FALSE;
+
+ switch (map->chipset) {
+ case CT_UNKWN:
+ break;
+ case CT_830:
+ case CT_855GM:
+ outl(0x8000005a, 0xcf8);
+ outb(map->b1, 0xcfe);
+ break;
+ case CT_845G:
+ case CT_865G:
+ case CT_915G:
+ case CT_915GM:
+ case CT_945G:
+ case CT_945GM:
+ case CT_945GME:
+ case CT_946GZ:
+ case CT_G965:
+ case CT_Q965:
+ case CT_965GM:
+ case CT_G33:
+ case CT_Q35:
+ case CT_Q33:
+ case CT_500GMA:
+ case CT_GM45:
+ case CT_GMA3150:
+ case CT_HD3000:
+ outl(0x80000090, 0xcf8);
+ outb(map->b1, 0xcfd);
+ outb(map->b2, 0xcfe);
+ break;
+ }
+
+#if DEBUG
+ {
+ cardinal t = inl(0xcfc);
+ printf("relock PAM: (0x%08x)\n", t);
+ }
+#endif
+}
+
+
+static void list_modes(vbios_map *map, cardinal raw) {
+ cardinal i, x, y;
+
+ for (i=0; i < map->mode_table_size; i++) {
+ switch(map->bios) {
+ case BT_1:
+ {
+ vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
+
+ x = ((((cardinal) res->x2) & 0xf0) << 4) | res->x1;
+ y = ((((cardinal) res->y2) & 0xf0) << 4) | res->y1;
+
+ if (x != 0 && y != 0) {
+ printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
+ }
+
+ if (raw)
+ {
+ printf("Mode %02x (raw) :\n\t%02x %02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n", map->mode_table[i].mode, res->unknow1[0],res->unknow1[1], res->x1,res->x_total,res->x2,res->y1,res->y_total,res->y2);
+ }
+
+ }
+ break;
+ case BT_2:
+ {
+ vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
+
+ x = res->modelines[0].x1+1;
+ y = res->modelines[0].y1+1;
+
+ if (x != 0 && y != 0) {
+ printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
+ }
+ }
+ break;
+ case BT_3:
+ {
+ vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
+
+ x = res->modelines[0].x1+1;
+ y = res->modelines[0].y1+1;
+
+ if (x != 0 && y != 0) {
+ printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
+ }
+ }
+ break;
+ case BT_UNKWN:
+ break;
+ }
+ }
+}
+
+static void gtf_timings(int x, int y, int freq,
+ unsigned long *clock,
+ word *hsyncstart, word *hsyncend, word *hblank,
+ word *vsyncstart, word *vsyncend, word *vblank)
+{
+ int hbl, vbl, vfreq;
+
+ /*
+ (y+1)/(20000.0/(11*freq) - 1) + 0.5
+ = ((y+1) * (11*freq))/(20000.0 - (11*freq)) + 0.5
+ = ((y+1) * (11*freq) + 10000.0 - (11*freq) / 2)/(20000.0 - (11*freq))
+ = ((y+1) * (11*freq) + 10000.0 - 5 * freq - (freq + 1) / 2)/(20000.0 - (11*freq))
+*/
+ vbl = y + 1 +
+ grub_divmod64 (((y+1) * (11*(long long)freq) + 10000 - 5 * (long long)freq
+ - (freq + 1) / 2),
+ (20000 - (11*(long long)freq)), 0);
+ vfreq = vbl * freq;
+ /*
+ (x * (30.0 - 300000.0 / vfreq) /
+ (70.0 + 300000.0 / vfreq) / 16.0 + 0.5)
+ = ((x * (30.0 - 300000.0 / vfreq) /
+ (70.0 + 300000.0 / vfreq) + 8) / 16)
+ = ((x * (30.0 * vfreq - 300000.0) /
+ (70.0 * vfreq + 300000.0) + 8) / 16)
+ = (((x * (30 * vfreq - 300000)) /
+ (70 * vfreq + 300000) + 8) / 16)
+ */
+ hbl = 16 * (int)((grub_divmod64((x * (30 * (long long)vfreq - 300000)),
+ (70 * (long long)vfreq + 300000), 0)
+ + 8) / 16);
+
+ *vsyncstart = y;
+ *vsyncend = y + 3;
+ *vblank = vbl - 1;
+ *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;
+ *hsyncend = x + hbl / 2 - 1;
+ *hblank = x + hbl - 1;
+ *clock = (x + hbl) * vfreq / 1000;
+}
+
+static void set_mode(vbios_map * map, cardinal mode, cardinal x, cardinal y, cardinal bp, cardinal htotal, cardinal vtotal) {
+ int xprev, yprev;
+ cardinal i, j;
+
+ for (i=0; i < map->mode_table_size; i++) {
+ if (map->mode_table[i].mode == mode) {
+ switch(map->bios) {
+ case BT_1:
+ {
+ vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
+
+ if (bp) {
+ map->mode_table[i].bits_per_pixel = bp;
+ }
+
+ res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0);
+ res->x1 = (x & 0xff);
+
+ res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0);
+ res->y1 = (y & 0xff);
+ if (htotal)
+ res->x_total = ((htotal-x) & 0xff);
+
+ if (vtotal)
+ res->y_total = ((vtotal-y) & 0xff);
+ }
+ break;
+ case BT_2:
+ {
+ vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
+
+ res->xchars = x / 8;
+ res->ychars = y / 16 - 1;
+ xprev = res->modelines[0].x1;
+ yprev = res->modelines[0].y1;
+
+ for(j=0; j < 3; j++) {
+ vbios_modeline_type2 * modeline = &res->modelines[j];
+
+ if (modeline->x1 == xprev && modeline->y1 == yprev) {
+ unsigned long clock;
+ word hsyncstart, hsyncend, hblank;
+ word vsyncstart, vsyncend, vblank;
+
+ modeline->x1 = modeline->x2 = x-1;
+ modeline->y1 = modeline->y2 = y-1;
+
+ gtf_timings(x, y, freqs[j], &clock,
+ &hsyncstart, &hsyncend, &hblank,
+ &vsyncstart, &vsyncend, &vblank);
+ modeline->clock = clock;
+ modeline->hsyncstart = hsyncstart;
+ modeline->hsyncend = hsyncend;
+ modeline->hblank = hblank;
+ modeline->vsyncstart = vsyncstart;
+ modeline->vsyncend = vsyncend;
+ modeline->vblank = vblank;
+
+ if (htotal)
+ modeline->htotal = htotal;
+ else
+ modeline->htotal = modeline->hblank;
+
+ if (vtotal)
+ modeline->vtotal = vtotal;
+ else
+ modeline->vtotal = modeline->vblank;
+ }
+ }
+ }
+ break;
+ case BT_3:
+ {
+ vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
+
+ xprev = res->modelines[0].x1;
+ yprev = res->modelines[0].y1;
+
+ for (j=0; j < 3; j++) {
+ vbios_modeline_type3 * modeline = &res->modelines[j];
+
+ if (modeline->x1 == xprev && modeline->y1 == yprev) {
+ unsigned long clock;
+ word hsyncstart, hsyncend, hblank;
+ word vsyncstart, vsyncend, vblank;
+
+ modeline->x1 = modeline->x2 = x-1;
+ modeline->y1 = modeline->y2 = y-1;
+
+ gtf_timings(x, y, freqs[j], &clock,
+ &hsyncstart, &hsyncend, &hblank,
+ &vsyncstart, &vsyncend, &vblank);
+ modeline->clock = clock;
+ modeline->hsyncstart = hsyncstart;
+ modeline->hsyncend = hsyncend;
+ modeline->hblank = hblank;
+ modeline->vsyncstart = vsyncstart;
+ modeline->vsyncend = vsyncend;
+ modeline->vblank = vblank;
+
+ if (htotal)
+ modeline->htotal = htotal;
+ else
+ modeline->htotal = modeline->hblank;
+ if (vtotal)
+ modeline->vtotal = vtotal;
+ else
+ modeline->vtotal = modeline->vblank;
+
+ modeline->timing_h = y-1;
+ modeline->timing_v = x-1;
+ }
+ }
+ }
+ break;
+ case BT_UNKWN:
+ break;
+ }
+ }
+ }
+}
+
+static void display_map_info(vbios_map * map) {
+ printf("Chipset: %s\n", chipset_type_names[map->chipset]);
+ printf("BIOS: %s\n", bios_type_names[map->bios]);
+
+ printf("Mode Table Offset: $C0000 + $%x\n", ((cardinal)map->mode_table) - ((cardinal)map->bios_ptr));
+ printf("Mode Table Entries: %u\n", map->mode_table_size);
+}
+
+
+static int parse_args(cardinal argc, char *argv[], chipset_type *forced_chipset,
+ cardinal *list, cardinal *mode, cardinal *x, cardinal *y,
+ cardinal *bp, cardinal *raw, cardinal *htotal,
+ cardinal *vtotal, cardinal *quiet) {
+ cardinal index = 0;
+
+ *list = *mode = *x = *y = *raw = *htotal = *vtotal = 0;
+ *bp = 0;
+ *quiet = 0;
+
+ *forced_chipset = CT_UNKWN;
+
+ if ((argc > index) && !strcmp(argv[index], "-q")) {
+ *quiet = 1;
+ index++;
+
+ if(argc<=index) {
+ return 0;
+ }
+ }
+
+ if ((argc > index) && !strcmp(argv[index], "-c")) {
+ index++;
+
+ if(argc<=index) {
+ return 0;
+ }
+
+ if (!strcmp(argv[index], "845")) {
+ *forced_chipset = CT_845G;
+ }
+ else if (!strcmp(argv[index], "855")) {
+ *forced_chipset = CT_855GM;
+ }
+ else if (!strcmp(argv[index], "865")) {
+ *forced_chipset = CT_865G;
+ }
+ else if (!strcmp(argv[index], "915G")) {
+ *forced_chipset = CT_915G;
+ }
+ else if (!strcmp(argv[index], "915GM")) {
+ *forced_chipset = CT_915GM;
+ }
+ else if (!strcmp(argv[index], "945G")) {
+ *forced_chipset = CT_945G;
+ }
+ else if (!strcmp(argv[index], "945GM")) {
+ *forced_chipset = CT_945GM;
+ }
+ else if (!strcmp(argv[index], "945GME")) {
+ *forced_chipset = CT_945GME;
+ }
+ else if (!strcmp(argv[index], "946GZ")) {
+ *forced_chipset = CT_946GZ;
+ }
+ else if (!strcmp(argv[index], "G965")) {
+ *forced_chipset = CT_G965;
+ }
+ else if (!strcmp(argv[index], "Q965")) {
+ *forced_chipset = CT_Q965;
+ }
+ else if (!strcmp(argv[index], "965GM")) {
+ *forced_chipset = CT_965GM;
+ }
+ else if (!strcmp(argv[index], "G33")) {
+ *forced_chipset = CT_G33;
+ }
+ else if (!strcmp(argv[index], "Q35")) {
+ *forced_chipset = CT_Q35;
+ }
+ else if (!strcmp(argv[index], "Q33")) {
+ *forced_chipset = CT_Q33;
+ }
+ else if (!strcmp(argv[index], "500GMA")) {
+ *forced_chipset = CT_500GMA;
+ }
+ else if (!strcmp(argv[index], "GM45")) {
+ *forced_chipset = CT_GM45;
+ }
+ else if (!strcmp(argv[index], "GMA3150")) {
+ *forced_chipset = CT_GMA3150;
+ }
+ else if (!strcmp(argv[index], "HD3000")) {
+ *forced_chipset = CT_HD3000;
+ }
+ else {
+ *forced_chipset = CT_UNKWN;
+ }
+
+ index++;
+
+ if (argc<=index) {
+ return 0;
+ }
+ }
+
+ if ((argc > index) && !strcmp(argv[index], "-l")) {
+ *list = 1;
+ index++;
+
+ if(argc<=index) {
+ return 0;
+ }
+ }
+
+ if ((argc > index) && !strcmp(argv[index], "-r")) {
+ *raw = 1;
+ index++;
+
+ if(argc<=index) {
+ return 0;
+ }
+ }
+
+ if (argc-index < 3 || argc-index > 6) {
+ return -1;
+ }
+
+ *mode = (cardinal) strtol(argv[index], NULL, 16);
+ *x = (cardinal)atoi(argv[index+1]);
+ *y = (cardinal)atoi(argv[index+2]);
+
+
+ if (argc-index > 3) {
+ *bp = (cardinal)atoi(argv[index+3]);
+ }
+ else {
+ *bp = 0;
+ }
+
+ if (argc-index > 4) {
+ *htotal = (cardinal)atoi(argv[index+4]);
+ }
+ else {
+ *htotal = 0;
+ }
+
+ if (argc-index > 5) {
+ *vtotal = (cardinal)atoi(argv[index+5]);
+ }
+ else {
+ *vtotal = 0;
+ }
+
+ return 0;
+}
+
+static void usage(void) {
+ printf("Usage: 915resolution [-q] [-c chipset] [-l] [mode X Y] [bits/pixel] [htotal] [vtotal]\n");
+ printf(" Set the resolution to XxY for a video mode\n");
+ printf(" Bits per pixel are optional. htotal/vtotal settings are additionally optional.\n");
+ printf(" Options:\n");
+ printf(" -q don't show any normal messages\n");
+ printf(" -c force chipset type (THIS IS USED FOR DEBUG PURPOSES)\n");
+ printf(" -l display the modes found in the video BIOS\n");
+ printf(" -r display the modes found in the video BIOS in raw mode (THIS IS USED FOR DEBUG PURPOSES)\n");
+}
+
+static int main_915 (int argc, char *argv[])
+{
+ vbios_map * map;
+ cardinal list, mode, x, y, bp, raw, htotal, vtotal;
+ cardinal quiet;
+ chipset_type forced_chipset;
+
+ if (parse_args(argc, argv, &forced_chipset, &list, &mode,
+ &x, &y, &bp, &raw, &htotal, &vtotal, &quiet) == -1) {
+ printf("Intel 800/900 Series VBIOS Hack : version %s\n\n",
+ RES915_VERSION);
+ usage();
+ return 2;
+ }
+
+ if (!quiet)
+ printf("Intel 800/900 Series VBIOS Hack : version %s\n\n",
+ RES915_VERSION);
+
+ map = open_vbios(forced_chipset);
+ if (!quiet)
+ {
+ display_map_info(map);
+ printf("\n");
+ }
+
+ if (list) {
+ list_modes(map, raw);
+ }
+
+ if (mode!=0 && x!=0 && y!=0) {
+ unlock_vbios(map);
+
+ set_mode(map, mode, x, y, bp, htotal, vtotal);
+
+ relock_vbios(map);
+
+ printf("Patch mode %02x to resolution %dx%d complete\n", mode, x, y);
+
+ if (list) {
+ list_modes(map, raw);
+ }
+ }
+
+ close_vbios(map);
+
+ return 0;
+}
+
+
+
+
+
+static grub_err_t
+grub_cmd_915resolution (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ return main_915 (argc, argv);
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(915resolution)
+{
+ cmd = grub_register_command ("915resolution", grub_cmd_915resolution,
+ "915resolution", "Intel VBE editor");
+}
+
+GRUB_MOD_FINI(915resolution)
+{
+ grub_unregister_command (cmd);
+}
diff --git a/debian/grub-extras/915resolution/COPYING b/debian/grub-extras/915resolution/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/debian/grub-extras/915resolution/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/debian/grub-extras/915resolution/Makefile.core.def b/debian/grub-extras/915resolution/Makefile.core.def
new file mode 100644
index 0000000..14c0ae5
--- /dev/null
+++ b/debian/grub-extras/915resolution/Makefile.core.def
@@ -0,0 +1,7 @@
+AutoGen definitions Makefile.tpl;
+
+module = {
+ name = '915resolution';
+ i386_pc = contrib/915resolution/915resolution.c;
+ enable = i386_pc;
+};
diff --git a/debian/grub-extras/915resolution/README b/debian/grub-extras/915resolution/README
new file mode 100644
index 0000000..874bd08
--- /dev/null
+++ b/debian/grub-extras/915resolution/README
@@ -0,0 +1,11 @@
+
+grub-extras is meant to be used as an overlay on grub2 source tree.
+
+Build instructions:
+
+ - Copy grub-extras in a subdirectory of your grub2 checkout.
+ For example, "grub-extras".
+
+ - Export GRUB_CONTRIB environment variable to point to this directory.
+
+ - Build GRUB as usual.
diff --git a/debian/grub-extras/disabled/gpxe/Makefile.common b/debian/grub-extras/disabled/gpxe/Makefile.common
new file mode 100644
index 0000000..b7a109a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/Makefile.common
@@ -0,0 +1,2 @@
+GPXE_CPPFLAGS = '-DFILE_LICENCE(x)=' -I$(srcdir)/contrib/gpxe/src/include -I$(srcdir)/contrib/gpxe/include_wrap
+GPXE_CFLAGS = -Wno-pointer-arith -Wno-error
diff --git a/debian/grub-extras/disabled/gpxe/Makefile.core.def b/debian/grub-extras/disabled/gpxe/Makefile.core.def
new file mode 100644
index 0000000..a9350ab
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/Makefile.core.def
@@ -0,0 +1,434 @@
+AutoGen definitions Makefile.tpl;
+
+module = {
+ name = gpxe;
+ common = contrib/gpxe/wrap/wrap.c;
+ common = contrib/gpxe/wrap/pci.c;
+ common = contrib/gpxe/wrap/nic.c;
+ common = contrib/gpxe/src/net/80211/net80211.c;
+ common = contrib/gpxe/src/net/80211/rc80211.c;
+ common = contrib/gpxe/src/net/arp.c;
+ common = contrib/gpxe/src/net/dhcpopts.c;
+ common = contrib/gpxe/src/net/dhcppkt.c;
+ common = contrib/gpxe/src/net/ethernet.c;
+ common = contrib/gpxe/src/net/fakedhcp.c;
+ common = contrib/gpxe/src/net/icmp.c;
+ common = contrib/gpxe/src/net/iobpad.c;
+ common = contrib/gpxe/src/net/ipv4.c;
+ common = contrib/gpxe/src/net/netdevice.c;
+ common = contrib/gpxe/src/net/netdev_settings.c;
+ common = contrib/gpxe/src/net/nullnet.c;
+ common = contrib/gpxe/src/net/rarp.c;
+ common = contrib/gpxe/src/net/retry.c;
+ common = contrib/gpxe/src/net/tcp/http.c;
+ common = contrib/gpxe/src/net/tcp.c;
+ common = contrib/gpxe/src/net/tcpip.c;
+ common = contrib/gpxe/src/net/udp/dhcp.c;
+ common = contrib/gpxe/src/net/udp/dns.c;
+ common = contrib/gpxe/src/net/udp/slam.c;
+ common = contrib/gpxe/src/net/udp/tftp.c;
+ common = contrib/gpxe/src/net/udp.c;
+ common = contrib/gpxe/src/core/base64.c;
+ common = contrib/gpxe/src/core/nvo.c;
+ common = contrib/gpxe/src/core/uri.c;
+ common = contrib/gpxe/src/core/uuid.c;
+ common = contrib/gpxe/src/core/random.c;
+ common = contrib/gpxe/src/core/open.c;
+ common = contrib/gpxe/src/core/cwuri.c;
+ common = contrib/gpxe/src/core/linebuf.c;
+ common = contrib/gpxe/src/core/xfer.c;
+ common = contrib/gpxe/src/core/settings.c;
+ common = contrib/gpxe/src/core/iobuf.c;
+ common = contrib/gpxe/src/core/refcnt.c;
+ common = contrib/gpxe/src/core/bitmap.c;
+ common = contrib/gpxe/src/core/process.c;
+ common = contrib/gpxe/src/core/job.c;
+ common = contrib/gpxe/src/core/resolv.c;
+ common = contrib/gpxe/src/core/interface.c;
+ common = contrib/gpxe/src/core/basename.c;
+ common = contrib/gpxe/src/core/misc.c;
+ common = contrib/gpxe/src/hci/strerror.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_infiniband;
+ common = contrib/gpxe/src/net/infiniband/ib_cm.c;
+ common = contrib/gpxe/src/net/infiniband/ib_cmrc.c;
+ common = contrib/gpxe/src/net/infiniband/ib_mcast.c;
+ common = contrib/gpxe/src/net/infiniband/ib_mi.c;
+ common = contrib/gpxe/src/net/infiniband/ib_packet.c;
+ common = contrib/gpxe/src/net/infiniband/ib_pathrec.c;
+ common = contrib/gpxe/src/net/infiniband/ib_sma.c;
+ common = contrib/gpxe/src/net/infiniband/ib_smc.c;
+ common = contrib/gpxe/src/net/infiniband/ib_srp.c;
+ common = contrib/gpxe/src/net/infiniband.c;
+ common = contrib/gpxe/src/drivers/net/ipoib.c;
+ common = contrib/gpxe/src/drivers/block/scsi.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_3c529;
+ common = contrib/gpxe/src/drivers/net/3c529.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_3c595;
+ common = contrib/gpxe/src/drivers/net/3c595.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_3c5x9;
+ common = contrib/gpxe/src/drivers/net/3c5x9.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_3c90x;
+ common = contrib/gpxe/src/drivers/net/3c90x.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_davicom;
+ common = contrib/gpxe/src/drivers/net/davicom.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+#if 0
+/* Not fixed for relocation yet. */
+module = {
+ name = gpxe_depca;
+ common = contrib/gpxe/src/drivers/net/depca.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+#endif
+
+module = {
+ name = gpxe_dmfe;
+ common = contrib/gpxe/src/drivers/net/dmfe.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_eepro100;
+ common = contrib/gpxe/src/drivers/net/eepro100.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_eepro;
+ common = contrib/gpxe/src/drivers/net/eepro.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_epic100;
+ common = contrib/gpxe/src/drivers/net/epic100.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_ipoib;
+ common = contrib/gpxe/src/drivers/net/ipoib.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_legacy;
+ common = contrib/gpxe/src/drivers/net/legacy.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_natsemi;
+ common = contrib/gpxe/src/drivers/net/natsemi.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_ne2k_isa;
+ common = contrib/gpxe/src/drivers/net/ne2k_isa.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_ns83820;
+ common = contrib/gpxe/src/drivers/net/ns83820.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_ns8390;
+ common = contrib/gpxe/src/drivers/net/ns8390.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_pnic;
+ common = contrib/gpxe/src/drivers/net/pnic.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_rtl8139;
+ common = contrib/gpxe/src/drivers/net/rtl8139.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_sis900;
+ common = contrib/gpxe/src/drivers/net/sis900.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_smc9000;
+ common = contrib/gpxe/src/drivers/net/smc9000.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_tulip;
+ common = contrib/gpxe/src/drivers/net/tulip.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_w89c840;
+ common = contrib/gpxe/src/drivers/net/w89c840.c;
+ /* Fails to preprocess without -Os! */
+ cppflags = '$(GPXE_CPPFLAGS) -Os';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_nvs;
+ common = contrib/gpxe/src/drivers/nvs/nvs.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_spi;
+ common = contrib/gpxe/src/drivers/nvs/spi.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_threewire;
+ common = contrib/gpxe/src/drivers/nvs/threewire.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_bitbash;
+ common = contrib/gpxe/src/drivers/bitbash/bitbash.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_i2c_bit;
+ common = contrib/gpxe/src/drivers/bitbash/i2c_bit.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_spi_bit;
+ common = contrib/gpxe/src/drivers/bitbash/spi_bit.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+#if 0
+
+/* Following ones require MII support which is GPLv2. */
+
+module = {
+ name = gpxe_amd8111e;
+ common = contrib/gpxe/src/drivers/net/amd8111e.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_atl1e;
+ common = contrib/gpxe/src/drivers/net/atl1e.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_b44;
+ common = contrib/gpxe/src/drivers/net/b44.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_bnx2;
+ common = contrib/gpxe/src/drivers/net/bnx2.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_etherfabric;
+ common = contrib/gpxe/src/drivers/net/etherfabric.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_forcedeth;
+ common = contrib/gpxe/src/drivers/net/forcedeth.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_pcnet32;
+ common = contrib/gpxe/src/drivers/net/pcnet32.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_mtd80x;
+ common = contrib/gpxe/src/drivers/net/mtd80x.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_r8169;
+ common = contrib/gpxe/src/drivers/net/r8169.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_sundance;
+ common = contrib/gpxe/src/drivers/net/sundance.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_tlan;
+ common = contrib/gpxe/src/drivers/net/tlan.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+/* Following is wireless (disabled for now). */
+
+module = {
+ name = gpxe_prism2;
+ common = contrib/gpxe/src/drivers/net/prism2.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_prism2_plx;
+ common = contrib/gpxe/src/drivers/net/prism2_plx.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_ath5k;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_attach.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_caps.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_desc.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_dma.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_eeprom.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_gpio.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_initvals.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_pcu.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_phy.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_qcu.c;
+ common = contrib/gpxe/src/drivers/net/ath5k/ath5k_reset.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+/* Following require ISA/ISAPNP. Disable for now. */
+
+module = {
+ name = gpxe_3c509;
+ common = contrib/gpxe/src/drivers/net/3c509.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = gpxe_3c515;
+ common = contrib/gpxe/src/drivers/net/3c515.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+/* Following uses crypto. Disable for now. */
+
+module = {
+ name = https;
+ common = contrib/gpxe/src/net/tcp/https.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = tls;
+ common = contrib/gpxe/src/net/tls.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = aoe;
+ common = contrib/gpxe/src/net/aoe.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+module = {
+ name = iscsi;
+ common = contrib/gpxe/src/net/tcp/iscsi.c;
+ cppflags = '$(GPXE_CPPFLAGS)';
+ cflags = '$(GPXE_CFLAGS)';
+};
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/assert.h b/debian/grub-extras/disabled/gpxe/include_wrap/assert.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/assert.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/bits/errfile.h b/debian/grub-extras/disabled/gpxe/include_wrap/bits/errfile.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/bits/errfile.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/bits/uaccess.h b/debian/grub-extras/disabled/gpxe/include_wrap/bits/uaccess.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/bits/uaccess.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/byteswap.h b/debian/grub-extras/disabled/gpxe/include_wrap/byteswap.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/byteswap.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/config/ioapi.h b/debian/grub-extras/disabled/gpxe/include_wrap/config/ioapi.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/config/ioapi.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/console.h b/debian/grub-extras/disabled/gpxe/include_wrap/console.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/console.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/ctype.h b/debian/grub-extras/disabled/gpxe/include_wrap/ctype.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/ctype.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/errno.h b/debian/grub-extras/disabled/gpxe/include_wrap/errno.h
new file mode 100644
index 0000000..c764fc5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/errno.h
@@ -0,0 +1,508 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Error codes
+ *
+ * Return status codes as used within gPXE are designed to allow for
+ * maximum visibility into the source of an error even in an end-user
+ * build with no debugging. They are constructed as follows:
+ *
+ * Bits 7-0 : PXE error code
+ *
+ * This is the closest equivalent PXE error code
+ * (e.g. PXENV_STATUS_OUT_OF_RESOURCES), and is the only part of the
+ * error that will be returned via the PXE API, since PXE has
+ * predefined error codes.
+ *
+ * Bits 12-8 : Per-file disambiguator
+ *
+ * When the same error number can be generated from multiple points
+ * within a file, this field can be used to identify the unique
+ * instance.
+ *
+ * Bits 23-13 : File identifier
+ *
+ * This is a unique identifier for the file generating the error
+ * (e.g. ERRFILE_tcp for tcp.c).
+ *
+ * Bits 30-24 : POSIX error code
+ *
+ * This is the closest equivalent POSIX error code (e.g. ENOMEM).
+ *
+ * Bit 31 : Reserved
+ *
+ * Errors are usually return as negative error numbers (e.g. -EINVAL);
+ * bit 31 is therefore unusable.
+ *
+ *
+ * The convention within the code is that errors are negative and
+ * expressed using the POSIX error code and (optionally) a per-file
+ * disambiguator, e.g.
+ *
+ * return -EINVAL;
+ *
+ * or
+ *
+ * #define ETCP_BAD_CHECKSUM EUNIQ_02
+ * return -( EINVAL | ETCP_BAD_CHECKSUM )
+ *
+ * By various bits of preprocessor magic, the PXE error code and file
+ * identifier are already incorporated into the definition of the
+ * POSIX error code, which keeps the code relatively clean.
+ *
+ *
+ * Functions that wish to return failures should be declared as
+ * returning an integer @c rc "Return status code". A return value of
+ * zero indicates success, a non-zero value indicates failure. The
+ * return value can be passed directly to strerror() in order to
+ * generate a human-readable error message, e.g.
+ *
+ * if ( ( rc = some_function ( ... ) ) != 0 ) {
+ * DBG ( "Whatever I was trying to do failed: %s\n", strerror ( rc ) );
+ * return rc;
+ * }
+ *
+ * As illustrated in the above example, error returns should generally
+ * be directly propagated upward to the calling function.
+ *
+ */
+
+/* Get definitions for file identifiers */
+#include <gpxe/errfile.h>
+
+/* If we do not have a valid file identifier, generate a compiler
+ * warning upon usage of any error codes. (Don't just use a #warning,
+ * because some files include errno.h but don't ever actually use any
+ * error codes.)
+ */
+extern char missing_errfile_declaration[] __attribute__ (( deprecated ));
+#undef ERRFILE
+#define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) )
+
+/** Derive PXENV_STATUS code from gPXE error number */
+#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff )
+
+/**
+ * @defgroup pxeerrors PXE error codes
+ *
+ * The names, meanings and values of these error codes are defined by
+ * the PXE specification.
+ *
+ * @{
+ */
+
+/* Generic errors */
+#define PXENV_STATUS_SUCCESS 0x0000
+#define PXENV_STATUS_FAILURE 0x0001
+#define PXENV_STATUS_BAD_FUNC 0x0002
+#define PXENV_STATUS_UNSUPPORTED 0x0003
+#define PXENV_STATUS_KEEP_UNDI 0x0004
+#define PXENV_STATUS_KEEP_ALL 0x0005
+#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006
+
+/* ARP errors (0x0010 to 0x001f) */
+#define PXENV_STATUS_ARP_TIMEOUT 0x0011
+
+/* Base-Code state errors */
+#define PXENV_STATUS_UDP_CLOSED 0x0018
+#define PXENV_STATUS_UDP_OPEN 0x0019
+#define PXENV_STATUS_TFTP_CLOSED 0x001a
+#define PXENV_STATUS_TFTP_OPEN 0x001b
+
+/* BIOS/system errors (0x0020 to 0x002f) */
+#define PXENV_STATUS_MCOPY_PROBLEM 0x0020
+#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021
+#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022
+#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023
+#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024
+#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025
+#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026
+#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027
+#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028
+
+/* TFTP/MTFTP errors (0x0030 to 0x003f) */
+#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030
+#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032
+#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033
+#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035
+#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036
+#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038
+#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039
+#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a
+#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b
+#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c
+#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d
+#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e
+#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f
+
+/* Reserved errors 0x0040 to 0x004f) */
+
+/* DHCP/BOOTP errors (0x0050 to 0x005f) */
+#define PXENV_STATUS_DHCP_TIMEOUT 0x0051
+#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052
+#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053
+#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054
+
+/* Driver errors (0x0060 to 0x006f) */
+#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060
+#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061
+#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063
+#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064
+#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065
+#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066
+#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067
+#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068
+#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069
+#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a
+#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b
+#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c
+
+/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */
+#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074
+#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076
+#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077
+#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078
+#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079
+
+/* Environment NBP errors (0x0080 to 0x008f) */
+
+/* Reserved errors (0x0090 to 0x009f) */
+
+/* Miscellaneous errors (0x00a0 to 0x00af) */
+#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0
+#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1
+#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2
+#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3
+
+/* BUSD errors (0x00b0 to 0x00bf) */
+#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0
+
+/* Loader errors (0x00c0 to 0x00cf) */
+#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0
+#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1
+#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2
+#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3
+#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4
+#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5
+#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6
+#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8
+#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9
+#define PXENV_STATUS_LOADER_UNDI_START 0x00ca
+#define PXENV_STATUS_LOADER_BC_START 0x00cb
+
+/** @} */
+
+/**
+ * @defgroup posixerrors POSIX error codes
+ *
+ * The names and meanings (but not the values) of these error codes
+ * are defined by POSIX. We choose to assign unique values which
+ * incorporate the closest equivalent PXE error code, so that code may
+ * simply use ENOMEM, rather than having to use the cumbersome
+ * (ENOMEM|PXENV_STATUS_OUT_OF_RESOURCES).
+ *
+ * @{
+ */
+
+/** Operation completed successfully */
+#define ENOERR ( ERRFILE | PXENV_STATUS_SUCCESS | 0x00000000 )
+
+/** Arg list too long */
+#define E2BIG ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x01000000 )
+
+/** Permission denied */
+#define EACCES ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x02000000 )
+
+/** Address in use */
+#define EADDRINUSE ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x03000000 )
+
+/** Address not available */
+#define EADDRNOTAVAIL ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x04000000 )
+
+/** Address family not supported */
+#define EAFNOSUPPORT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x05000000 )
+
+/** Resource temporarily unavailable */
+#define EAGAIN ( ERRFILE | PXENV_STATUS_FAILURE | 0x06000000 )
+
+/** Connection already in progress */
+#define EALREADY ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x07000000 )
+
+/** Bad file descriptor */
+#define EBADF ( ERRFILE | PXENV_STATUS_TFTP_CLOSED | 0x08000000 )
+
+/** Bad message */
+#define EBADMSG ( ERRFILE | PXENV_STATUS_FAILURE | 0x09000000 )
+
+/** Resource busy */
+#define EBUSY ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x0a000000 )
+
+/** Operation canceled */
+#define ECANCELED \
+ ( ERRFILE | PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE | 0x0b000000 )
+
+/** No child processes */
+#define ECHILD ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x0c000000 )
+
+/** Connection aborted */
+#define ECONNABORTED \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0d000000 )
+
+/** Connection refused */
+#define ECONNREFUSED \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION | 0x0e000000 )
+
+/** Connection reset */
+#define ECONNRESET \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x0f000000 )
+
+/** Resource deadlock avoided */
+#define EDEADLK ( ERRFILE | PXENV_STATUS_FAILURE | 0x10000000 )
+
+/** Destination address required */
+#define EDESTADDRREQ ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x11000000 )
+
+/** Domain error */
+#define EDOM ( ERRFILE | PXENV_STATUS_FAILURE | 0x12000000 )
+
+/** Reserved */
+#define EDQUOT ( ERRFILE | PXENV_STATUS_FAILURE | 0x13000000 )
+
+/** File exists */
+#define EEXIST ( ERRFILE | PXENV_STATUS_FAILURE | 0x14000000 )
+
+/** Bad address */
+#define EFAULT ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x15000000 )
+
+/** File too large */
+#define EFBIG ( ERRFILE | PXENV_STATUS_MCOPY_PROBLEM | 0x16000000 )
+
+/** Host is unreachable */
+#define EHOSTUNREACH ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x17000000 )
+
+/** Identifier removed */
+#define EIDRM ( ERRFILE | PXENV_STATUS_FAILURE | 0x18000000 )
+
+/** Illegal byte sequence */
+#define EILSEQ ( ERRFILE | PXENV_STATUS_FAILURE | 0x19000000 )
+
+/** Operation in progress */
+#define EINPROGRESS ( ERRFILE | PXENV_STATUS_FAILURE | 0x1a000000 )
+
+/** Interrupted function call */
+#define EINTR ( ERRFILE | PXENV_STATUS_FAILURE | 0x1b000000 )
+
+/** Invalid argument */
+#define EINVAL ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x1c000000 )
+
+/** Input/output error */
+#define EIO \
+ ( ERRFILE | PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION | 0x1d000000 )
+
+/** Socket is connected */
+#define EISCONN ( ERRFILE | PXENV_STATUS_UDP_OPEN | 0x1e000000 )
+
+/** Is a directory */
+#define EISDIR ( ERRFILE | PXENV_STATUS_FAILURE | 0x1f000000 )
+
+/** Too many levels of symbolic links */
+#define ELOOP ( ERRFILE | PXENV_STATUS_FAILURE | 0x20000000 )
+
+/** Too many open files */
+#define EMFILE ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x21000000 )
+
+/** Too many links */
+#define EMLINK ( ERRFILE | PXENV_STATUS_FAILURE | 0x22000000 )
+
+/** Inappropriate message buffer length */
+#define EMSGSIZE ( ERRFILE | PXENV_STATUS_BAD_FUNC | 0x23000000 )
+
+/** Reserved */
+#define EMULTIHOP ( ERRFILE | PXENV_STATUS_FAILURE | 0x24000000 )
+
+/** Filename too long */
+#define ENAMETOOLONG ( ERRFILE | PXENV_STATUS_FAILURE | 0x25000000 )
+
+/** Network is down */
+#define ENETDOWN ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x26000000 )
+
+/** Connection aborted by network */
+#define ENETRESET ( ERRFILE | PXENV_STATUS_FAILURE | 0x27000000 )
+
+/** Network unreachable */
+#define ENETUNREACH ( ERRFILE | PXENV_STATUS_ARP_TIMEOUT | 0x28000000 )
+
+/** Too many open files in system */
+#define ENFILE ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x29000000 )
+
+/** No buffer space available */
+#define ENOBUFS ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x2a000000 )
+
+/** No message is available on the STREAM head read queue */
+#define ENODATA ( ERRFILE | PXENV_STATUS_FAILURE | 0x2b000000 )
+
+/** No such device */
+#define ENODEV ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2c000000 )
+
+/** No such file or directory */
+#define ENOENT ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x2d000000 )
+
+/** Exec format error */
+#define ENOEXEC ( ERRFILE | PXENV_STATUS_FAILURE | 0x2e000000 )
+
+/** No locks available */
+#define ENOLCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x2f000000 )
+
+/** Reserved */
+#define ENOLINK ( ERRFILE | PXENV_STATUS_FAILURE | 0x30000000 )
+
+/** Not enough space */
+#define ENOMEM ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x31000000 )
+
+/** No message of the desired type */
+#define ENOMSG ( ERRFILE | PXENV_STATUS_FAILURE | 0x32000000 )
+
+/** Protocol not available */
+#define ENOPROTOOPT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x33000000 )
+
+/** No space left on device */
+#define ENOSPC ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x34000000 )
+
+/** No STREAM resources */
+#define ENOSR ( ERRFILE | PXENV_STATUS_OUT_OF_RESOURCES | 0x35000000 )
+
+/** Not a STREAM */
+#define ENOSTR ( ERRFILE | PXENV_STATUS_FAILURE | 0x36000000 )
+
+/** Function not implemented */
+#define ENOSYS ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x37000000 )
+
+/** The socket is not connected */
+#define ENOTCONN ( ERRFILE | PXENV_STATUS_FAILURE | 0x38000000 )
+
+/** Not a directory */
+#define ENOTDIR ( ERRFILE | PXENV_STATUS_FAILURE | 0x39000000 )
+
+/** Directory not empty */
+#define ENOTEMPTY ( ERRFILE | PXENV_STATUS_FAILURE | 0x3a000000 )
+
+/** Not a socket */
+#define ENOTSOCK ( ERRFILE | PXENV_STATUS_FAILURE | 0x3b000000 )
+
+/** Not supported */
+#define ENOTSUP ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3c000000 )
+
+/** Inappropriate I/O control operation */
+#define ENOTTY ( ERRFILE | PXENV_STATUS_FAILURE | 0x3d000000 )
+
+/** No such device or address */
+#define ENXIO ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x3e000000 )
+
+/** Operation not supported on socket */
+#define EOPNOTSUPP ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x3f000000 )
+
+/** Value too large to be stored in data type */
+#define EOVERFLOW ( ERRFILE | PXENV_STATUS_FAILURE | 0x40000000 )
+
+/** Operation not permitted */
+#define EPERM ( ERRFILE | PXENV_STATUS_TFTP_ACCESS_VIOLATION | 0x41000000 )
+
+/** Broken pipe */
+#define EPIPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x42000000 )
+
+/** Protocol error */
+#define EPROTO ( ERRFILE | PXENV_STATUS_FAILURE | 0x43000000 )
+
+/** Protocol not supported */
+#define EPROTONOSUPPORT ( ERRFILE | PXENV_STATUS_UNSUPPORTED | 0x44000000 )
+
+/** Protocol wrong type for socket */
+#define EPROTOTYPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x45000000 )
+
+/** Result too large */
+#define ERANGE ( ERRFILE | PXENV_STATUS_FAILURE | 0x46000000 )
+
+/** Read-only file system */
+#define EROFS ( ERRFILE | PXENV_STATUS_FAILURE | 0x47000000 )
+
+/** Invalid seek */
+#define ESPIPE ( ERRFILE | PXENV_STATUS_FAILURE | 0x48000000 )
+
+/** No such process */
+#define ESRCH ( ERRFILE | PXENV_STATUS_TFTP_FILE_NOT_FOUND | 0x49000000 )
+
+/** Stale file handle */
+#define ESTALE ( ERRFILE | PXENV_STATUS_FAILURE | 0x4a000000 )
+
+/** STREAM ioctl() timeout */
+#define ETIME ( ERRFILE | PXENV_STATUS_FAILURE | 0x4b000000 )
+
+/** Operation timed out */
+#define ETIMEDOUT ( ERRFILE | PXENV_STATUS_TFTP_READ_TIMEOUT | 0x4c000000 )
+
+/** Text file busy */
+#define ETXTBSY ( ERRFILE | PXENV_STATUS_FAILURE | 0x4d000000 )
+
+/** Operation would block (different from EAGAIN!) */
+#define EWOULDBLOCK ( ERRFILE | PXENV_STATUS_TFTP_OPEN | 0x4e000000 )
+
+/** Improper link */
+#define EXDEV ( ERRFILE | PXENV_STATUS_FAILURE | 0x4f000000 )
+
+/** @} */
+
+/**
+ * @defgroup euniq Per-file error disambiguators
+ *
+ * Files which use the same error number multiple times should
+ * probably define their own error subspace using these
+ * disambiguators. For example:
+ *
+ * #define ETCP_HEADER_TOO_SHORT EUNIQ_01
+ * #define ETCP_BAD_CHECKSUM EUNIQ_02
+ *
+ * @{
+ */
+
+#define EUNIQ_01 0x00000100
+#define EUNIQ_02 0x00000200
+#define EUNIQ_03 0x00000300
+#define EUNIQ_04 0x00000400
+#define EUNIQ_05 0x00000500
+#define EUNIQ_06 0x00000600
+#define EUNIQ_07 0x00000700
+#define EUNIQ_08 0x00000800
+#define EUNIQ_09 0x00000900
+#define EUNIQ_0A 0x00000a00
+#define EUNIQ_0B 0x00000b00
+#define EUNIQ_0C 0x00000c00
+#define EUNIQ_0D 0x00000d00
+#define EUNIQ_0E 0x00000e00
+#define EUNIQ_0F 0x00000f00
+#define EUNIQ_10 0x00001000
+#define EUNIQ_11 0x00001100
+#define EUNIQ_12 0x00001200
+#define EUNIQ_13 0x00001300
+#define EUNIQ_14 0x00001400
+#define EUNIQ_15 0x00001500
+#define EUNIQ_16 0x00001600
+#define EUNIQ_17 0x00001700
+#define EUNIQ_18 0x00001800
+#define EUNIQ_19 0x00001900
+#define EUNIQ_1A 0x00001a00
+#define EUNIQ_1B 0x00001b00
+#define EUNIQ_1C 0x00001c00
+#define EUNIQ_1D 0x00001d00
+#define EUNIQ_1E 0x00001e00
+#define EUNIQ_1F 0x00001f00
+
+/** @} */
+
+extern int errno;
+
+#endif /* ERRNO_H */
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/device.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/device.h
new file mode 100644
index 0000000..441a7e1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/device.h
@@ -0,0 +1 @@
+#include <gpxe/pci.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/efi/efi_uaccess.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/efi/efi_uaccess.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/efi/efi_uaccess.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/features.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/features.h
new file mode 100644
index 0000000..f17ade3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/features.h
@@ -0,0 +1,68 @@
+#ifndef _GPXE_FEATURES_H
+#define _GPXE_FEATURES_H
+
+#include <stdint.h>
+#include <gpxe/tables.h>
+#include <gpxe/dhcp.h>
+
+/** @file
+ *
+ * Feature list
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @defgroup featurecat Feature categories
+ * @{
+ */
+
+#define FEATURE_PROTOCOL 01 /**< Network protocols */
+#define FEATURE_IMAGE 02 /**< Image formats */
+#define FEATURE_MISC 03 /**< Miscellaneous */
+
+/** @} */
+
+/**
+ * @defgroup dhcpfeatures DHCP feature option tags
+ *
+ * DHCP feature option tags are Etherboot encapsulated options in the
+ * range 0x10-0x7f.
+ *
+ * @{
+ */
+
+#define DHCP_EB_FEATURE_PXE_EXT 0x10 /**< PXE API extensions */
+#define DHCP_EB_FEATURE_ISCSI 0x11 /**< iSCSI protocol */
+#define DHCP_EB_FEATURE_AOE 0x12 /**< AoE protocol */
+#define DHCP_EB_FEATURE_HTTP 0x13 /**< HTTP protocol */
+#define DHCP_EB_FEATURE_HTTPS 0x14 /**< HTTPS protocol */
+#define DHCP_EB_FEATURE_TFTP 0x15 /**< TFTP protocol */
+#define DHCP_EB_FEATURE_FTP 0x16 /**< FTP protocol */
+#define DHCP_EB_FEATURE_DNS 0x17 /**< DNS protocol */
+#define DHCP_EB_FEATURE_BZIMAGE 0x18 /**< bzImage format */
+#define DHCP_EB_FEATURE_MULTIBOOT 0x19 /**< Multiboot format */
+#define DHCP_EB_FEATURE_SLAM 0x1a /**< SLAM protocol */
+#define DHCP_EB_FEATURE_SRP 0x1b /**< SRP protocol */
+#define DHCP_EB_FEATURE_NBI 0x20 /**< NBI format */
+#define DHCP_EB_FEATURE_PXE 0x21 /**< PXE format */
+#define DHCP_EB_FEATURE_ELF 0x22 /**< ELF format */
+#define DHCP_EB_FEATURE_COMBOOT 0x23 /**< COMBOOT format */
+#define DHCP_EB_FEATURE_EFI 0x24 /**< EFI format */
+
+/** @} */
+
+
+/** Construct a DHCP feature table entry */
+#define DHCP_FEATURE( feature_opt, ... )
+/** Construct a named feature */
+#define FEATURE_NAME( category, text )
+
+/** Declare a feature */
+#define FEATURE( category, text, feature_opt, version )
+
+/** Declare the version number feature */
+#define FEATURE_VERSION( ... )
+
+#endif /* _GPXE_FEATURES_H */
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/io.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/io.h
new file mode 100644
index 0000000..441a7e1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/io.h
@@ -0,0 +1 @@
+#include <gpxe/pci.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/list.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/list.h
new file mode 100644
index 0000000..a4bcdb7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/list.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef _GPXE_LIST_H
+#define _GPXE_LIST_H 1
+
+#include <grub/types.h>
+#include <gpxe/wrap.h>
+
+struct list_head
+{
+ struct list_head *next;
+ struct list_head *prev;
+};
+
+#define LIST_HEAD struct list_head
+
+#define INIT_LIST_HEAD(x) ((x)->next = NULL)
+#define LIST_HEAD_INIT(x) { .next = NULL, .prev = NULL }
+#define list_empty(x) ((x)->next == NULL)
+
+#define offsetof(type, elem) ((grub_uint8_t *) (&((type *) NULL)->elem) - (grub_uint8_t *) NULL)
+#define container_of(var, type, elem) ((type *) ((grub_uint8_t *)(var) - offsetof (type, elem)))
+
+#define list_get_next(it, lst_el, hold) \
+ container_of ((it)->lst_el.next, typeof (*hold), lst_el)
+
+#define list_for_each_entry(it, lst, lst_el) \
+ for ((it) = container_of((lst)->next, typeof (*(it)), lst_el); \
+ &(it)->lst_el != NULL && &(it)->lst_el != (void *) lst; \
+ (it) = list_get_next(it, lst_el, it))
+
+#define list_for_each_entry_safe(it, next_h, lst, lst_el) \
+ for ((it) = container_of((lst)->next, typeof (*(it)), lst_el); \
+ &(it)->lst_el != NULL && &(it)->lst_el != (void *) lst; \
+ ((it) = container_of ((next_h), typeof (*(next_h)), lst_el)), \
+ (next_h) = list_get_next(it, lst_el, next_h))
+
+
+static inline void
+list_del (struct list_head *head)
+{
+ if (head->next == head->prev)
+ {
+ head->next->prev = NULL;
+ head->prev->next = NULL;
+ }
+ else
+ {
+ head->prev->next = head->next;
+ head->next->prev = head->prev;
+ }
+}
+
+static inline void
+list_add_tail (struct list_head *head, struct list_head *new)
+{
+ if (list_empty (head))
+ {
+ head->next = head->prev = new;
+ new->next = new->prev = head;
+ }
+ else
+ {
+ head->prev->next = new;
+ new->prev = head->prev;
+ new->next = head;
+ head->prev = new;
+ }
+}
+
+static inline void
+list_add (struct list_head *head, struct list_head *new)
+{
+ if (list_empty (head))
+ {
+ head->next = head->prev = new;
+ new->next = new->prev = head;
+ }
+ else
+ {
+ head->next->prev = new;
+ new->next = head->next;
+ new->prev = head;
+ head->next = new;
+ }
+}
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/nap.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/nap.h
new file mode 100644
index 0000000..a4bd90b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/nap.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef _GPXE_NAP_H
+#define _GPXE_NAP_H
+
+#include <grub/time.h>
+
+static inline void
+cpu_nap ( void )
+{
+ grub_cpu_idle ();
+}
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/pci.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/pci.h
new file mode 100644
index 0000000..964cf43
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/pci.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef _GPXE_PCI_H
+#define _GPXE_PCI_H
+
+#include <grub/pci.h>
+#include <gpxe/wrap.h>
+#include <gpxe/timer.h>
+
+static inline grub_uint8_t
+inb (grub_uint16_t port)
+{
+ return grub_inb (GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+outb (grub_uint8_t data, grub_uint16_t port)
+{
+ return grub_outb (data, GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+outw (grub_uint16_t data, grub_uint16_t port)
+{
+ return grub_outw (data, GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline grub_uint16_t
+inw (grub_uint16_t port)
+{
+ return grub_inw (GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+insw (grub_uint16_t port, grub_uint16_t *data, int count)
+{
+ while (count--)
+ *data++ = grub_inw (GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+outsw (grub_uint16_t port, grub_uint16_t *data, int count)
+{
+ while (count--)
+ grub_outw (*data++, GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+outsb (grub_uint16_t port, grub_uint8_t *data, int count)
+{
+ while (count--)
+ grub_outb (*data++, GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+insb (grub_uint16_t port, grub_uint8_t *data, int count)
+{
+ while (count--)
+ *data++ = grub_inb (GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline void
+outl (grub_uint32_t data, grub_uint16_t port)
+{
+ return grub_outw (data, GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+static inline grub_uint16_t
+inl (grub_uint32_t port)
+{
+ return grub_inw (GRUB_MACHINE_PCI_IO_BASE + port);
+}
+
+struct device_description
+{
+ enum {BUS_TYPE_PCI, BUS_TYPE_ISA} bus_type;
+ int bus;
+ int location;
+ grub_uint16_t vendor;
+ grub_uint16_t device;
+};
+
+struct device
+{
+ struct device_description desc;
+ char *name;
+ union
+ {
+ grub_pci_device_t pci_dev;
+ };
+};
+
+struct pci_device
+{
+ struct device dev;
+
+ grub_uint16_t ioaddr;
+ grub_uint16_t vendor;
+ grub_uint16_t device;
+
+ int irq;
+
+ void *priv;
+
+ void *drvdata;
+};
+
+struct pci_device_id
+{
+ grub_pci_id_t devid;
+};
+
+#define PCI_ROM(vendor, model, short_name, long_name, num) {.devid = ((vendor) | ((model) << 16))}
+#define __pci_driver
+
+struct nic;
+
+struct pci_driver
+{
+ struct pci_device_id *ids;
+ grub_size_t id_count;
+ int (*probe) (struct pci_device *pci, const struct pci_device_id *id);
+ void (*remove) (struct pci_device *pci);
+ void (*irq) (struct nic *nic, int action);
+};
+
+static inline void
+pci_read_config_byte (struct pci_device *dev, grub_uint32_t reg,
+ grub_uint8_t *val)
+{
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg);
+ *val = grub_pci_read_byte (addr);
+}
+
+static inline void
+pci_read_config_word (struct pci_device *dev, grub_uint32_t reg,
+ grub_uint16_t *val)
+{
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg);
+ *val = grub_pci_read_word (addr);
+}
+
+static inline void
+pci_read_config_dword (struct pci_device *dev, grub_uint32_t reg,
+ grub_uint32_t *val)
+{
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg);
+ *val = grub_pci_read (addr);
+}
+
+static inline void
+pci_write_config_byte (struct pci_device *dev, grub_uint32_t reg,
+ grub_uint8_t val)
+{
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg);
+ grub_pci_write_byte (addr, val);
+}
+
+static inline void
+pci_write_config_word (struct pci_device *dev, grub_uint32_t reg,
+ grub_uint16_t val)
+{
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg);
+ grub_pci_write_word (addr, val);
+}
+
+static inline void
+pci_write_config_dword (struct pci_device *dev, grub_uint32_t reg,
+ grub_uint32_t val)
+{
+ grub_pci_address_t addr;
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg);
+ grub_pci_write (addr, val);
+}
+
+static inline void *
+pci_get_drvdata (struct pci_device *dev)
+{
+ return dev->drvdata;
+}
+
+static inline void
+pci_set_drvdata (struct pci_device *dev, void *data)
+{
+ dev->drvdata = data;
+}
+
+static inline grub_uint32_t
+readl (volatile void *ptr)
+{
+ return *(volatile grub_uint32_t *) ptr;
+}
+
+static inline void
+writel (grub_uint32_t data, volatile void *ptr)
+{
+ *(volatile grub_uint32_t *) ptr = data;
+}
+
+static inline grub_addr_t
+pci_bar_start (struct pci_device *dev, grub_uint32_t reg)
+{
+ grub_pci_address_t addr;
+ grub_uint64_t space;
+
+ addr = grub_pci_make_address (dev->dev.pci_dev, reg >> 2);
+ space = grub_pci_read (addr);
+
+ if ((space & GRUB_PCI_ADDR_SPACE_MASK) == GRUB_PCI_ADDR_SPACE_IO)
+ return space & GRUB_PCI_ADDR_IO_MASK;
+
+ if ((space & GRUB_PCI_ADDR_MEM_TYPE_MASK) == GRUB_PCI_ADDR_MEM_TYPE_64)
+ {
+ addr = grub_pci_make_address (dev->dev.pci_dev, (reg >> 2) + 1);
+ space |= ((grub_uint64_t) grub_pci_read (addr)) << 32;
+ }
+
+ return space & GRUB_PCI_ADDR_MEM_MASK;
+}
+
+/* XXX: make it use grub_pci_device_map_range. */
+static inline void *
+bus_to_virt (grub_uint32_t bus)
+{
+ return (void *) bus;
+}
+
+static inline void *
+ioremap (grub_uint32_t bus, grub_size_t size __attribute__ ((unused)))
+{
+ return (void *) bus;
+}
+
+static inline grub_uint32_t
+virt_to_bus (void *virt)
+{
+ return (grub_addr_t) virt;
+}
+
+void
+grub_gpxe_register_pci_nic (struct pci_driver *nic);
+
+void
+grub_gpxe_unregister_pci_nic (struct pci_driver *nic);
+
+void adjust_pci_device ( struct pci_device *pci );
+
+#define PCI_VENDOR_ID_DAVICOM 0x0291
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_COMMAND GRUB_PCI_REG_COMMAND
+#define PCI_REVISION_ID GRUB_PCI_REG_REVISION
+#define PCI_REVISION PCI_REVISION_ID
+#define PCI_LATENCY_TIMER GRUB_PCI_REG_LAT_TIMER
+#define PCI_BASE_ADDRESS_0 GRUB_PCI_REG_ADDRESS_REG0
+#define PCI_BASE_ADDRESS_1 GRUB_PCI_REG_ADDRESS_REG1
+#define PCI_COMMAND_IO 0x1
+#define PCI_COMMAND_MEM 0x2
+#define PCI_COMMAND_MASTER 0x4
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/timer.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/timer.h
new file mode 100644
index 0000000..22484c7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/timer.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef _GPXE_TIMER_H
+#define _GPXE_TIMER_H
+
+#include <grub/time.h>
+
+static inline void
+udelay ( unsigned long usecs )
+{
+ grub_millisleep ((usecs + 999) / 1000);
+}
+
+static inline void
+mdelay (unsigned delay)
+{
+ grub_millisleep (delay);
+}
+
+static inline void
+sleep (unsigned delay)
+{
+ grub_millisleep (1000 * delay);
+}
+
+
+static inline unsigned long
+currticks ( void )
+{
+ return grub_get_time_ms ();
+}
+
+#define TICKS_PER_SEC (1000)
+#define ticks_per_sec() TICKS_PER_SEC
+
+#endif /* _GPXE_TIMER_H */
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/vsprintf.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/vsprintf.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/vsprintf.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/wrap.h b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/wrap.h
new file mode 100644
index 0000000..61b7570
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/gpxe/wrap.h
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef _GPXE_WRAP_H
+#define _GPXE_WRAP_H
+
+#include <config.h>
+
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <errno.h>
+#include <grub/mm.h>
+#include <gpxe/list.h>
+#include <gpxe/timer.h>
+
+void *
+memchr (void *s, grub_uint8_t c, grub_size_t size);
+
+#define be64_to_cpu grub_be_to_cpu64
+#define cpu_to_be64 grub_cpu_to_be64
+#define cpu_to_be32 grub_cpu_to_be32
+#define cpu_to_be16 grub_cpu_to_be16
+#define le16_to_cpu grub_le_to_cpu16
+#define be16_to_cpu grub_be_to_cpu16
+#define be32_to_cpu grub_be_to_cpu32
+#define cpu_to_le16 grub_cpu_to_le16
+#define cpu_to_le32 grub_cpu_to_le32
+#define le32_to_cpu grub_le_to_cpu32
+
+/* In gPXE codebase following has to be a macro.
+ So grub_cpu_to_be isn't usable. */
+#define bswap_16(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define swap16 bswap_16
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+#define htons(x) (x)
+#define htonl(x) (x)
+#else
+#define htons(x) (bswap_16(x))
+#define htonl(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
+#endif
+
+#define ntohl(x) htonl(x)
+#define ntohs(x) htons(x)
+
+typedef grub_uint64_t u64;
+typedef grub_uint64_t uint64_t;
+typedef grub_uint32_t u32;
+typedef grub_int32_t s32;
+typedef grub_uint32_t uint32_t;
+typedef grub_int32_t int32_t;
+typedef grub_uint16_t u16;
+typedef grub_int16_t s16;
+typedef grub_uint16_t uint16_t;
+typedef grub_int16_t int16_t;
+typedef grub_uint8_t u8;
+typedef grub_uint8_t uint8_t;
+typedef grub_int8_t int8_t;
+typedef grub_size_t size_t;
+
+#define __malloc
+#define __shared
+#define __unused __attribute__ ((unused))
+
+#define off_t grub_off_t
+
+#define strcpy grub_strcpy
+
+#if 0
+typedef void *userptr_t;
+
+static inline void memcpy_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len )
+{
+ grub_memcpy ((void *) (dest + dest_off), (void *) (src + src_off), len);
+}
+#endif
+
+#define memcpy grub_memcpy
+
+#define zalloc grub_zalloc
+#define strdup grub_strdup
+#define strncmp grub_strncmp
+#define strchr grub_strchr
+#define strcasecmp grub_strcasecmp
+#define printf grub_printf
+#define intptr_t grub_addr_t
+
+static inline void *
+malloc (grub_size_t size)
+{
+ return grub_malloc (size);
+}
+
+static inline void *
+realloc (void *ptr, grub_size_t size)
+{
+ return grub_realloc (ptr, size);
+}
+
+static inline grub_size_t
+strlen (const char *s)
+{
+ return grub_strlen (s);
+}
+
+static inline int
+strcmp (const char *s1, const char *s2)
+{
+ return grub_strcmp (s1, s2);
+}
+
+static inline int
+toupper (int c)
+{
+ return grub_toupper (c);
+}
+
+static inline int
+tolower (int c)
+{
+ return grub_tolower (c);
+}
+
+unsigned long strtoul ( const char *p, char **endp, int base );
+
+static inline int
+isspace (int c)
+{
+ return grub_isspace (c);
+}
+
+static inline int
+isdigit (int c)
+{
+ return grub_isdigit (c);
+}
+
+static inline int
+isalpha (int c)
+{
+ return grub_isalpha (c);
+}
+
+static inline int
+islower (int c)
+{
+ return (c >= 'a' && c <= 'z');
+}
+
+static inline int
+isupper (int c)
+{
+ return (c >= 'A' && c <= 'Z');
+}
+
+typedef grub_ssize_t ssize_t;
+
+static inline void
+free (void *ptr)
+{
+ grub_free (ptr);
+}
+
+#define assert(x) assert_real(__FILE__, __LINE__, x)
+
+static inline void
+assert_real (const char *file, int line, int cond)
+{
+ if (!cond)
+ grub_fatal ("Assertion failed at %s:%d\n", file, line);
+}
+
+#define __assert_fail grub_abort
+
+#define __always_inline
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 97
+#define VERSION_PATCH 1
+
+#define strstr grub_strstr
+#define alloc_memblock(size,align) grub_memalign(align,size)
+
+#define DBG(fmt,args...) grub_dprintf("net", fmt, ## args)
+#define DBG2(fmt,args...) grub_dprintf("net", fmt, ## args)
+#define DBG_HD(data,len)
+#define DBGP(fmt,args...) grub_dprintf("net", fmt, ## args)
+#define DBGP_HD(data,len)
+#define DBGC(ptr, fmt,args...) grub_dprintf("net", fmt, ## args)
+#define DBGCP(ptr, fmt,args...) grub_dprintf("net", fmt, ## args)
+#define DBGC2(ptr, fmt,args...) grub_dprintf("net", fmt, ## args)
+#define DBGC_HD(ptr,data,len)
+#define DBGCP_HD(ptr,data,len)
+#define DBGC_HDA(ptr,s,data,len)
+#define DBGC2_HDA(ptr,s,data,len)
+#define DBGCP_HDA(ptr,s,data,len)
+
+#define strrchr grub_strrchr
+
+static inline void
+memswap (void *b1, void *b2, grub_size_t size)
+{
+ register grub_uint8_t t;
+ while (size--)
+ {
+ t = *(grub_uint8_t *) b1;
+ *(grub_uint8_t *) b1 = *(grub_uint8_t *) b2;
+ *(grub_uint8_t *) b2 = t;
+ b1 = (grub_uint8_t *) b1 + 1;
+ b2 = (grub_uint8_t *) b2 + 1;
+ }
+}
+
+static inline int
+flsl (long n)
+{
+ int i;
+ for (i = sizeof (n) - 1; i >= 0; i--)
+ if (n & (1 << i))
+ return i + 1;
+ return 0;
+}
+
+#define INT_MAX 2147483647L
+
+#define putchar(x) grub_printf("%c", x)
+
+#define snprintf grub_snprintf
+#define ssnprintf grub_snprintf
+#define vsnprintf grub_vsnprintf
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/libgen.h b/debian/grub-extras/disabled/gpxe/include_wrap/libgen.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/libgen.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/limits.h b/debian/grub-extras/disabled/gpxe/include_wrap/limits.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/limits.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/stddef.h b/debian/grub-extras/disabled/gpxe/include_wrap/stddef.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/stddef.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/stdint.h b/debian/grub-extras/disabled/gpxe/include_wrap/stdint.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/stdint.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/stdio.h b/debian/grub-extras/disabled/gpxe/include_wrap/stdio.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/stdio.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/stdlib.h b/debian/grub-extras/disabled/gpxe/include_wrap/stdlib.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/stdlib.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/string.h b/debian/grub-extras/disabled/gpxe/include_wrap/string.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/string.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/strings.h b/debian/grub-extras/disabled/gpxe/include_wrap/strings.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/strings.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/include_wrap/unistd.h b/debian/grub-extras/disabled/gpxe/include_wrap/unistd.h
new file mode 100644
index 0000000..b1a5272
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/include_wrap/unistd.h
@@ -0,0 +1 @@
+#include <gpxe/wrap.h>
diff --git a/debian/grub-extras/disabled/gpxe/src/core/base64.c b/debian/grub-extras/disabled/gpxe/src/core/base64.c
new file mode 100644
index 0000000..5619ef7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/base64.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <gpxe/base64.h>
+
+/** @file
+ *
+ * Base64 encoding
+ *
+ */
+
+static const char base64[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * Base64-encode a string
+ *
+ * @v raw Raw string
+ * @v encoded Buffer for encoded string
+ *
+ * The buffer must be the correct length for the encoded string. Use
+ * something like
+ *
+ * char buf[ base64_encoded_len ( strlen ( raw ) ) + 1 ];
+ *
+ * (the +1 is for the terminating NUL) to provide a buffer of the
+ * correct size.
+ */
+void base64_encode ( const char *raw, char *encoded ) {
+ const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
+ uint8_t *encoded_bytes = ( ( uint8_t * ) encoded );
+ size_t raw_bit_len = ( 8 * strlen ( raw ) );
+ unsigned int bit;
+ unsigned int tmp;
+
+ for ( bit = 0 ; bit < raw_bit_len ; bit += 6 ) {
+ tmp = ( ( raw_bytes[ bit / 8 ] << ( bit % 8 ) ) |
+ ( raw_bytes[ bit / 8 + 1 ] >> ( 8 - ( bit % 8 ) ) ) );
+ tmp = ( ( tmp >> 2 ) & 0x3f );
+ *(encoded_bytes++) = base64[tmp];
+ }
+ for ( ; ( bit % 8 ) != 0 ; bit += 6 )
+ *(encoded_bytes++) = '=';
+ *(encoded_bytes++) = '\0';
+
+ DBG ( "Base64-encoded \"%s\" as \"%s\"\n", raw, encoded );
+ assert ( strlen ( encoded ) == base64_encoded_len ( strlen ( raw ) ) );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/basename.c b/debian/grub-extras/disabled/gpxe/src/core/basename.c
new file mode 100644
index 0000000..a481c54
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/basename.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Get base name of path
+ *
+ */
+
+#include <string.h>
+#include <libgen.h>
+
+/**
+ * Return base name from path
+ *
+ * @v path Full path
+ * @ret basename Base name
+ */
+char * basename ( char *path ) {
+ char *basename;
+
+ basename = strrchr ( path, '/' );
+ return ( basename ? ( basename + 1 ) : path );
+}
+
+/**
+ * Return directory name from path
+ *
+ * @v path Full path
+ * @ret dirname Directory name
+ *
+ * Note that this function may modify its argument.
+ */
+char * dirname ( char *path ) {
+ char *separator;
+
+ separator = strrchr ( path, '/' );
+ if ( separator == path ) {
+ return "/";
+ } else if ( separator ) {
+ *separator = 0;
+ return path;
+ } else {
+ return ".";
+ }
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/bitmap.c b/debian/grub-extras/disabled/gpxe/src/core/bitmap.c
new file mode 100644
index 0000000..bbe9cba
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/bitmap.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <gpxe/bitmap.h>
+
+/** @file
+ *
+ * Bitmaps for multicast downloads
+ *
+ */
+
+/**
+ * Resize bitmap
+ *
+ * @v bitmap Bitmap
+ * @v new_length New length of bitmap, in bits
+ * @ret rc Return status code
+ */
+int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length ) {
+ unsigned int old_num_blocks;
+ unsigned int new_num_blocks;
+ size_t new_size;
+ bitmap_block_t *new_blocks;
+
+ old_num_blocks = BITMAP_INDEX ( bitmap->length + BITMAP_BLKSIZE - 1 );
+ new_num_blocks = BITMAP_INDEX ( new_length + BITMAP_BLKSIZE - 1 );
+
+ if ( old_num_blocks != new_num_blocks ) {
+ new_size = ( new_num_blocks * sizeof ( bitmap->blocks[0] ) );
+ new_blocks = realloc ( bitmap->blocks, new_size );
+ if ( ! new_blocks ) {
+ DBGC ( bitmap, "Bitmap %p could not resize to %d "
+ "bits\n", bitmap, new_length );
+ return -ENOMEM;
+ }
+ bitmap->blocks = new_blocks;
+ }
+ bitmap->length = new_length;
+
+ while ( old_num_blocks < new_num_blocks ) {
+ bitmap->blocks[old_num_blocks++] = 0;
+ }
+
+ DBGC ( bitmap, "Bitmap %p resized to %d bits\n", bitmap, new_length );
+ return 0;
+}
+
+/**
+ * Test bit in bitmap
+ *
+ * @v bitmap Bitmap
+ * @v bit Bit index
+ * @ret is_set Bit is set
+ */
+int bitmap_test ( struct bitmap *bitmap, unsigned int bit ) {
+ unsigned int index = BITMAP_INDEX ( bit );
+ bitmap_block_t mask = BITMAP_MASK ( bit );
+
+ if ( bit >= bitmap->length )
+ return 0;
+ return ( bitmap->blocks[index] & mask );
+}
+
+/**
+ * Set bit in bitmap
+ *
+ * @v bitmap Bitmap
+ * @v bit Bit index
+ */
+void bitmap_set ( struct bitmap *bitmap, unsigned int bit ) {
+ unsigned int index = BITMAP_INDEX ( bit );
+ bitmap_block_t mask = BITMAP_MASK ( bit );
+
+ DBGC ( bitmap, "Bitmap %p setting bit %d\n", bitmap, bit );
+
+ /* Update bitmap */
+ bitmap->blocks[index] |= mask;
+
+ /* Update first gap counter */
+ while ( bitmap_test ( bitmap, bitmap->first_gap ) ) {
+ bitmap->first_gap++;
+ }
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/cwuri.c b/debian/grub-extras/disabled/gpxe/src/core/cwuri.c
new file mode 100644
index 0000000..65e01b2
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/cwuri.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <gpxe/uri.h>
+
+/** @file
+ *
+ * Current working URI
+ *
+ * Somewhat analogous to the current working directory in a POSIX
+ * system.
+ */
+
+/** Current working URI */
+struct uri *cwuri = NULL;
+
+/**
+ * Change working URI
+ *
+ * @v uri New working URI, or NULL
+ */
+void churi ( struct uri *uri ) {
+ struct uri *new_uri;
+
+ new_uri = resolve_uri ( cwuri, uri );
+ uri_put ( cwuri );
+ cwuri = new_uri;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/interface.c b/debian/grub-extras/disabled/gpxe/src/core/interface.c
new file mode 100644
index 0000000..6451bfe
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/interface.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/wrap.h>
+#include <gpxe/interface.h>
+
+/** @file
+ *
+ * Object communication interfaces
+ *
+ */
+
+/**
+ * Plug an interface into a new destination interface
+ *
+ * @v intf Interface
+ * @v dest New destination interface
+ *
+ * The reference to the existing destination interface is dropped, a
+ * reference to the new destination interface is obtained, and the
+ * interface is updated to point to the new destination interface.
+ *
+ * Note that there is no "unplug" call; instead you must plug the
+ * interface into a null interface.
+ */
+void plug ( struct interface *intf, struct interface *dest ) {
+ DBGC ( intf, "INTF %p moving from INTF %p to INTF %p\n",
+ intf, intf->dest, dest );
+ intf_put ( intf->dest );
+ intf->dest = intf_get ( dest );
+}
+
+/**
+ * Plug two interfaces together
+ *
+ * @v a Interface A
+ * @v b Interface B
+ *
+ * Plugs interface A into interface B, and interface B into interface
+ * A. (The basic plug() function is unidirectional; this function is
+ * merely a shorthand for two calls to plug(), hence the name.)
+ */
+void plug_plug ( struct interface *a, struct interface *b ) {
+ plug ( a, b );
+ plug ( b, a );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/iobuf.c b/debian/grub-extras/disabled/gpxe/src/core/iobuf.c
new file mode 100644
index 0000000..1ce7890
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/iobuf.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <gpxe/malloc.h>
+#include <gpxe/iobuf.h>
+
+/** @file
+ *
+ * I/O buffers
+ *
+ */
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v len Required length of buffer
+ * @ret iobuf I/O buffer, or NULL if none available
+ *
+ * The I/O buffer will be physically aligned to a multiple of
+ * @c IOBUF_SIZE.
+ */
+struct io_buffer * alloc_iob ( size_t len ) {
+ struct io_buffer *iobuf = NULL;
+ void *data;
+
+ /* Pad to minimum length */
+ if ( len < IOB_ZLEN )
+ len = IOB_ZLEN;
+
+ /* Align buffer length */
+ len = ( len + __alignof__( *iobuf ) - 1 ) &
+ ~( __alignof__( *iobuf ) - 1 );
+
+ /* Allocate memory for buffer plus descriptor */
+ data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN );
+ if ( ! data )
+ return NULL;
+
+ iobuf = ( struct io_buffer * ) ( data + len );
+ iobuf->head = iobuf->data = iobuf->tail = data;
+ iobuf->end = iobuf;
+ return iobuf;
+}
+
+/**
+ * Free I/O buffer
+ *
+ * @v iobuf I/O buffer
+ */
+void free_iob ( struct io_buffer *iobuf ) {
+ if ( iobuf ) {
+ assert ( iobuf->head <= iobuf->data );
+ assert ( iobuf->data <= iobuf->tail );
+ assert ( iobuf->tail <= iobuf->end );
+ free_dma ( iobuf->head,
+ ( iobuf->end - iobuf->head ) + sizeof ( *iobuf ) );
+ }
+}
+
+/**
+ * Ensure I/O buffer has sufficient headroom
+ *
+ * @v iobuf I/O buffer
+ * @v len Required headroom
+ *
+ * This function currently only checks for the required headroom; it
+ * does not reallocate the I/O buffer if required. If we ever have a
+ * code path that requires this functionality, it's a fairly trivial
+ * change to make.
+ */
+int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) {
+
+ if ( iob_headroom ( iobuf ) >= len )
+ return 0;
+ return -ENOBUFS;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/core/job.c b/debian/grub-extras/disabled/gpxe/src/core/job.c
new file mode 100644
index 0000000..438064e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/job.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <gpxe/job.h>
+
+/** @file
+ *
+ * Job control interfaces
+ *
+ */
+
+void job_done ( struct job_interface *job, int rc ) {
+ struct job_interface *dest = job_get_dest ( job );
+
+ job_unplug ( job );
+ dest->op->done ( dest, rc );
+ job_put ( dest );
+}
+
+void job_kill ( struct job_interface *job ) {
+ struct job_interface *dest = job_get_dest ( job );
+
+ job_unplug ( job );
+ dest->op->kill ( dest );
+ job_put ( dest );
+}
+
+void job_progress ( struct job_interface *job,
+ struct job_progress *progress ) {
+ struct job_interface *dest = job_get_dest ( job );
+
+ dest->op->progress ( dest, progress );
+ job_put ( dest );
+}
+
+/****************************************************************************
+ *
+ * Helper methods
+ *
+ * These functions are designed to be used as methods in the
+ * job_interface_operations table.
+ *
+ */
+
+void ignore_job_done ( struct job_interface *job __unused, int rc __unused ) {
+ /* Nothing to do */
+}
+
+void ignore_job_kill ( struct job_interface *job __unused ) {
+ /* Nothing to do */
+}
+
+void ignore_job_progress ( struct job_interface *job __unused,
+ struct job_progress *progress ) {
+ memset ( progress, 0, sizeof ( *progress ) );
+}
+
+/** Null job control interface operations */
+struct job_interface_operations null_job_ops = {
+ .done = ignore_job_done,
+ .kill = ignore_job_kill,
+ .progress = ignore_job_progress,
+};
+
+/**
+ * Null job control interface
+ *
+ * This is the interface to which job control interfaces are connected
+ * when unplugged. It will never generate messages, and will silently
+ * absorb all received messages.
+ */
+struct job_interface null_job = {
+ .intf = {
+ .dest = &null_job.intf,
+ .refcnt = NULL,
+ },
+ .op = &null_job_ops,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/core/linebuf.c b/debian/grub-extras/disabled/gpxe/src/core/linebuf.c
new file mode 100644
index 0000000..221f4e1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/linebuf.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Line buffering
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <gpxe/linebuf.h>
+
+/**
+ * Retrieve buffered-up line
+ *
+ * @v linebuf Line buffer
+ * @ret line Buffered line, or NULL if no line ready to read
+ */
+char * buffered_line ( struct line_buffer *linebuf ) {
+ return ( linebuf->ready ? linebuf->data : NULL );
+}
+
+/**
+ * Discard line buffer contents
+ *
+ * @v linebuf Line buffer
+ */
+void empty_line_buffer ( struct line_buffer *linebuf ) {
+ free ( linebuf->data );
+ linebuf->data = NULL;
+ linebuf->len = 0;
+ linebuf->ready = 0;
+}
+
+/**
+ * Buffer up received data by lines
+ *
+ * @v linebuf Line buffer
+ * @v data New data to add
+ * @v len Length of new data to add
+ * @ret len Consumed length, or negative error number
+ *
+ * After calling line_buffer(), use buffered_line() to determine
+ * whether or not a complete line is available. Carriage returns and
+ * newlines will have been stripped, and the line will be
+ * NUL-terminated. This buffered line is valid only until the next
+ * call to line_buffer() (or to empty_line_buffer()).
+ *
+ * Note that line buffers use dynamically allocated storage; you
+ * should call empty_line_buffer() before freeing a @c struct @c
+ * line_buffer.
+ */
+ssize_t line_buffer ( struct line_buffer *linebuf,
+ const char *data, size_t len ) {
+ const char *eol;
+ size_t consume;
+ size_t new_len;
+ char *new_data;
+
+ /* Free any completed line from previous iteration */
+ if ( linebuf->ready )
+ empty_line_buffer ( linebuf );
+
+ /* Search for line terminator */
+ if ( ( eol = memchr ( data, '\n', len ) ) ) {
+ consume = ( eol - data + 1 );
+ } else {
+ consume = len;
+ }
+
+ /* Reallocate data buffer and copy in new data */
+ new_len = ( linebuf->len + consume );
+ new_data = realloc ( linebuf->data, ( new_len + 1 ) );
+ if ( ! new_data )
+ return -ENOMEM;
+ memcpy ( ( new_data + linebuf->len ), data, consume );
+ new_data[new_len] = '\0';
+ linebuf->data = new_data;
+ linebuf->len = new_len;
+
+ /* If we have reached end of line, trim the line and mark as ready */
+ if ( eol ) {
+ linebuf->data[--linebuf->len] = '\0'; /* trim NL */
+ if ( linebuf->data[linebuf->len - 1] == '\r' )
+ linebuf->data[--linebuf->len] = '\0'; /* trim CR */
+ linebuf->ready = 1;
+ }
+
+ return consume;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/misc.c b/debian/grub-extras/disabled/gpxe/src/core/misc.c
new file mode 100644
index 0000000..c19591b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/misc.c
@@ -0,0 +1,80 @@
+/**************************************************************************
+MISC Support Routines
+**************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <byteswap.h>
+#include <gpxe/in.h>
+#include <gpxe/timer.h>
+
+/**************************************************************************
+INET_ATON - Convert an ascii x.x.x.x to binary form
+**************************************************************************/
+int inet_aton ( const char *cp, struct in_addr *inp ) {
+ const char *p = cp;
+ const char *digits_start;
+ unsigned long ip = 0;
+ unsigned long val;
+ int j;
+ for(j = 0; j <= 3; j++) {
+ digits_start = p;
+ val = strtoul(p, ( char ** ) &p, 10);
+ if ((p == digits_start) || (val > 255)) return 0;
+ if ( ( j < 3 ) && ( *(p++) != '.' ) ) return 0;
+ ip = (ip << 8) | val;
+ }
+ if ( *p == '\0' ) {
+ inp->s_addr = htonl(ip);
+ return 1;
+ }
+ return 0;
+}
+
+unsigned long strtoul ( const char *p, char **endp, int base ) {
+ unsigned long ret = 0;
+ unsigned int charval;
+
+ while ( isspace ( *p ) )
+ p++;
+
+ if ( base == 0 ) {
+ base = 10;
+ if ( *p == '0' ) {
+ p++;
+ base = 8;
+ if ( ( *p | 0x20 ) == 'x' ) {
+ p++;
+ base = 16;
+ }
+ }
+ }
+
+ while ( 1 ) {
+ charval = *p;
+ if ( charval >= 'a' ) {
+ charval = ( charval - 'a' + 10 );
+ } else if ( charval >= 'A' ) {
+ charval = ( charval - 'A' + 10 );
+ } else if ( charval <= '9' ) {
+ charval = ( charval - '0' );
+ }
+ if ( charval >= ( unsigned int ) base )
+ break;
+ ret = ( ( ret * base ) + charval );
+ p++;
+ }
+
+ if ( endp )
+ *endp = ( char * ) p;
+
+ return ( ret );
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/core/nvo.c b/debian/grub-extras/disabled/gpxe/src/core/nvo.c
new file mode 100644
index 0000000..3dbf51d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/nvo.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/nvs.h>
+#include <gpxe/nvo.h>
+
+/** @file
+ *
+ * Non-volatile stored options
+ *
+ */
+
+/**
+ * Calculate checksum over non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ * @ret sum Checksum
+ */
+static unsigned int nvo_checksum ( struct nvo_block *nvo ) {
+ uint8_t *data = nvo->data;
+ uint8_t sum = 0;
+ unsigned int i;
+
+ for ( i = 0 ; i < nvo->total_len ; i++ ) {
+ sum += *(data++);
+ }
+ return sum;
+}
+
+/**
+ * Load non-volatile stored options from non-volatile storage device
+ *
+ * @v nvo Non-volatile options block
+ * @ret rc Return status code
+ */
+static int nvo_load ( struct nvo_block *nvo ) {
+ void *data = nvo->data;
+ struct nvo_fragment *frag;
+ int rc;
+
+ /* Read data a fragment at a time */
+ for ( frag = nvo->fragments ; frag->len ; frag++ ) {
+ if ( ( rc = nvs_read ( nvo->nvs, frag->address, data,
+ frag->len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not read %zd bytes at "
+ "%#04x\n", nvo, frag->len, frag->address );
+ return rc;
+ }
+ data += frag->len;
+ }
+
+ DBGC ( nvo, "NVO %p loaded from non-volatile storage\n", nvo );
+ return 0;
+}
+
+/**
+ * Save non-volatile stored options back to non-volatile storage device
+ *
+ * @v nvo Non-volatile options block
+ * @ret rc Return status code
+ */
+static int nvo_save ( struct nvo_block *nvo ) {
+ void *data = nvo->data;
+ uint8_t *checksum = data;
+ struct nvo_fragment *frag;
+ int rc;
+
+ /* Recalculate checksum */
+ *checksum -= nvo_checksum ( nvo );
+
+ /* Write data a fragment at a time */
+ for ( frag = nvo->fragments ; frag->len ; frag++ ) {
+ if ( ( rc = nvs_write ( nvo->nvs, frag->address, data,
+ frag->len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not write %zd bytes at "
+ "%#04x\n", nvo, frag->len, frag->address );
+ return rc;
+ }
+ data += frag->len;
+ }
+
+ DBGC ( nvo, "NVO %p saved to non-volatile storage\n", nvo );
+ return 0;
+}
+
+/**
+ * Parse stored options
+ *
+ * @v nvo Non-volatile options block
+ *
+ * Verifies that the options data is valid, and configures the DHCP
+ * options block. If the data is not valid, it is replaced with an
+ * empty options block.
+ */
+static void nvo_init_dhcpopts ( struct nvo_block *nvo ) {
+ uint8_t *options_data;
+ size_t options_len;
+
+ /* Steal one byte for the checksum */
+ options_data = ( nvo->data + 1 );
+ options_len = ( nvo->total_len - 1 );
+
+ /* If checksum fails, or options data starts with a zero,
+ * assume the whole block is invalid. This should capture the
+ * case of random initial contents.
+ */
+ if ( ( nvo_checksum ( nvo ) != 0 ) || ( options_data[0] == 0 ) ) {
+ DBGC ( nvo, "NVO %p has checksum %02x and initial byte %02x; "
+ "assuming empty\n", nvo, nvo_checksum ( nvo ),
+ options_data[0] );
+ memset ( nvo->data, 0, nvo->total_len );
+ }
+
+ dhcpopt_init ( &nvo->dhcpopts, options_data, options_len );
+}
+
+/**
+ * Store value of NVO setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int nvo_store ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ struct nvo_block *nvo =
+ container_of ( settings, struct nvo_block, settings );
+ int rc;
+
+ /* Update stored options */
+ if ( ( rc = dhcpopt_store ( &nvo->dhcpopts, setting->tag,
+ data, len ) ) != 0 ) {
+ DBGC ( nvo, "NVO %p could not store %zd bytes: %s\n",
+ nvo, len, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Save updated options to NVS */
+ if ( ( rc = nvo_save ( nvo ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Fetch value of NVO setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+static int nvo_fetch ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct nvo_block *nvo =
+ container_of ( settings, struct nvo_block, settings );
+
+ return dhcpopt_fetch ( &nvo->dhcpopts, setting->tag, data, len );
+}
+
+/** NVO settings operations */
+static struct settings_operations nvo_settings_operations = {
+ .store = nvo_store,
+ .fetch = nvo_fetch,
+};
+
+/**
+ * Initialise non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ * @v nvs Underlying non-volatile storage device
+ * @v fragments List of option-containing fragments
+ * @v refcnt Containing object reference counter, or NULL
+ */
+void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
+ struct nvo_fragment *fragments, struct refcnt *refcnt ) {
+ nvo->nvs = nvs;
+ nvo->fragments = fragments;
+ settings_init ( &nvo->settings, &nvo_settings_operations, refcnt,
+ "nvo", 0 );
+}
+
+/**
+ * Register non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ * @v parent Parent settings block, or NULL
+ * @ret rc Return status code
+ */
+int register_nvo ( struct nvo_block *nvo, struct settings *parent ) {
+ struct nvo_fragment *fragment = nvo->fragments;
+ int rc;
+
+ /* Calculate total length of all fragments */
+ for ( fragment = nvo->fragments ; fragment->len ; fragment++ )
+ nvo->total_len += fragment->len;
+
+ /* Allocate memory for options and read in from NVS */
+ nvo->data = malloc ( nvo->total_len );
+ if ( ! nvo->data ) {
+ DBGC ( nvo, "NVO %p could not allocate %zd bytes\n",
+ nvo, nvo->total_len );
+ rc = -ENOMEM;
+ goto err_malloc;
+ }
+ if ( ( rc = nvo_load ( nvo ) ) != 0 )
+ goto err_load;
+
+ /* Verify and register options */
+ nvo_init_dhcpopts ( nvo );
+ if ( ( rc = register_settings ( &nvo->settings, parent ) ) != 0 )
+ goto err_register;
+
+ DBGC ( nvo, "NVO %p registered\n", nvo );
+ return 0;
+
+ err_register:
+ err_load:
+ free ( nvo->data );
+ nvo->data = NULL;
+ err_malloc:
+ return rc;
+}
+
+/**
+ * Unregister non-volatile stored options
+ *
+ * @v nvo Non-volatile options block
+ */
+void unregister_nvo ( struct nvo_block *nvo ) {
+ unregister_settings ( &nvo->settings );
+ free ( nvo->data );
+ nvo->data = NULL;
+ DBGC ( nvo, "NVO %p unregistered\n", nvo );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/open.c b/debian/grub-extras/disabled/gpxe/src/core/open.c
new file mode 100644
index 0000000..70b427b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/open.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/xfer.h>
+#include <gpxe/uri.h>
+#include <gpxe/socket.h>
+#include <gpxe/open.h>
+
+/** @file
+ *
+ * Data transfer interface opening
+ *
+ */
+
+/**
+ * Open URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ *
+ * The URI will be regarded as being relative to the current working
+ * URI (see churi()).
+ */
+int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
+ struct uri_opener *opener;
+ struct uri *resolved_uri;
+ int rc = -ENOTSUP;
+
+ /* Resolve URI */
+ resolved_uri = resolve_uri ( cwuri, uri );
+ if ( ! resolved_uri )
+ return -ENOMEM;
+
+ /* Find opener which supports this URI scheme */
+ for_each_table_entry ( opener, URI_OPENERS ) {
+ if ( strcmp ( resolved_uri->scheme, opener->scheme ) == 0 ) {
+ DBGC ( xfer, "XFER %p opening %s URI\n",
+ xfer, opener->scheme );
+ rc = opener->open ( xfer, resolved_uri );
+ goto done;
+ }
+ }
+ DBGC ( xfer, "XFER %p attempted to open unsupported URI scheme "
+ "\"%s\"\n", xfer, resolved_uri->scheme );
+
+ done:
+ uri_put ( resolved_uri );
+ return rc;
+}
+
+/**
+ * Open URI string
+ *
+ * @v xfer Data transfer interface
+ * @v uri_string URI string (e.g. "http://etherboot.org/kernel")
+ * @ret rc Return status code
+ *
+ * The URI will be regarded as being relative to the current working
+ * URI (see churi()).
+ */
+int xfer_open_uri_string ( struct xfer_interface *xfer,
+ const char *uri_string ) {
+ struct uri *uri;
+ int rc;
+
+ DBGC ( xfer, "XFER %p opening URI %s\n", xfer, uri_string );
+
+ uri = parse_uri ( uri_string );
+ if ( ! uri )
+ return -ENOMEM;
+
+ rc = xfer_open_uri ( xfer, uri );
+
+ uri_put ( uri );
+ return rc;
+}
+
+/**
+ * Open socket
+ *
+ * @v xfer Data transfer interface
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
+ struct sockaddr *peer, struct sockaddr *local ) {
+ struct socket_opener *opener;
+
+ DBGC ( xfer, "XFER %p opening (%s,%s) socket\n", xfer,
+ socket_semantics_name ( semantics ),
+ socket_family_name ( peer->sa_family ) );
+
+ for_each_table_entry ( opener, SOCKET_OPENERS ) {
+ if ( ( opener->semantics == semantics ) &&
+ ( opener->family == peer->sa_family ) ) {
+ return opener->open ( xfer, peer, local );
+ }
+ }
+
+ DBGC ( xfer, "XFER %p attempted to open unsupported socket type "
+ "(%s,%s)\n", xfer, socket_semantics_name ( semantics ),
+ socket_family_name ( peer->sa_family ) );
+ return -ENOTSUP;
+}
+
+/**
+ * Open location
+ *
+ * @v xfer Data transfer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args ) {
+ switch ( type ) {
+ case LOCATION_URI_STRING: {
+ const char *uri_string = va_arg ( args, const char * );
+
+ return xfer_open_uri_string ( xfer, uri_string ); }
+ case LOCATION_URI: {
+ struct uri *uri = va_arg ( args, struct uri * );
+
+ return xfer_open_uri ( xfer, uri ); }
+ case LOCATION_SOCKET: {
+ int semantics = va_arg ( args, int );
+ struct sockaddr *peer = va_arg ( args, struct sockaddr * );
+ struct sockaddr *local = va_arg ( args, struct sockaddr * );
+
+ return xfer_open_socket ( xfer, semantics, peer, local ); }
+ default:
+ DBGC ( xfer, "XFER %p attempted to open unsupported location "
+ "type %d\n", xfer, type );
+ return -ENOTSUP;
+ }
+}
+
+/**
+ * Open location
+ *
+ * @v xfer Data transfer interface
+ * @v type Location type
+ * @v ... Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_open ( struct xfer_interface *xfer, int type, ... ) {
+ va_list args;
+ int rc;
+
+ va_start ( args, type );
+ rc = xfer_vopen ( xfer, type, args );
+ va_end ( args );
+ return rc;
+}
+
+/**
+ * Reopen location
+ *
+ * @v xfer Data transfer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ *
+ * This will close the existing connection and open a new connection
+ * using xfer_vopen(). It is intended to be used as a .vredirect
+ * method handler.
+ */
+int xfer_vreopen ( struct xfer_interface *xfer, int type, va_list args ) {
+
+ /* Close existing connection */
+ xfer_close ( xfer, 0 );
+
+ /* Open new location */
+ return xfer_vopen ( xfer, type, args );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/process.c b/debian/grub-extras/disabled/gpxe/src/core/process.c
new file mode 100644
index 0000000..9c13e02
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/process.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/list.h>
+#include <gpxe/init.h>
+#include <gpxe/process.h>
+
+/** @file
+ *
+ * Processes
+ *
+ * We implement a trivial form of cooperative multitasking, in which
+ * all processes share a single stack and address space.
+ */
+
+/** Process run queue */
+static LIST_HEAD ( run_queue );
+
+/**
+ * Add process to process list
+ *
+ * @v process Process
+ *
+ * It is safe to call process_add() multiple times; further calls will
+ * have no effect.
+ */
+void process_add ( struct process *process ) {
+ if ( list_empty ( &process->list ) ) {
+ DBGC ( process, "PROCESS %p starting\n", process );
+ ref_get ( process->refcnt );
+ list_add_tail ( &process->list, &run_queue );
+ } else {
+ DBGC ( process, "PROCESS %p already started\n", process );
+ }
+}
+
+/**
+ * Remove process from process list
+ *
+ * @v process Process
+ *
+ * It is safe to call process_del() multiple times; further calls will
+ * have no effect.
+ */
+void process_del ( struct process *process ) {
+ if ( ! list_empty ( &process->list ) ) {
+ DBGC ( process, "PROCESS %p stopping\n", process );
+ list_del ( &process->list );
+ INIT_LIST_HEAD ( &process->list );
+ ref_put ( process->refcnt );
+ } else {
+ DBGC ( process, "PROCESS %p already stopped\n", process );
+ }
+}
+
+/**
+ * Single-step a single process
+ *
+ * This executes a single step of the first process in the run queue,
+ * and moves the process to the end of the run queue.
+ */
+void step ( void ) {
+ struct process *process;
+
+ list_for_each_entry ( process, &run_queue, list ) {
+ list_del ( &process->list );
+ list_add_tail ( &process->list, &run_queue );
+ DBGC2 ( process, "PROCESS %p executing\n", process );
+ process->step ( process );
+ DBGC2 ( process, "PROCESS %p finished executing\n", process );
+ break;
+ }
+}
+
+/**
+ * Initialise processes
+ *
+ */
+static void init_processes ( void ) {
+ struct process *process;
+
+ for_each_table_entry ( process, PERMANENT_PROCESSES )
+ process_add ( process );
+}
+
+/** Process initialiser */
+struct init_fn process_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = init_processes,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/core/random.c b/debian/grub-extras/disabled/gpxe/src/core/random.c
new file mode 100644
index 0000000..6e7374e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/random.c
@@ -0,0 +1,41 @@
+/** @file
+ *
+ * Random number generation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <gpxe/timer.h>
+
+static int32_t rnd_seed = 0;
+
+/**
+ * Seed the pseudo-random number generator
+ *
+ * @v seed Seed value
+ */
+void srandom ( unsigned int seed ) {
+ rnd_seed = seed;
+}
+
+/**
+ * Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
+ *
+ * @ret rand Pseudo-random number
+ */
+long int random ( void ) {
+ int32_t q;
+
+ if ( ! rnd_seed ) /* Initialize linear congruential generator */
+ srandom ( currticks() );
+
+ /* simplified version of the LCG given in Bruce Schneier's
+ "Applied Cryptography" */
+ q = ( rnd_seed / 53668 );
+ rnd_seed = ( 40014 * ( rnd_seed - 53668 * q ) - 12211 * q );
+ if ( rnd_seed < 0 )
+ rnd_seed += 2147483563L;
+ return rnd_seed;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/refcnt.c b/debian/grub-extras/disabled/gpxe/src/core/refcnt.c
new file mode 100644
index 0000000..f2286ca
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/refcnt.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <gpxe/refcnt.h>
+
+/** @file
+ *
+ * Reference counting
+ *
+ */
+
+/**
+ * Increment reference count
+ *
+ * @v refcnt Reference counter, or NULL
+ * @ret refcnt Reference counter
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+struct refcnt * ref_get ( struct refcnt *refcnt ) {
+
+ if ( refcnt ) {
+ refcnt->refcnt++;
+ DBGC2 ( refcnt, "REFCNT %p incremented to %d\n",
+ refcnt, refcnt->refcnt );
+ }
+ return refcnt;
+}
+
+/**
+ * Decrement reference count
+ *
+ * @v refcnt Reference counter, or NULL
+ *
+ * If the reference count decreases below zero, the object's free()
+ * method will be called.
+ *
+ * If @c refcnt is NULL, no action is taken.
+ */
+void ref_put ( struct refcnt *refcnt ) {
+
+ if ( ! refcnt )
+ return;
+
+ refcnt->refcnt--;
+ DBGC2 ( refcnt, "REFCNT %p decremented to %d\n",
+ refcnt, refcnt->refcnt );
+
+ if ( refcnt->refcnt >= 0 )
+ return;
+
+ if ( refcnt->free ) {
+ DBGC ( refcnt, "REFCNT %p being freed via method %p\n",
+ refcnt, refcnt->free );
+ refcnt->free ( refcnt );
+ } else {
+ DBGC ( refcnt, "REFCNT %p being freed\n", refcnt );
+ free ( refcnt );
+ }
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/resolv.c b/debian/grub-extras/disabled/gpxe/src/core/resolv.c
new file mode 100644
index 0000000..6f01f93
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/resolv.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/in.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/process.h>
+#include <gpxe/resolv.h>
+
+/** @file
+ *
+ * Name resolution
+ *
+ */
+
+/***************************************************************************
+ *
+ * Name resolution interfaces
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Name resolution completed
+ *
+ * @v resolv Name resolution interface
+ * @v sa Completed socket address (if successful)
+ * @v rc Final status code
+ */
+void resolv_done ( struct resolv_interface *resolv, struct sockaddr *sa,
+ int rc ) {
+ struct resolv_interface *dest = resolv_get_dest ( resolv );
+
+ resolv_unplug ( resolv );
+ dest->op->done ( dest, sa, rc );
+ resolv_put ( dest );
+}
+
+/**
+ * Ignore name resolution done() event
+ *
+ * @v resolv Name resolution interface
+ * @v sa Completed socket address (if successful)
+ * @v rc Final status code
+ */
+void ignore_resolv_done ( struct resolv_interface *resolv __unused,
+ struct sockaddr *sa __unused, int rc __unused ) {
+ /* Do nothing */
+}
+
+/** Null name resolution interface operations */
+struct resolv_interface_operations null_resolv_ops = {
+ .done = ignore_resolv_done,
+};
+
+/** Null name resolution interface */
+struct resolv_interface null_resolv = {
+ .intf = {
+ .dest = &null_resolv.intf,
+ .refcnt = NULL,
+ },
+ .op = &null_resolv_ops,
+};
+
+/***************************************************************************
+ *
+ * Numeric name resolver
+ *
+ ***************************************************************************
+ */
+
+/** A numeric name resolver */
+struct numeric_resolv {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Name resolution interface */
+ struct resolv_interface resolv;
+ /** Process */
+ struct process process;
+ /** Completed socket address */
+ struct sockaddr sa;
+ /** Overall status code */
+ int rc;
+};
+
+static void numeric_step ( struct process *process ) {
+ struct numeric_resolv *numeric =
+ container_of ( process, struct numeric_resolv, process );
+
+ resolv_done ( &numeric->resolv, &numeric->sa, numeric->rc );
+ process_del ( process );
+}
+
+static int numeric_resolv ( struct resolv_interface *resolv,
+ const char *name, struct sockaddr *sa ) {
+ struct numeric_resolv *numeric;
+ struct sockaddr_in *sin;
+
+ /* Allocate and initialise structure */
+ numeric = zalloc ( sizeof ( *numeric ) );
+ if ( ! numeric )
+ return -ENOMEM;
+ resolv_init ( &numeric->resolv, &null_resolv_ops, &numeric->refcnt );
+ process_init ( &numeric->process, numeric_step, &numeric->refcnt );
+ memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) );
+
+ DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n",
+ numeric, name );
+
+ /* Attempt to resolve name */
+ sin = ( ( struct sockaddr_in * ) &numeric->sa );
+ sin->sin_family = AF_INET;
+ if ( inet_aton ( name, &sin->sin_addr ) == 0 )
+ numeric->rc = -EINVAL;
+
+ /* Attach to parent interface, mortalise self, and return */
+ resolv_plug_plug ( &numeric->resolv, resolv );
+ ref_put ( &numeric->refcnt );
+ return 0;
+}
+
+struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
+ .name = "NUMERIC",
+ .resolv = numeric_resolv,
+};
+
+/***************************************************************************
+ *
+ * Name resolution multiplexer
+ *
+ ***************************************************************************
+ */
+
+/** A name resolution multiplexer */
+struct resolv_mux {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Parent name resolution interface */
+ struct resolv_interface parent;
+
+ /** Child name resolution interface */
+ struct resolv_interface child;
+ /** Current child resolver */
+ struct resolver *resolver;
+
+ /** Socket address to complete */
+ struct sockaddr sa;
+ /** Name to be resolved
+ *
+ * Must be at end of structure
+ */
+ char name[0];
+};
+
+/**
+ * Try current child name resolver
+ *
+ * @v mux Name resolution multiplexer
+ * @ret rc Return status code
+ */
+static int resolv_mux_try ( struct resolv_mux *mux ) {
+ struct resolver *resolver = mux->resolver;
+ int rc;
+
+ DBGC ( mux, "RESOLV %p trying method %s\n", mux, resolver->name );
+
+ if ( ( rc = resolver->resolv ( &mux->child, mux->name,
+ &mux->sa ) ) != 0 ) {
+ DBGC ( mux, "RESOLV %p could not use method %s: %s\n",
+ mux, resolver->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle done() event from child name resolver
+ *
+ * @v resolv Child name resolution interface
+ * @v sa Completed socket address (if successful)
+ * @v rc Final status code
+ */
+static void resolv_mux_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc ) {
+ struct resolv_mux *mux =
+ container_of ( resolv, struct resolv_mux, child );
+
+ /* Unplug child */
+ resolv_unplug ( &mux->child );
+
+ /* If this resolution succeeded, stop now */
+ if ( rc == 0 ) {
+ DBGC ( mux, "RESOLV %p succeeded using method %s\n",
+ mux, mux->resolver->name );
+ goto finished;
+ }
+
+ /* Attempt next child resolver, if possible */
+ mux->resolver++;
+ if ( mux->resolver >= table_end ( RESOLVERS ) ) {
+ DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
+ goto finished;
+ }
+ if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
+ goto finished;
+
+ /* Next resolver is now running */
+ return;
+
+ finished:
+ resolv_done ( &mux->parent, sa, rc );
+}
+
+/** Name resolution multiplexer operations */
+static struct resolv_interface_operations resolv_mux_child_ops = {
+ .done = resolv_mux_done,
+};
+
+/**
+ * Start name resolution
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to complete
+ * @ret rc Return status code
+ */
+int resolv ( struct resolv_interface *resolv, const char *name,
+ struct sockaddr *sa ) {
+ struct resolv_mux *mux;
+ size_t name_len = ( strlen ( name ) + 1 );
+ int rc;
+
+ /* Allocate and initialise structure */
+ mux = zalloc ( sizeof ( *mux ) + name_len );
+ if ( ! mux )
+ return -ENOMEM;
+ resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt );
+ resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt );
+ mux->resolver = table_start ( RESOLVERS );
+ memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
+ memcpy ( mux->name, name, name_len );
+
+ DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name );
+
+ /* Start first resolver in chain. There will always be at
+ * least one resolver (the numeric resolver), so no need to
+ * check for the zero-resolvers-available case.
+ */
+ if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
+ goto err;
+
+ /* Attach parent interface, mortalise self, and return */
+ resolv_plug_plug ( &mux->parent, resolv );
+ ref_put ( &mux->refcnt );
+ return 0;
+
+ err:
+ ref_put ( &mux->refcnt );
+ return rc;
+}
+
+/***************************************************************************
+ *
+ * Named socket opening
+ *
+ ***************************************************************************
+ */
+
+/** A named socket */
+struct named_socket {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+ /** Name resolution interface */
+ struct resolv_interface resolv;
+ /** Communication semantics (e.g. SOCK_STREAM) */
+ int semantics;
+ /** Stored local socket address, if applicable */
+ struct sockaddr local;
+ /** Stored local socket address exists */
+ int have_local;
+};
+
+/**
+ * Finish using named socket
+ *
+ * @v named Named socket
+ * @v rc Reason for finish
+ */
+static void named_done ( struct named_socket *named, int rc ) {
+
+ /* Close all interfaces */
+ resolv_nullify ( &named->resolv );
+ xfer_nullify ( &named->xfer );
+ xfer_close ( &named->xfer, rc );
+}
+
+/**
+ * Handle close() event
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void named_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct named_socket *named =
+ container_of ( xfer, struct named_socket, xfer );
+
+ named_done ( named, rc );
+}
+
+/** Named socket opener data transfer interface operations */
+static struct xfer_interface_operations named_xfer_ops = {
+ .close = named_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = no_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = ignore_xfer_deliver_raw,
+};
+
+/**
+ * Handle done() event
+ *
+ * @v resolv Name resolution interface
+ * @v sa Completed socket address (if successful)
+ * @v rc Final status code
+ */
+static void named_resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc ) {
+ struct named_socket *named =
+ container_of ( resolv, struct named_socket, resolv );
+
+ /* Redirect if name resolution was successful */
+ if ( rc == 0 ) {
+ rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
+ named->semantics, sa,
+ ( named->have_local ?
+ &named->local : NULL ) );
+ }
+
+ /* Terminate resolution */
+ named_done ( named, rc );
+}
+
+/** Named socket opener name resolution interface operations */
+static struct resolv_interface_operations named_resolv_ops = {
+ .done = named_resolv_done,
+};
+
+/**
+ * Open named socket
+ *
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @v peer Peer socket address to complete
+ * @v name Name to resolve
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+int xfer_open_named_socket ( struct xfer_interface *xfer, int semantics,
+ struct sockaddr *peer, const char *name,
+ struct sockaddr *local ) {
+ struct named_socket *named;
+ int rc;
+
+ /* Allocate and initialise structure */
+ named = zalloc ( sizeof ( *named ) );
+ if ( ! named )
+ return -ENOMEM;
+ xfer_init ( &named->xfer, &named_xfer_ops, &named->refcnt );
+ resolv_init ( &named->resolv, &named_resolv_ops, &named->refcnt );
+ named->semantics = semantics;
+ if ( local ) {
+ memcpy ( &named->local, local, sizeof ( named->local ) );
+ named->have_local = 1;
+ }
+
+ DBGC ( named, "RESOLV %p opening named socket \"%s\"\n",
+ named, name );
+
+ /* Start name resolution */
+ if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 )
+ goto err;
+
+ /* Attach parent interface, mortalise self, and return */
+ xfer_plug_plug ( &named->xfer, xfer );
+ ref_put ( &named->refcnt );
+ return 0;
+
+ err:
+ ref_put ( &named->refcnt );
+ return rc;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/settings.c b/debian/grub-extras/disabled/gpxe/src/core/settings.c
new file mode 100644
index 0000000..87d84a0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/settings.c
@@ -0,0 +1,1447 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/in.h>
+#include <gpxe/vsprintf.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/uuid.h>
+#include <gpxe/uri.h>
+#include <gpxe/settings.h>
+
+/** @file
+ *
+ * Configuration settings
+ *
+ */
+
+/******************************************************************************
+ *
+ * Generic settings blocks
+ *
+ ******************************************************************************
+ */
+
+/**
+ * A generic setting
+ *
+ */
+struct generic_setting {
+ /** List of generic settings */
+ struct list_head list;
+ /** Setting */
+ struct setting setting;
+ /** Size of setting name */
+ size_t name_len;
+ /** Size of setting data */
+ size_t data_len;
+};
+
+/**
+ * Get generic setting name
+ *
+ * @v generic Generic setting
+ * @ret name Generic setting name
+ */
+static inline void * generic_setting_name ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) );
+}
+
+/**
+ * Get generic setting data
+ *
+ * @v generic Generic setting
+ * @ret data Generic setting data
+ */
+static inline void * generic_setting_data ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) +
+ generic->name_len );
+}
+
+/**
+ * Find generic setting
+ *
+ * @v generics Generic settings block
+ * @v setting Setting to find
+ * @ret generic Generic setting, or NULL
+ */
+static struct generic_setting *
+find_generic_setting ( struct generic_settings *generics,
+ struct setting *setting ) {
+ struct generic_setting *generic;
+
+ list_for_each_entry ( generic, &generics->list, list ) {
+ if ( setting_cmp ( &generic->setting, setting ) == 0 )
+ return generic;
+ }
+ return NULL;
+}
+
+/**
+ * Store value of generic setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int generic_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *old;
+ struct generic_setting *new = NULL;
+ size_t name_len;
+
+ /* Identify existing generic setting, if any */
+ old = find_generic_setting ( generics, setting );
+
+ /* Create new generic setting, if required */
+ if ( len ) {
+ /* Allocate new generic setting */
+ name_len = ( strlen ( setting->name ) + 1 );
+ new = zalloc ( sizeof ( *new ) + name_len + len );
+ if ( ! new )
+ return -ENOMEM;
+
+ /* Populate new generic setting */
+ new->name_len = name_len;
+ new->data_len = len;
+ memcpy ( &new->setting, setting, sizeof ( new->setting ) );
+ new->setting.name = generic_setting_name ( new );
+ memcpy ( generic_setting_name ( new ),
+ setting->name, name_len );
+ memcpy ( generic_setting_data ( new ), data, len );
+ }
+
+ /* Delete existing generic setting, if any */
+ if ( old ) {
+ list_del ( &old->list );
+ free ( old );
+ }
+
+ /* Add new setting to list, if any */
+ if ( new )
+ list_add ( &new->list, &generics->list );
+
+ return 0;
+}
+
+/**
+ * Fetch value of generic setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+int generic_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+
+ /* Find generic setting */
+ generic = find_generic_setting ( generics, setting );
+ if ( ! generic )
+ return -ENOENT;
+
+ /* Copy out generic setting data */
+ if ( len > generic->data_len )
+ len = generic->data_len;
+ memcpy ( data, generic_setting_data ( generic ), len );
+ return generic->data_len;
+}
+
+/**
+ * Clear generic settings block
+ *
+ * @v settings Settings block
+ */
+void generic_settings_clear ( struct settings *settings ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+ struct generic_setting *tmp;
+
+ list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
+ list_del ( &generic->list );
+ free ( generic );
+ }
+ assert ( list_empty ( &generics->list ) );
+}
+
+/** Generic settings operations */
+struct settings_operations generic_settings_operations = {
+ .store = generic_settings_store,
+ .fetch = generic_settings_fetch,
+ .clear = generic_settings_clear,
+};
+
+/******************************************************************************
+ *
+ * Registered settings blocks
+ *
+ ******************************************************************************
+ */
+
+/** Root generic settings block */
+struct generic_settings generic_settings_root = {
+ .settings = {
+ .refcnt = NULL,
+ .name = "",
+ .siblings =
+ LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
+ .children =
+ LIST_HEAD_INIT ( generic_settings_root.settings.children ),
+ .op = &generic_settings_operations,
+ },
+ .list = LIST_HEAD_INIT ( generic_settings_root.list ),
+};
+
+/** Root settings block */
+#define settings_root generic_settings_root.settings
+
+/**
+ * Find child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * find_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct settings *settings;
+
+ /* Treat empty name as meaning "this block" */
+ if ( ! *name )
+ return parent;
+
+ /* Look for child with matching name */
+ list_for_each_entry ( settings, &parent->children, siblings ) {
+ if ( strcmp ( settings->name, name ) == 0 )
+ return settings;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find or create child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * autovivify_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct {
+ struct generic_settings generic;
+ char name[ strlen ( name ) + 1 /* NUL */ ];
+ } *new_child;
+ struct settings *settings;
+
+ /* Return existing settings, if existent */
+ if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
+ return settings;
+
+ /* Create new generic settings block */
+ new_child = zalloc ( sizeof ( *new_child ) );
+ if ( ! new_child ) {
+ DBGC ( parent, "Settings %p could not create child %s\n",
+ parent, name );
+ return NULL;
+ }
+ memcpy ( new_child->name, name, sizeof ( new_child->name ) );
+ generic_settings_init ( &new_child->generic, NULL, new_child->name );
+ settings = &new_child->generic.settings;
+ register_settings ( settings, parent );
+ return settings;
+}
+
+/**
+ * Return settings block name (for debug only)
+ *
+ * @v settings Settings block
+ * @ret name Settings block name
+ */
+static const char * settings_name ( struct settings *settings ) {
+ static char buf[64];
+ char tmp[ sizeof ( buf ) ];
+ int count;
+
+ for ( count = 0 ; settings ; settings = settings->parent ) {
+ memcpy ( tmp, buf, sizeof ( tmp ) );
+ snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
+ ( count++ ? '.' : '\0' ), tmp );
+ }
+ return ( buf + 1 );
+}
+
+/**
+ * Parse settings block name
+ *
+ * @v name Name
+ * @v get_child Function to find or create child settings block
+ * @ret settings Settings block, or NULL
+ */
+static struct settings *
+parse_settings_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ) ) {
+ struct settings *settings = &settings_root;
+ char name_copy[ strlen ( name ) + 1 ];
+ char *subname;
+ char *remainder;
+
+ /* Create modifiable copy of name */
+ memcpy ( name_copy, name, sizeof ( name_copy ) );
+ remainder = name_copy;
+
+ /* Parse each name component in turn */
+ while ( remainder ) {
+ subname = remainder;
+ remainder = strchr ( subname, '.' );
+ if ( remainder )
+ *(remainder++) = '\0';
+ settings = get_child ( settings, subname );
+ if ( ! settings )
+ break;
+ }
+
+ return settings;
+}
+
+/**
+ * Find named settings block
+ *
+ * @v name Name
+ * @ret settings Settings block, or NULL
+ */
+struct settings * find_settings ( const char *name ) {
+
+ return parse_settings_name ( name, find_child_settings );
+}
+
+/**
+ * Apply all settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_settings ( void ) {
+ struct settings_applicator *applicator;
+ int rc;
+
+ /* Call all settings applicators */
+ for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
+ if ( ( rc = applicator->apply() ) != 0 ) {
+ DBG ( "Could not apply settings using applicator "
+ "%p: %s\n", applicator, strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Reprioritise settings
+ *
+ * @v settings Settings block
+ *
+ * Reorders the settings block amongst its siblings according to its
+ * priority.
+ */
+static void reprioritise_settings ( struct settings *settings ) {
+ struct settings *parent = settings->parent;
+ long priority;
+ struct settings *tmp;
+ long tmp_priority;
+
+ /* Stop when we reach the top of the tree */
+ if ( ! parent )
+ return;
+
+ /* Read priority, if present */
+ priority = fetch_intz_setting ( settings, &priority_setting );
+
+ /* Remove from siblings list */
+ list_del ( &settings->siblings );
+
+ /* Reinsert after any existing blocks which have a higher priority */
+ list_for_each_entry ( tmp, &parent->children, siblings ) {
+ tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
+ if ( priority > tmp_priority )
+ break;
+ }
+ list_add_tail ( &settings->siblings, &tmp->siblings );
+
+ /* Recurse up the tree */
+ reprioritise_settings ( parent );
+}
+
+/**
+ * Register settings block
+ *
+ * @v settings Settings block
+ * @v parent Parent settings block, or NULL
+ * @ret rc Return status code
+ */
+int register_settings ( struct settings *settings, struct settings *parent ) {
+ struct settings *old_settings;
+
+ /* NULL parent => add to settings root */
+ assert ( settings != NULL );
+ if ( parent == NULL )
+ parent = &settings_root;
+
+ /* Remove any existing settings with the same name */
+ if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
+ unregister_settings ( old_settings );
+
+ /* Add to list of settings */
+ ref_get ( settings->refcnt );
+ ref_get ( parent->refcnt );
+ settings->parent = parent;
+ list_add_tail ( &settings->siblings, &parent->children );
+ DBGC ( settings, "Settings %p (\"%s\") registered\n",
+ settings, settings_name ( settings ) );
+
+ /* Fix up settings priority */
+ reprioritise_settings ( settings );
+
+ /* Apply potentially-updated settings */
+ apply_settings();
+
+ return 0;
+}
+
+/**
+ * Unregister settings block
+ *
+ * @v settings Settings block
+ */
+void unregister_settings ( struct settings *settings ) {
+
+ DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
+ settings, settings_name ( settings ) );
+
+ /* Remove from list of settings */
+ ref_put ( settings->refcnt );
+ ref_put ( settings->parent->refcnt );
+ settings->parent = NULL;
+ list_del ( &settings->siblings );
+
+ /* Apply potentially-updated settings */
+ apply_settings();
+}
+
+/******************************************************************************
+ *
+ * Core settings routines
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Store value of setting
+ *
+ * @v settings Settings block, or NULL
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int store_setting ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ int rc;
+
+ /* NULL settings implies storing into the global settings root */
+ if ( ! settings )
+ settings = &settings_root;
+
+ /* Sanity check */
+ if ( ! settings->op->store )
+ return -ENOTSUP;
+
+ /* Store setting */
+ if ( ( rc = settings->op->store ( settings, setting,
+ data, len ) ) != 0 )
+ return rc;
+
+ /* Reprioritise settings if necessary */
+ if ( setting_cmp ( setting, &priority_setting ) == 0 )
+ reprioritise_settings ( settings );
+
+ /* If these settings are registered, apply potentially-updated
+ * settings
+ */
+ for ( ; settings ; settings = settings->parent ) {
+ if ( settings == &settings_root ) {
+ if ( ( rc = apply_settings() ) != 0 )
+ return rc;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Fetch value of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+int fetch_setting ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct settings *child;
+ int ret;
+
+ /* Avoid returning uninitialised data on error */
+ memset ( data, 0, len );
+
+ /* NULL settings implies starting at the global settings root */
+ if ( ! settings )
+ settings = &settings_root;
+
+ /* Sanity check */
+ if ( ! settings->op->fetch )
+ return -ENOTSUP;
+
+ /* Try this block first */
+ if ( ( ret = settings->op->fetch ( settings, setting,
+ data, len ) ) >= 0 )
+ return ret;
+
+ /* Recurse into each child block in turn */
+ list_for_each_entry ( child, &settings->children, siblings ) {
+ if ( ( ret = fetch_setting ( child, setting,
+ data, len ) ) >= 0 )
+ return ret;
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * Fetch length of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret len Length of setting data, or negative error
+ *
+ * This function can also be used as an existence check for the
+ * setting.
+ */
+int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
+ return fetch_setting ( settings, setting, NULL, 0 );
+}
+
+/**
+ * Fetch value of string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting string data
+ * @v len Length of buffer
+ * @ret len Length of string setting, or negative error
+ *
+ * The resulting string is guaranteed to be correctly NUL-terminated.
+ * The returned length will be the length of the underlying setting
+ * data.
+ */
+int fetch_string_setting ( struct settings *settings, struct setting *setting,
+ char *data, size_t len ) {
+ memset ( data, 0, len );
+ return fetch_setting ( settings, setting, data,
+ ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
+}
+
+/**
+ * Fetch value of string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to allocate and fill with setting string data
+ * @ret len Length of string setting, or negative error
+ *
+ * The resulting string is guaranteed to be correctly NUL-terminated.
+ * The returned length will be the length of the underlying setting
+ * data. The caller is responsible for eventually freeing the
+ * allocated buffer.
+ */
+int fetch_string_setting_copy ( struct settings *settings,
+ struct setting *setting,
+ char **data ) {
+ int len;
+ int check_len = 0;
+
+ len = fetch_setting_len ( settings, setting );
+ if ( len < 0 )
+ return len;
+
+ *data = malloc ( len + 1 );
+ if ( ! *data )
+ return -ENOMEM;
+
+ check_len = fetch_string_setting ( settings, setting, *data,
+ ( len + 1 ) );
+ assert ( check_len == len );
+ return len;
+}
+
+/**
+ * Fetch value of IPv4 address setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v inp IPv4 address to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
+ struct in_addr *inp ) {
+ int len;
+
+ len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
+ if ( len < 0 )
+ return len;
+ if ( len < ( int ) sizeof ( *inp ) )
+ return -ERANGE;
+ return len;
+}
+
+/**
+ * Fetch value of signed integer setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v value Integer value to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_int_setting ( struct settings *settings, struct setting *setting,
+ long *value ) {
+ union {
+ uint8_t u8[ sizeof ( long ) ];
+ int8_t s8[ sizeof ( long ) ];
+ } buf;
+ int len;
+ int i;
+
+ /* Avoid returning uninitialised data on error */
+ *value = 0;
+
+ /* Fetch raw (network-ordered, variable-length) setting */
+ len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
+ if ( len < 0 )
+ return len;
+ if ( len > ( int ) sizeof ( buf ) )
+ return -ERANGE;
+
+ /* Convert to host-ordered signed long */
+ *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
+ for ( i = 0 ; i < len ; i++ ) {
+ *value = ( ( *value << 8 ) | buf.u8[i] );
+ }
+
+ return len;
+}
+
+/**
+ * Fetch value of unsigned integer setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v value Integer value to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_uint_setting ( struct settings *settings, struct setting *setting,
+ unsigned long *value ) {
+ long svalue;
+ int len;
+
+ /* Avoid returning uninitialised data on error */
+ *value = 0;
+
+ /* Fetch as a signed long */
+ len = fetch_int_setting ( settings, setting, &svalue );
+ if ( len < 0 )
+ return len;
+
+ /* Mask off sign-extended bits */
+ assert ( len <= ( int ) sizeof ( long ) );
+ *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
+
+ return len;
+}
+
+/**
+ * Fetch value of signed integer setting, or zero
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret value Setting value, or zero
+ */
+long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
+ long value;
+
+ fetch_int_setting ( settings, setting, &value );
+ return value;
+}
+
+/**
+ * Fetch value of unsigned integer setting, or zero
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret value Setting value, or zero
+ */
+unsigned long fetch_uintz_setting ( struct settings *settings,
+ struct setting *setting ) {
+ unsigned long value;
+
+ fetch_uint_setting ( settings, setting, &value );
+ return value;
+}
+
+/**
+ * Fetch value of UUID setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v uuid UUID to fill in
+ * @ret len Length of setting, or negative error
+ */
+int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
+ union uuid *uuid ) {
+ int len;
+
+ len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
+ if ( len < 0 )
+ return len;
+ if ( len != sizeof ( *uuid ) )
+ return -ERANGE;
+ return len;
+}
+
+/**
+ * Clear settings block
+ *
+ * @v settings Settings block
+ */
+void clear_settings ( struct settings *settings ) {
+ if ( settings->op->clear )
+ settings->op->clear ( settings );
+}
+
+/**
+ * Compare two settings
+ *
+ * @v a Setting to compare
+ * @v b Setting to compare
+ * @ret 0 Settings are the same
+ * @ret non-zero Settings are not the same
+ */
+int setting_cmp ( struct setting *a, struct setting *b ) {
+
+ /* If the settings have tags, compare them */
+ if ( a->tag && ( a->tag == b->tag ) )
+ return 0;
+
+ /* Otherwise, if the settings have names, compare them */
+ if ( a->name && b->name && a->name[0] )
+ return strcmp ( a->name, b->name );
+
+ /* Otherwise, return a non-match */
+ return ( ! 0 );
+}
+
+/******************************************************************************
+ *
+ * Formatted setting routines
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Store value of typed setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v type Settings type
+ * @v value Formatted setting data, or NULL
+ * @ret rc Return status code
+ */
+int storef_setting ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+
+ /* NULL value implies deletion. Avoid imposing the burden of
+ * checking for NULL values on each typed setting's storef()
+ * method.
+ */
+ if ( ! value )
+ return delete_setting ( settings, setting );
+
+ return setting->type->storef ( settings, setting, value );
+}
+
+/**
+ * Find named setting
+ *
+ * @v name Name
+ * @ret setting Named setting, or NULL
+ */
+static struct setting * find_setting ( const char *name ) {
+ struct setting *setting;
+
+ for_each_table_entry ( setting, SETTINGS ) {
+ if ( strcmp ( name, setting->name ) == 0 )
+ return setting;
+ }
+ return NULL;
+}
+
+/**
+ * Parse setting name as tag number
+ *
+ * @v name Name
+ * @ret tag Tag number, or 0 if not a valid number
+ */
+static unsigned int parse_setting_tag ( const char *name ) {
+ char *tmp = ( ( char * ) name );
+ unsigned int tag = 0;
+
+ while ( 1 ) {
+ tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
+ if ( *tmp == 0 )
+ return tag;
+ if ( *tmp != '.' )
+ return 0;
+ tmp++;
+ }
+}
+
+/**
+ * Find setting type
+ *
+ * @v name Name
+ * @ret type Setting type, or NULL
+ */
+static struct setting_type * find_setting_type ( const char *name ) {
+ struct setting_type *type;
+
+ for_each_table_entry ( type, SETTING_TYPES ) {
+ if ( strcmp ( name, type->name ) == 0 )
+ return type;
+ }
+ return NULL;
+}
+
+/**
+ * Parse setting name
+ *
+ * @v name Name of setting
+ * @v get_child Function to find or create child settings block
+ * @v settings Settings block to fill in
+ * @v setting Setting to fill in
+ * @v tmp_name Buffer for copy of setting name
+ * @ret rc Return status code
+ *
+ * Interprets a name of the form
+ * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
+ * fields.
+ *
+ * The @c tmp_name buffer must be large enough to hold a copy of the
+ * setting name.
+ */
+static int
+parse_setting_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ),
+ struct settings **settings, struct setting *setting,
+ char *tmp_name ) {
+ char *settings_name;
+ char *setting_name;
+ char *type_name;
+ struct setting *named_setting;
+
+ /* Set defaults */
+ *settings = &settings_root;
+ memset ( setting, 0, sizeof ( *setting ) );
+ setting->name = "";
+ setting->type = &setting_type_string;
+
+ /* Split name into "[settings_name/]setting_name[:type_name]" */
+ strcpy ( tmp_name, name );
+ if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
+ *(setting_name++) = 0;
+ settings_name = tmp_name;
+ } else {
+ setting_name = tmp_name;
+ settings_name = NULL;
+ }
+ if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
+ *(type_name++) = 0;
+
+ /* Identify settings block, if specified */
+ if ( settings_name ) {
+ *settings = parse_settings_name ( settings_name, get_child );
+ if ( *settings == NULL ) {
+ DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
+ settings_name, name );
+ return -ENODEV;
+ }
+ }
+
+ /* Identify setting */
+ if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
+ /* Matches a defined named setting; use that setting */
+ memcpy ( setting, named_setting, sizeof ( *setting ) );
+ } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
+ /* Is a valid numeric tag; use the tag */
+ setting->tag |= (*settings)->tag_magic;
+ } else {
+ /* Use the arbitrary name */
+ setting->name = setting_name;
+ }
+
+ /* Identify setting type, if specified */
+ if ( type_name ) {
+ setting->type = find_setting_type ( type_name );
+ if ( setting->type == NULL ) {
+ DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
+ type_name, name );
+ return -ENOTSUP;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Parse and store value of named setting
+ *
+ * @v name Name of setting
+ * @v value Formatted setting data, or NULL
+ * @ret rc Return status code
+ */
+int storef_named_setting ( const char *name, const char *value ) {
+ struct settings *settings;
+ struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
+ int rc;
+
+ if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
+ &settings, &setting, tmp_name )) != 0)
+ return rc;
+ return storef_setting ( settings, &setting, value );
+}
+
+/**
+ * Fetch and format value of named setting
+ *
+ * @v name Name of setting
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
+ struct settings *settings;
+ struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
+ int rc;
+
+ if ( ( rc = parse_setting_name ( name, find_child_settings,
+ &settings, &setting, tmp_name )) != 0)
+ return rc;
+ return fetchf_setting ( settings, &setting, buf, len );
+}
+
+/******************************************************************************
+ *
+ * Setting types
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Parse and store value of string setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+static int storef_string ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ return store_setting ( settings, setting, value, strlen ( value ) );
+}
+
+/**
+ * Fetch and format value of string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_string ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ return fetch_string_setting ( settings, setting, buf, len );
+}
+
+/** A string setting type */
+struct setting_type setting_type_string __setting_type = {
+ .name = "string",
+ .storef = storef_string,
+ .fetchf = fetchf_string,
+};
+
+/**
+ * Parse and store value of URI-encoded string setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+static int storef_uristring ( struct settings *settings,
+ struct setting *setting,
+ const char *value ) {
+ char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */
+ size_t len;
+
+ len = uri_decode ( value, buf, sizeof ( buf ) );
+ return store_setting ( settings, setting, buf, len );
+}
+
+/**
+ * Fetch and format value of URI-encoded string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_uristring ( struct settings *settings,
+ struct setting *setting,
+ char *buf, size_t len ) {
+ ssize_t raw_len;
+
+ /* We need to always retrieve the full raw string to know the
+ * length of the encoded string.
+ */
+ raw_len = fetch_setting ( settings, setting, NULL, 0 );
+ if ( raw_len < 0 )
+ return raw_len;
+
+ {
+ char raw_buf[ raw_len + 1 ];
+
+ fetch_string_setting ( settings, setting, raw_buf,
+ sizeof ( raw_buf ) );
+ return uri_encode ( raw_buf, buf, len );
+ }
+}
+
+/** A URI-encoded string setting type */
+struct setting_type setting_type_uristring __setting_type = {
+ .name = "uristring",
+ .storef = storef_uristring,
+ .fetchf = fetchf_uristring,
+};
+
+/**
+ * Parse and store value of IPv4 address setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+static int storef_ipv4 ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ struct in_addr ipv4;
+
+ if ( inet_aton ( value, &ipv4 ) == 0 )
+ return -EINVAL;
+ return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
+}
+
+/**
+ * Fetch and format value of IPv4 address setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ struct in_addr ipv4;
+ int raw_len;
+
+ if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
+ return raw_len;
+ return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
+}
+
+/** An IPv4 address setting type */
+struct setting_type setting_type_ipv4 __setting_type = {
+ .name = "ipv4",
+ .storef = storef_ipv4,
+ .fetchf = fetchf_ipv4,
+};
+
+/**
+ * Parse and store value of integer setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @v size Integer size, in bytes
+ * @ret rc Return status code
+ */
+static int storef_int ( struct settings *settings, struct setting *setting,
+ const char *value, unsigned int size ) {
+ union {
+ uint32_t num;
+ uint8_t bytes[4];
+ } u;
+ char *endp;
+
+ u.num = htonl ( strtoul ( value, &endp, 0 ) );
+ if ( *endp )
+ return -EINVAL;
+ return store_setting ( settings, setting,
+ &u.bytes[ sizeof ( u ) - size ], size );
+}
+
+/**
+ * Parse and store value of 8-bit integer setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @v size Integer size, in bytes
+ * @ret rc Return status code
+ */
+static int storef_int8 ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ return storef_int ( settings, setting, value, 1 );
+}
+
+/**
+ * Parse and store value of 16-bit integer setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @v size Integer size, in bytes
+ * @ret rc Return status code
+ */
+static int storef_int16 ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ return storef_int ( settings, setting, value, 2 );
+}
+
+/**
+ * Parse and store value of 32-bit integer setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @v size Integer size, in bytes
+ * @ret rc Return status code
+ */
+static int storef_int32 ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ return storef_int ( settings, setting, value, 4 );
+}
+
+/**
+ * Fetch and format value of signed integer setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_int ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ long value;
+ int rc;
+
+ if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
+ return rc;
+ return snprintf ( buf, len, "%ld", value );
+}
+
+/**
+ * Fetch and format value of unsigned integer setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_uint ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ unsigned long value;
+ int rc;
+
+ if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
+ return rc;
+ return snprintf ( buf, len, "%#lx", value );
+}
+
+/** A signed 8-bit integer setting type */
+struct setting_type setting_type_int8 __setting_type = {
+ .name = "int8",
+ .storef = storef_int8,
+ .fetchf = fetchf_int,
+};
+
+/** A signed 16-bit integer setting type */
+struct setting_type setting_type_int16 __setting_type = {
+ .name = "int16",
+ .storef = storef_int16,
+ .fetchf = fetchf_int,
+};
+
+/** A signed 32-bit integer setting type */
+struct setting_type setting_type_int32 __setting_type = {
+ .name = "int32",
+ .storef = storef_int32,
+ .fetchf = fetchf_int,
+};
+
+/** An unsigned 8-bit integer setting type */
+struct setting_type setting_type_uint8 __setting_type = {
+ .name = "uint8",
+ .storef = storef_int8,
+ .fetchf = fetchf_uint,
+};
+
+/** An unsigned 16-bit integer setting type */
+struct setting_type setting_type_uint16 __setting_type = {
+ .name = "uint16",
+ .storef = storef_int16,
+ .fetchf = fetchf_uint,
+};
+
+/** An unsigned 32-bit integer setting type */
+struct setting_type setting_type_uint32 __setting_type = {
+ .name = "uint32",
+ .storef = storef_int32,
+ .fetchf = fetchf_uint,
+};
+
+/**
+ * Parse and store value of hex string setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+static int storef_hex ( struct settings *settings, struct setting *setting,
+ const char *value ) {
+ char *ptr = ( char * ) value;
+ uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
+ unsigned int len = 0;
+
+ while ( 1 ) {
+ bytes[len++] = strtoul ( ptr, &ptr, 16 );
+ switch ( *ptr ) {
+ case '\0' :
+ return store_setting ( settings, setting, bytes, len );
+ case ':' :
+ ptr++;
+ break;
+ default :
+ return -EINVAL;
+ }
+ }
+}
+
+/**
+ * Fetch and format value of hex string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_hex ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ int raw_len;
+ int check_len;
+ int used = 0;
+ int i;
+
+ raw_len = fetch_setting_len ( settings, setting );
+ if ( raw_len < 0 )
+ return raw_len;
+
+ {
+ uint8_t raw[raw_len];
+
+ check_len = fetch_setting ( settings, setting, raw,
+ sizeof ( raw ) );
+ if ( check_len < 0 )
+ return check_len;
+ assert ( check_len == raw_len );
+
+ if ( len )
+ buf[0] = 0; /* Ensure that a terminating NUL exists */
+ for ( i = 0 ; i < raw_len ; i++ ) {
+ used += ssnprintf ( ( buf + used ), ( len - used ),
+ "%s%02x", ( used ? ":" : "" ),
+ raw[i] );
+ }
+ return used;
+ }
+}
+
+/** A hex-string setting */
+struct setting_type setting_type_hex __setting_type = {
+ .name = "hex",
+ .storef = storef_hex,
+ .fetchf = fetchf_hex,
+};
+
+/**
+ * Parse and store value of UUID setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+static int storef_uuid ( struct settings *settings __unused,
+ struct setting *setting __unused,
+ const char *value __unused ) {
+ return -ENOTSUP;
+}
+
+/**
+ * Fetch and format value of UUID setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static int fetchf_uuid ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len ) {
+ union uuid uuid;
+ int raw_len;
+
+ if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
+ return raw_len;
+ return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
+}
+
+/** UUID setting type */
+struct setting_type setting_type_uuid __setting_type = {
+ .name = "uuid",
+ .storef = storef_uuid,
+ .fetchf = fetchf_uuid,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** Hostname setting */
+struct setting hostname_setting __setting = {
+ .name = "hostname",
+ .description = "Host name",
+ .tag = DHCP_HOST_NAME,
+ .type = &setting_type_string,
+};
+
+/** Filename setting */
+struct setting filename_setting __setting = {
+ .name = "filename",
+ .description = "Boot filename",
+ .tag = DHCP_BOOTFILE_NAME,
+ .type = &setting_type_string,
+};
+
+/** Root path setting */
+struct setting root_path_setting __setting = {
+ .name = "root-path",
+ .description = "NFS/iSCSI root path",
+ .tag = DHCP_ROOT_PATH,
+ .type = &setting_type_string,
+};
+
+/** Username setting */
+struct setting username_setting __setting = {
+ .name = "username",
+ .description = "User name",
+ .tag = DHCP_EB_USERNAME,
+ .type = &setting_type_string,
+};
+
+/** Password setting */
+struct setting password_setting __setting = {
+ .name = "password",
+ .description = "Password",
+ .tag = DHCP_EB_PASSWORD,
+ .type = &setting_type_string,
+};
+
+/** Priority setting */
+struct setting priority_setting __setting = {
+ .name = "priority",
+ .description = "Priority of these settings",
+ .tag = DHCP_EB_PRIORITY,
+ .type = &setting_type_int8,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/core/uri.c b/debian/grub-extras/disabled/gpxe/src/core/uri.c
new file mode 100644
index 0000000..f87ec1b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/uri.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Uniform Resource Identifiers
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <ctype.h>
+#include <gpxe/vsprintf.h>
+#include <gpxe/uri.h>
+
+/**
+ * Dump URI for debugging
+ *
+ * @v uri URI
+ */
+static void dump_uri ( struct uri *uri ) {
+ if ( ! uri )
+ return;
+ if ( uri->scheme )
+ DBG ( " scheme \"%s\"", uri->scheme );
+ if ( uri->opaque )
+ DBG ( " opaque \"%s\"", uri->opaque );
+ if ( uri->user )
+ DBG ( " user \"%s\"", uri->user );
+ if ( uri->password )
+ DBG ( " password \"%s\"", uri->password );
+ if ( uri->host )
+ DBG ( " host \"%s\"", uri->host );
+ if ( uri->port )
+ DBG ( " port \"%s\"", uri->port );
+ if ( uri->path )
+ DBG ( " path \"%s\"", uri->path );
+ if ( uri->query )
+ DBG ( " query \"%s\"", uri->query );
+ if ( uri->fragment )
+ DBG ( " fragment \"%s\"", uri->fragment );
+}
+
+/**
+ * Parse URI
+ *
+ * @v uri_string URI as a string
+ * @ret uri URI
+ *
+ * Splits a URI into its component parts. The return URI structure is
+ * dynamically allocated and must eventually be freed by calling
+ * uri_put().
+ */
+struct uri * parse_uri ( const char *uri_string ) {
+ struct uri *uri;
+ char *raw;
+ char *tmp;
+ char *path = NULL;
+ char *authority = NULL;
+ size_t raw_len;
+
+ /* Allocate space for URI struct and a copy of the string */
+ raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
+ uri = zalloc ( sizeof ( *uri ) + raw_len );
+ if ( ! uri )
+ return NULL;
+ raw = ( ( ( char * ) uri ) + sizeof ( *uri ) );
+
+ /* Zero URI struct and copy in the raw string */
+ memcpy ( raw, uri_string, raw_len );
+
+ /* Start by chopping off the fragment, if it exists */
+ if ( ( tmp = strchr ( raw, '#' ) ) ) {
+ *(tmp++) = '\0';
+ uri->fragment = tmp;
+ }
+
+ /* Identify absolute/relative URI. We ignore schemes that are
+ * apparently only a single character long, since otherwise we
+ * misinterpret a DOS-style path name ("C:\path\to\file") as a
+ * URI with scheme="C",opaque="\path\to\file".
+ */
+ if ( ( tmp = strchr ( raw, ':' ) ) && ( tmp > ( raw + 1 ) ) ) {
+ /* Absolute URI: identify hierarchical/opaque */
+ uri->scheme = raw;
+ *(tmp++) = '\0';
+ if ( *tmp == '/' ) {
+ /* Absolute URI with hierarchical part */
+ path = tmp;
+ } else {
+ /* Absolute URI with opaque part */
+ uri->opaque = tmp;
+ }
+ } else {
+ /* Relative URI */
+ path = raw;
+ }
+
+ /* If we don't have a path (i.e. we have an absolute URI with
+ * an opaque portion, we're already finished processing
+ */
+ if ( ! path )
+ goto done;
+
+ /* Chop off the query, if it exists */
+ if ( ( tmp = strchr ( path, '?' ) ) ) {
+ *(tmp++) = '\0';
+ uri->query = tmp;
+ }
+
+ /* Identify net/absolute/relative path */
+ if ( strncmp ( path, "//", 2 ) == 0 ) {
+ /* Net path. If this is terminated by the first '/'
+ * of an absolute path, then we have no space for a
+ * terminator after the authority field, so shuffle
+ * the authority down by one byte, overwriting one of
+ * the two slashes.
+ */
+ authority = ( path + 2 );
+ if ( ( tmp = strchr ( authority, '/' ) ) ) {
+ /* Shuffle down */
+ uri->path = tmp;
+ memmove ( ( authority - 1 ), authority,
+ ( tmp - authority ) );
+ authority--;
+ *(--tmp) = '\0';
+ }
+ } else {
+ /* Absolute/relative path */
+ uri->path = path;
+ }
+
+ /* Split authority into user[:password] and host[:port] portions */
+ if ( ( tmp = strchr ( authority, '@' ) ) ) {
+ /* Has user[:password] */
+ *(tmp++) = '\0';
+ uri->host = tmp;
+ uri->user = authority;
+ if ( ( tmp = strchr ( authority, ':' ) ) ) {
+ /* Has password */
+ *(tmp++) = '\0';
+ uri->password = tmp;
+ }
+ } else {
+ /* No user:password */
+ uri->host = authority;
+ }
+
+ /* Split host into host[:port] */
+ if ( ( tmp = strchr ( uri->host, ':' ) ) ) {
+ *(tmp++) = '\0';
+ uri->port = tmp;
+ }
+
+ done:
+ DBG ( "URI \"%s\" split into", uri_string );
+ dump_uri ( uri );
+ DBG ( "\n" );
+
+ return uri;
+}
+
+/**
+ * Get port from URI
+ *
+ * @v uri URI, or NULL
+ * @v default_port Default port to use if none specified in URI
+ * @ret port Port
+ */
+unsigned int uri_port ( struct uri *uri, unsigned int default_port ) {
+ if ( ( ! uri ) || ( ! uri->port ) )
+ return default_port;
+ return ( strtoul ( uri->port, NULL, 0 ) );
+}
+
+/**
+ * Unparse URI
+ *
+ * @v buf Buffer to fill with URI string
+ * @v size Size of buffer
+ * @v uri URI to write into buffer, or NULL
+ * @ret len Length of URI string
+ */
+int unparse_uri ( char *buf, size_t size, struct uri *uri ) {
+ int used = 0;
+
+ DBG ( "URI unparsing" );
+ dump_uri ( uri );
+ DBG ( "\n" );
+
+ /* Special-case NULL URI */
+ if ( ! uri ) {
+ if ( size )
+ buf[0] = '\0';
+ return 0;
+ }
+
+ /* Special-case opaque URIs */
+ if ( uri->opaque ) {
+ return ssnprintf ( ( buf + used ), ( size - used ),
+ "%s:%s", uri->scheme, uri->opaque );
+ }
+
+ /* scheme:// */
+ if ( uri->scheme ) {
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ "%s://", uri->scheme );
+ }
+
+ /* [user[:password]@]host[:port] */
+ if ( uri->host ) {
+ if ( uri->user ) {
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ "%s", uri->user );
+ if ( uri->password ) {
+ used += ssnprintf ( ( buf + used ),
+ ( size - used ),
+ ":%s", uri->password );
+ }
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ "@" );
+ }
+ used += ssnprintf ( ( buf + used ), ( size - used ), "%s",
+ uri->host );
+ if ( uri->port ) {
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ ":%s", uri->port );
+ }
+ }
+
+ /* /path */
+ if ( uri->path ) {
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ "%s", uri->path );
+ }
+
+ /* ?query */
+ if ( uri->query ) {
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ "?%s", uri->query );
+ }
+
+ /* #fragment */
+ if ( uri->fragment ) {
+ used += ssnprintf ( ( buf + used ), ( size - used ),
+ "#%s", uri->fragment );
+ }
+
+ return used;
+}
+
+/**
+ * Duplicate URI
+ *
+ * @v uri URI
+ * @ret uri Duplicate URI
+ *
+ * Creates a modifiable copy of a URI.
+ */
+struct uri * uri_dup ( struct uri *uri ) {
+ size_t len = ( unparse_uri ( NULL, 0, uri ) + 1 );
+ char buf[len];
+
+ unparse_uri ( buf, len, uri );
+ return parse_uri ( buf );
+}
+
+/**
+ * Resolve base+relative path
+ *
+ * @v base_uri Base path
+ * @v relative_uri Relative path
+ * @ret resolved_uri Resolved path
+ *
+ * Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative
+ * path (e.g. "initrd.gz") and produces a new path
+ * (e.g. "/var/lib/tftpboot/initrd.gz"). Note that any non-directory
+ * portion of the base path will automatically be stripped; this
+ * matches the semantics used when resolving the path component of
+ * URIs.
+ */
+char * resolve_path ( const char *base_path,
+ const char *relative_path ) {
+ size_t base_len = ( strlen ( base_path ) + 1 );
+ char base_path_copy[base_len];
+ char *base_tmp = base_path_copy;
+
+ /* If relative path is absolute, just re-use it */
+ if ( relative_path[0] == '/' )
+ return strdup ( relative_path );
+
+ /* Create modifiable copy of path for dirname() */
+ memcpy ( base_tmp, base_path, base_len );
+ base_tmp = dirname ( base_tmp );
+
+ /* Process "./" and "../" elements */
+ while ( *relative_path == '.' ) {
+ relative_path++;
+ if ( *relative_path == 0 ) {
+ /* Do nothing */
+ } else if ( *relative_path == '/' ) {
+ relative_path++;
+ } else if ( *relative_path == '.' ) {
+ relative_path++;
+ if ( *relative_path == 0 ) {
+ base_tmp = dirname ( base_tmp );
+ } else if ( *relative_path == '/' ) {
+ base_tmp = dirname ( base_tmp );
+ relative_path++;
+ } else {
+ relative_path -= 2;
+ break;
+ }
+ } else {
+ relative_path--;
+ break;
+ }
+ }
+
+ /* Create and return new path */
+ return grub_xasprintf ( "%s%s%s", base_tmp,
+ ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
+ "" : "/" ), relative_path );
+}
+
+/**
+ * Resolve base+relative URI
+ *
+ * @v base_uri Base URI, or NULL
+ * @v relative_uri Relative URI
+ * @ret resolved_uri Resolved URI
+ *
+ * Takes a base URI (e.g. "http://etherboot.org/kernels/vmlinuz" and a
+ * relative URI (e.g. "../initrds/initrd.gz") and produces a new URI
+ * (e.g. "http://etherboot.org/initrds/initrd.gz").
+ */
+struct uri * resolve_uri ( struct uri *base_uri,
+ struct uri *relative_uri ) {
+ struct uri tmp_uri;
+ char *tmp_path = NULL;
+ struct uri *new_uri;
+
+ /* If relative URI is absolute, just re-use it */
+ if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
+ return uri_get ( relative_uri );
+
+ /* Mangle URI */
+ memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
+ if ( relative_uri->path ) {
+ tmp_path = resolve_path ( ( base_uri->path ?
+ base_uri->path : "/" ),
+ relative_uri->path );
+ tmp_uri.path = tmp_path;
+ tmp_uri.query = relative_uri->query;
+ tmp_uri.fragment = relative_uri->fragment;
+ } else if ( relative_uri->query ) {
+ tmp_uri.query = relative_uri->query;
+ tmp_uri.fragment = relative_uri->fragment;
+ } else if ( relative_uri->fragment ) {
+ tmp_uri.fragment = relative_uri->fragment;
+ }
+
+ /* Create demangled URI */
+ new_uri = uri_dup ( &tmp_uri );
+ free ( tmp_path );
+ return new_uri;
+}
+
+/**
+ * Test for unreserved URI characters
+ *
+ * @v c Character to test
+ * @ret is_unreserved Character is an unreserved character
+ */
+static int is_unreserved_uri_char ( int c ) {
+ /* According to RFC3986, the unreserved character set is
+ *
+ * A-Z a-z 0-9 - _ . ~
+ */
+ return ( isupper ( c ) || islower ( c ) || isdigit ( c ) ||
+ ( c == '-' ) || ( c == '_' ) ||
+ ( c == '.' ) || ( c == '~' ) );
+}
+
+/**
+ * URI-encode string
+ *
+ * @v raw_string String to be URI-encoded
+ * @v buf Buffer to contain encoded string
+ * @v len Length of buffer
+ * @ret len Length of encoded string (excluding NUL)
+ */
+size_t uri_encode ( const char *raw_string, char *buf, size_t len ) {
+ ssize_t remaining = len;
+ size_t used;
+ unsigned char c;
+
+ if ( len )
+ buf[0] = '\0';
+
+ while ( ( c = *(raw_string++) ) ) {
+ if ( is_unreserved_uri_char ( c ) ) {
+ used = ssnprintf ( buf, remaining, "%c", c );
+ } else {
+ used = ssnprintf ( buf, remaining, "%%%02X", c );
+ }
+ buf += used;
+ remaining -= used;
+ }
+
+ return ( len - remaining );
+}
+
+/**
+ * Decode URI-encoded string
+ *
+ * @v encoded_string URI-encoded string
+ * @v buf Buffer to contain decoded string
+ * @v len Length of buffer
+ * @ret len Length of decoded string (excluding NUL)
+ */
+size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) {
+ ssize_t remaining = len;
+ char hexbuf[3];
+ char *hexbuf_end;
+ unsigned char c;
+
+ if ( len )
+ buf[0] = '\0';
+
+ while ( *encoded_string ) {
+ if ( *encoded_string == '%' ) {
+ encoded_string++;
+ snprintf ( hexbuf, sizeof ( hexbuf ), "%s",
+ encoded_string );
+ c = strtoul ( hexbuf, &hexbuf_end, 16 );
+ encoded_string += ( hexbuf_end - hexbuf );
+ } else {
+ c = *(encoded_string++);
+ }
+ ssnprintf ( buf++, remaining--, "%c", c );
+ }
+ return ( len - remaining );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/uuid.c b/debian/grub-extras/disabled/gpxe/src/core/uuid.c
new file mode 100644
index 0000000..55fad36
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/uuid.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <gpxe/uuid.h>
+
+/** @file
+ *
+ * Universally unique IDs
+ *
+ */
+
+/**
+ * Convert UUID to printable string
+ *
+ * @v uuid UUID
+ * @ret string UUID in canonical form
+ */
+char * uuid_ntoa ( union uuid *uuid ) {
+ static char buf[37]; /* "00000000-0000-0000-0000-000000000000" */
+
+ snprintf ( buf, sizeof (buf),
+ "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ be32_to_cpu ( uuid->canonical.a ),
+ be16_to_cpu ( uuid->canonical.b ),
+ be16_to_cpu ( uuid->canonical.c ),
+ be16_to_cpu ( uuid->canonical.d ),
+ uuid->canonical.e[0], uuid->canonical.e[1],
+ uuid->canonical.e[2], uuid->canonical.e[3],
+ uuid->canonical.e[4], uuid->canonical.e[5] );
+ return buf;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/core/xfer.c b/debian/grub-extras/disabled/gpxe/src/core/xfer.c
new file mode 100644
index 0000000..1ec6f9d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/core/xfer.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <gpxe/xfer.h>
+
+/** @file
+ *
+ * Data transfer interfaces
+ *
+ */
+
+/**
+ * Dummy transfer metadata
+ *
+ * This gets passed to xfer_interface::deliver_iob() and equivalents
+ * when no metadata is available.
+ */
+static struct xfer_metadata dummy_metadata;
+
+/**
+ * Close data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+void xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct xfer_interface *dest = xfer_get_dest ( xfer );
+ struct xfer_interface_operations *op = xfer->op;
+
+ DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
+
+ xfer_unplug ( xfer );
+ xfer_nullify ( xfer );
+ dest->op->close ( dest, rc );
+ xfer->op = op;
+ xfer_put ( dest );
+}
+
+/**
+ * Send redirection event
+ *
+ * @v xfer Data transfer interface
+ * @v type New location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
+ struct xfer_interface *dest = xfer_get_dest ( xfer );
+ int rc;
+
+ DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest );
+
+ rc = dest->op->vredirect ( dest, type, args );
+
+ if ( rc != 0 ) {
+ DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest,
+ strerror ( rc ) );
+ }
+ xfer_put ( dest );
+ return rc;
+}
+
+/**
+ * Send redirection event
+ *
+ * @v xfer Data transfer interface
+ * @v type New location type
+ * @v ... Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
+ va_list args;
+ int rc;
+
+ va_start ( args, type );
+ rc = xfer_vredirect ( xfer, type, args );
+ va_end ( args );
+ return rc;
+}
+
+/**
+ * Check flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ */
+size_t xfer_window ( struct xfer_interface *xfer ) {
+ struct xfer_interface *dest = xfer_get_dest ( xfer );
+ size_t len;
+
+ len = dest->op->window ( dest );
+
+ xfer_put ( dest );
+ return len;
+}
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v len I/O buffer payload length
+ * @ret iobuf I/O buffer
+ */
+struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
+ struct xfer_interface *dest = xfer_get_dest ( xfer );
+ struct io_buffer *iobuf;
+
+ DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
+
+ iobuf = dest->op->alloc_iob ( dest, len );
+
+ if ( ! iobuf ) {
+ DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
+ }
+ xfer_put ( dest );
+ return iobuf;
+}
+
+/**
+ * Deliver datagram as I/O buffer with metadata
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct xfer_interface *dest = xfer_get_dest ( xfer );
+ int rc;
+
+ DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
+ iob_len ( iobuf ) );
+
+ rc = dest->op->deliver_iob ( dest, iobuf, meta );
+
+ if ( rc != 0 ) {
+ DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
+ strerror ( rc ) );
+ }
+ xfer_put ( dest );
+ return rc;
+}
+
+/**
+ * Deliver datagram as I/O buffer with metadata
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @ret rc Return status code
+ */
+int xfer_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf ) {
+ return xfer_deliver_iob_meta ( xfer, iobuf, &dummy_metadata );
+}
+
+/**
+ * Deliver datagram as raw data
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @ret rc Return status code
+ */
+int xfer_deliver_raw ( struct xfer_interface *xfer,
+ const void *data, size_t len ) {
+ struct xfer_interface *dest = xfer_get_dest ( xfer );
+ int rc;
+
+ DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
+ data, len );
+
+ rc = dest->op->deliver_raw ( dest, data, len );
+
+ if ( rc != 0 ) {
+ DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
+ strerror ( rc ) );
+ }
+ xfer_put ( dest );
+ return rc;
+}
+
+/**
+ * Deliver formatted string
+ *
+ * @v xfer Data transfer interface
+ * @v format Format string
+ * @v args Arguments corresponding to the format string
+ * @ret rc Return status code
+ */
+int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
+ va_list args ) {
+ size_t len;
+ va_list args_tmp;
+
+ va_copy ( args_tmp, args );
+ len = vsnprintf ( NULL, 0, format, args );
+ {
+ char buf[len + 1];
+ vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
+ va_end ( args_tmp );
+ return xfer_deliver_raw ( xfer, buf, len );
+ }
+}
+
+/**
+ * Deliver formatted string
+ *
+ * @v xfer Data transfer interface
+ * @v format Format string
+ * @v ... Arguments corresponding to the format string
+ * @ret rc Return status code
+ */
+int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
+ va_list args;
+ int rc;
+
+ va_start ( args, format );
+ rc = xfer_vprintf ( xfer, format, args );
+ va_end ( args );
+ return rc;
+}
+
+/**
+ * Seek to position
+ *
+ * @v xfer Data transfer interface
+ * @v offset Offset to new position
+ * @v whence Basis for new position
+ * @ret rc Return status code
+ */
+int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
+ struct io_buffer *iobuf;
+ struct xfer_metadata meta = {
+ .offset = offset,
+ .whence = whence,
+ };
+
+ DBGC ( xfer, "XFER %p seek %s+%ld\n", xfer,
+ whence_text ( whence ), offset );
+
+ /* Allocate and send a zero-length data buffer */
+ iobuf = xfer_alloc_iob ( xfer, 0 );
+ if ( ! iobuf )
+ return -ENOMEM;
+ return xfer_deliver_iob_meta ( xfer, iobuf, &meta );
+}
+
+/****************************************************************************
+ *
+ * Helper methods
+ *
+ * These functions are designed to be used as methods in the
+ * xfer_interface_operations table.
+ *
+ */
+
+/**
+ * Ignore close() event
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+void ignore_xfer_close ( struct xfer_interface *xfer __unused,
+ int rc __unused ) {
+ /* Nothing to do */
+}
+
+/**
+ * Ignore vredirect() event
+ *
+ * @v xfer Data transfer interface
+ * @v type New location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
+ int type __unused, va_list args __unused ) {
+ return 0;
+}
+
+/**
+ * Unlimited flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ *
+ * This handler indicates that the interface is always ready to accept
+ * data.
+ */
+size_t unlimited_xfer_window ( struct xfer_interface *xfer __unused ) {
+ return ~( ( size_t ) 0 );
+}
+
+/**
+ * No flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ *
+ * This handler indicates that the interface is never ready to accept
+ * data.
+ */
+size_t no_xfer_window ( struct xfer_interface *xfer __unused ) {
+ return 0;
+}
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v len I/O buffer payload length
+ * @ret iobuf I/O buffer
+ */
+struct io_buffer *
+default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
+ return alloc_iob ( len );
+}
+
+/**
+ * Deliver datagram as raw data
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ *
+ * This function is intended to be used as the deliver() method for
+ * data transfer interfaces that prefer to handle raw data.
+ */
+int xfer_deliver_as_raw ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ int rc;
+
+ rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Deliver datagram as I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * This function is intended to be used as the deliver_raw() method
+ * for data transfer interfaces that prefer to handle I/O buffers.
+ */
+int xfer_deliver_as_iob ( struct xfer_interface *xfer,
+ const void *data, size_t len ) {
+ struct io_buffer *iobuf;
+
+ iobuf = xfer->op->alloc_iob ( xfer, len );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ memcpy ( iob_put ( iobuf, len ), data, len );
+ return xfer->op->deliver_iob ( xfer, iobuf, &dummy_metadata );
+}
+
+/**
+ * Ignore datagram as raw data event
+ *
+ * @v xfer Data transfer interface
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
+ const void *data __unused, size_t len ) {
+ DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len,
+ ( ( xfer == &null_xfer ) ?
+ "before connection" : "after termination" ) );
+ return 0;
+}
+
+/** Null data transfer interface operations */
+struct xfer_interface_operations null_xfer_ops = {
+ .close = ignore_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = ignore_xfer_deliver_raw,
+};
+
+/**
+ * Null data transfer interface
+ *
+ * This is the interface to which data transfer interfaces are
+ * connected when unplugged. It will never generate messages, and
+ * will silently absorb all received messages.
+ */
+struct xfer_interface null_xfer = XFER_INIT ( &null_xfer_ops );
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/bitbash.c b/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/bitbash.c
new file mode 100644
index 0000000..3e558d5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/bitbash.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/bitbash.h>
+
+/** @file
+ *
+ * Bit-bashing interfaces
+ *
+ */
+
+/**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ *
+ * If @c data is 0, a logic 0 will be written. If @c data is
+ * non-zero, a logic 1 will be written.
+ */
+void write_bit ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data ) {
+ basher->op->write ( basher, bit_id, ( data ? -1UL : 0 ) );
+}
+
+/**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret data Value read
+ *
+ * @c data will always be either 0 or -1UL. The idea is that the
+ * caller can simply binary-AND the returned value with whatever mask
+ * it needs to apply.
+ */
+int read_bit ( struct bit_basher *basher, unsigned int bit_id ) {
+ return ( basher->op->read ( basher, bit_id ) ? -1UL : 0 );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/i2c_bit.c b/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/i2c_bit.c
new file mode 100644
index 0000000..1319727
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/i2c_bit.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <gpxe/bitbash.h>
+#include <gpxe/i2c.h>
+
+/** @file
+ *
+ * I2C bit-bashing interface
+ *
+ * This implements a simple I2C master via a bit-bashing interface
+ * that provides two lines: SCL (clock) and SDA (data).
+ */
+
+/**
+ * Delay between output state changes
+ *
+ * Max rated i2c speed (for the basic i2c protocol) is 100kbps,
+ * i.e. 200k clock transitions per second.
+ */
+static void i2c_delay ( void ) {
+ udelay ( I2C_UDELAY );
+}
+
+/**
+ * Set state of I2C SCL line
+ *
+ * @v basher Bit-bashing interface
+ * @v state New state of SCL
+ */
+static void setscl ( struct bit_basher *basher, int state ) {
+ DBG2 ( "%c", ( state ? '/' : '\\' ) );
+ write_bit ( basher, I2C_BIT_SCL, state );
+ i2c_delay();
+}
+
+/**
+ * Set state of I2C SDA line
+ *
+ * @v basher Bit-bashing interface
+ * @v state New state of SDA
+ */
+static void setsda ( struct bit_basher *basher, int state ) {
+ DBG2 ( "%c", ( state ? '1' : '0' ) );
+ write_bit ( basher, I2C_BIT_SDA, state );
+ i2c_delay();
+}
+
+/**
+ * Get state of I2C SDA line
+ *
+ * @v basher Bit-bashing interface
+ * @ret state State of SDA
+ */
+static int getsda ( struct bit_basher *basher ) {
+ int state;
+ state = read_bit ( basher, I2C_BIT_SDA );
+ DBG2 ( "%c", ( state ? '+' : '-' ) );
+ return state;
+}
+
+/**
+ * Send an I2C start condition
+ *
+ * @v basher Bit-bashing interface
+ */
+static void i2c_start ( struct bit_basher *basher ) {
+ setscl ( basher, 1 );
+ setsda ( basher, 0 );
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+}
+
+/**
+ * Send an I2C data bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit Bit to send
+ */
+static void i2c_send_bit ( struct bit_basher *basher, int bit ) {
+ setsda ( basher, bit );
+ setscl ( basher, 1 );
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+}
+
+/**
+ * Receive an I2C data bit
+ *
+ * @v basher Bit-bashing interface
+ * @ret bit Received bit
+ */
+static int i2c_recv_bit ( struct bit_basher *basher ) {
+ int bit;
+
+ setscl ( basher, 1 );
+ bit = getsda ( basher );
+ setscl ( basher, 0 );
+ return bit;
+}
+
+/**
+ * Send an I2C stop condition
+ *
+ * @v basher Bit-bashing interface
+ */
+static void i2c_stop ( struct bit_basher *basher ) {
+ setsda ( basher, 0 );
+ setscl ( basher, 1 );
+ setsda ( basher, 1 );
+}
+
+/**
+ * Send byte via I2C bus and check for acknowledgement
+ *
+ * @v basher Bit-bashing interface
+ * @v byte Byte to send
+ * @ret rc Return status code
+ *
+ * Sends a byte via the I2C bus and checks for an acknowledgement from
+ * the slave device.
+ */
+static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
+ int i;
+ int ack;
+
+ /* Send byte */
+ DBG2 ( "[send %02x]", byte );
+ for ( i = 8 ; i ; i-- ) {
+ i2c_send_bit ( basher, byte & 0x80 );
+ byte <<= 1;
+ }
+
+ /* Check for acknowledgement from slave */
+ ack = ( i2c_recv_bit ( basher ) == 0 );
+ DBG2 ( "%s", ( ack ? "[acked]" : "[not acked]" ) );
+
+ return ( ack ? 0 : -EIO );
+}
+
+/**
+ * Receive byte via I2C bus
+ *
+ * @v basher Bit-bashing interface
+ * @ret byte Received byte
+ *
+ * Receives a byte via the I2C bus and sends NACK to the slave device.
+ */
+static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
+ uint8_t byte = 0;
+ int i;
+
+ /* Receive byte */
+ for ( i = 8 ; i ; i-- ) {
+ byte <<= 1;
+ byte |= ( i2c_recv_bit ( basher ) & 0x1 );
+ }
+
+ /* Send NACK */
+ i2c_send_bit ( basher, 1 );
+
+ DBG2 ( "[rcvd %02x]", byte );
+ return byte;
+}
+
+/**
+ * Select I2C device for reading or writing
+ *
+ * @v basher Bit-bashing interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v direction I2C_READ or I2C_WRITE
+ * @ret rc Return status code
+ */
+static int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev,
+ unsigned int offset, unsigned int direction ) {
+ unsigned int address;
+ int shift;
+ unsigned int byte;
+ int rc;
+
+ i2c_start ( basher );
+
+ /* Calculate address to appear on bus */
+ address = ( ( ( i2cdev->dev_addr |
+ ( offset >> ( 8 * i2cdev->word_addr_len ) ) ) << 1 )
+ | direction );
+
+ /* Send address a byte at a time */
+ for ( shift = ( 8 * ( i2cdev->dev_addr_len - 1 ) ) ;
+ shift >= 0 ; shift -= 8 ) {
+ byte = ( ( address >> shift ) & 0xff );
+ if ( ( rc = i2c_send_byte ( basher, byte ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Reset I2C bus
+ *
+ * @v basher Bit-bashing interface
+ * @ret rc Return status code
+ *
+ * i2c devices often don't have a reset line, so even a reboot or
+ * system power cycle is sometimes not enough to bring them back to a
+ * known state.
+ */
+static int i2c_reset ( struct bit_basher *basher ) {
+ unsigned int i;
+ int sda;
+
+ /* Clock through several cycles, waiting for an opportunity to
+ * pull SDA low while SCL is high (which creates a start
+ * condition).
+ */
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+ for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) {
+ setscl ( basher, 1 );
+ sda = getsda ( basher );
+ if ( sda ) {
+ /* Now that the device will see a start, issue it */
+ i2c_start ( basher );
+ /* Stop the bus to leave it in a known good state */
+ i2c_stop ( basher );
+ DBGC ( basher, "I2CBIT %p reset after %d attempts\n",
+ basher, ( i + 1 ) );
+ return 0;
+ }
+ setscl ( basher, 0 );
+ }
+
+ DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n",
+ basher, i );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read data from I2C device via bit-bashing interface
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Note that attempting to read zero bytes of data is a valid way to
+ * check for I2C device presence.
+ */
+static int i2c_bit_read ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev, unsigned int offset,
+ uint8_t *data, unsigned int len ) {
+ struct i2c_bit_basher *i2cbit
+ = container_of ( i2c, struct i2c_bit_basher, i2c );
+ struct bit_basher *basher = &i2cbit->basher;
+ int rc = 0;
+
+ DBGC ( basher, "I2CBIT %p reading from device %x: ",
+ basher, i2cdev->dev_addr );
+
+ for ( ; ; data++, offset++ ) {
+
+ /* Select device for writing */
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_WRITE ) ) != 0 )
+ break;
+
+ /* Abort at end of data */
+ if ( ! ( len-- ) )
+ break;
+
+ /* Select offset */
+ if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
+ break;
+
+ /* Select device for reading */
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_READ ) ) != 0 )
+ break;
+
+ /* Read byte */
+ *data = i2c_recv_byte ( basher );
+ DBGC ( basher, "%02x ", *data );
+ }
+
+ DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
+ i2c_stop ( basher );
+ return rc;
+}
+
+/**
+ * Write data to I2C device via bit-bashing interface
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Note that attempting to write zero bytes of data is a valid way to
+ * check for I2C device presence.
+ */
+static int i2c_bit_write ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev, unsigned int offset,
+ const uint8_t *data, unsigned int len ) {
+ struct i2c_bit_basher *i2cbit
+ = container_of ( i2c, struct i2c_bit_basher, i2c );
+ struct bit_basher *basher = &i2cbit->basher;
+ int rc = 0;
+
+ DBGC ( basher, "I2CBIT %p writing to device %x: ",
+ basher, i2cdev->dev_addr );
+
+ for ( ; ; data++, offset++ ) {
+
+ /* Select device for writing */
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_WRITE ) ) != 0 )
+ break;
+
+ /* Abort at end of data */
+ if ( ! ( len-- ) )
+ break;
+
+ /* Select offset */
+ if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
+ break;
+
+ /* Write data to device */
+ DBGC ( basher, "%02x ", *data );
+ if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 )
+ break;
+ }
+
+ DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
+ i2c_stop ( basher );
+ return rc;
+}
+
+/**
+ * Initialise I2C bit-bashing interface
+ *
+ * @v i2cbit I2C bit-bashing interface
+ * @v bash_op Bit-basher operations
+ */
+int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
+ struct bit_basher_operations *bash_op ) {
+ struct bit_basher *basher = &i2cbit->basher;
+ int rc;
+
+ /* Initialise data structures */
+ basher->op = bash_op;
+ assert ( basher->op->read != NULL );
+ assert ( basher->op->write != NULL );
+ i2cbit->i2c.read = i2c_bit_read;
+ i2cbit->i2c.write = i2c_bit_write;
+
+ /* Reset I2C bus */
+ if ( ( rc = i2c_reset ( basher ) ) != 0 ) {
+ DBGC ( basher, "I2CBIT %p could not reset I2C bus: %s\n",
+ basher, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/spi_bit.c b/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/spi_bit.c
new file mode 100644
index 0000000..8e70393
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/bitbash/spi_bit.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+#include <gpxe/bitbash.h>
+#include <gpxe/spi_bit.h>
+
+/** @file
+ *
+ * SPI bit-bashing interface
+ *
+ */
+
+/** Delay between SCLK changes and around SS changes */
+static void spi_bit_delay ( void ) {
+ udelay ( SPI_BIT_UDELAY );
+}
+
+/** Chip select line will be asserted */
+#define SELECT_SLAVE 0
+
+/** Chip select line will be deasserted */
+#define DESELECT_SLAVE SPI_MODE_SSPOL
+
+/**
+ * Select/deselect slave
+ *
+ * @v spibit SPI bit-bashing interface
+ * @v slave Slave number
+ * @v state Slave select state
+ *
+ * @c state must be @c SELECT_SLAVE or @c DESELECT_SLAVE.
+ */
+static void spi_bit_set_slave_select ( struct spi_bit_basher *spibit,
+ unsigned int slave,
+ unsigned int state ) {
+ struct bit_basher *basher = &spibit->basher;
+
+ state ^= ( spibit->bus.mode & SPI_MODE_SSPOL );
+ DBGC2 ( spibit, "SPIBIT %p setting slave %d select %s\n",
+ spibit, slave, ( state ? "high" : "low" ) );
+
+ spi_bit_delay();
+ write_bit ( basher, SPI_BIT_SS ( slave ), state );
+ spi_bit_delay();
+}
+
+/**
+ * Transfer bits over SPI bit-bashing bus
+ *
+ * @v bus SPI bus
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of transfer (in @b bits)
+ * @v endianness Endianness of this data transfer
+ *
+ * This issues @c len clock cycles on the SPI bus, shifting out data
+ * from the @c data_out buffer to the MOSI line and shifting in data
+ * from the MISO line to the @c data_in buffer. If @c data_out is
+ * NULL, then the data sent will be all zeroes. If @c data_in is
+ * NULL, then the incoming data will be discarded.
+ */
+static void spi_bit_transfer ( struct spi_bit_basher *spibit,
+ const void *data_out, void *data_in,
+ unsigned int len, int endianness ) {
+ struct spi_bus *bus = &spibit->bus;
+ struct bit_basher *basher = &spibit->basher;
+ unsigned int sclk = ( ( bus->mode & SPI_MODE_CPOL ) ? 1 : 0 );
+ unsigned int cpha = ( ( bus->mode & SPI_MODE_CPHA ) ? 1 : 0 );
+ unsigned int bit_offset;
+ unsigned int byte_offset;
+ unsigned int byte_mask;
+ unsigned int bit;
+ unsigned int step;
+
+ DBGC2 ( spibit, "SPIBIT %p transferring %d bits in mode %#x\n",
+ spibit, len, bus->mode );
+
+ for ( step = 0 ; step < ( len * 2 ) ; step++ ) {
+ /* Calculate byte offset and byte mask */
+ bit_offset = ( ( endianness == SPI_BIT_BIG_ENDIAN ) ?
+ ( len - ( step / 2 ) - 1 ) : ( step / 2 ) );
+ byte_offset = ( bit_offset / 8 );
+ byte_mask = ( 1 << ( bit_offset % 8 ) );
+
+ /* Shift data in or out */
+ if ( sclk == cpha ) {
+ const uint8_t *byte;
+
+ /* Shift data out */
+ if ( data_out ) {
+ byte = ( data_out + byte_offset );
+ bit = ( *byte & byte_mask );
+ DBGCP ( spibit, "SPIBIT %p wrote bit %d\n",
+ spibit, ( bit ? 1 : 0 ) );
+ } else {
+ bit = 0;
+ }
+ write_bit ( basher, SPI_BIT_MOSI, bit );
+ } else {
+ uint8_t *byte;
+
+ /* Shift data in */
+ bit = read_bit ( basher, SPI_BIT_MISO );
+ if ( data_in ) {
+ DBGCP ( spibit, "SPIBIT %p read bit %d\n",
+ spibit, ( bit ? 1 : 0 ) );
+ byte = ( data_in + byte_offset );
+ *byte &= ~byte_mask;
+ *byte |= ( bit & byte_mask );
+ }
+ }
+
+ /* Toggle clock line */
+ spi_bit_delay();
+ sclk ^= 1;
+ write_bit ( basher, SPI_BIT_SCLK, sclk );
+ }
+}
+
+/**
+ * Read/write data via SPI bit-bashing bus
+ *
+ * @v bus SPI bus
+ * @v device SPI device
+ * @v command Command
+ * @v address Address to read/write (<0 for no address)
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of transfer
+ * @ret rc Return status code
+ */
+static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void *data_out, void *data_in, size_t len ) {
+ struct spi_bit_basher *spibit
+ = container_of ( bus, struct spi_bit_basher, bus );
+ uint32_t tmp_command;
+ uint32_t tmp_address;
+ uint32_t tmp_address_detect;
+
+ /* Set clock line to idle state */
+ write_bit ( &spibit->basher, SPI_BIT_SCLK,
+ ( bus->mode & SPI_MODE_CPOL ) );
+
+ /* Assert chip select on specified slave */
+ spi_bit_set_slave_select ( spibit, device->slave, SELECT_SLAVE );
+
+ /* Transmit command */
+ assert ( device->command_len <= ( 8 * sizeof ( tmp_command ) ) );
+ tmp_command = cpu_to_le32 ( command );
+ spi_bit_transfer ( spibit, &tmp_command, NULL, device->command_len,
+ SPI_BIT_BIG_ENDIAN );
+
+ /* Transmit address, if present */
+ if ( address >= 0 ) {
+ assert ( device->address_len <= ( 8 * sizeof ( tmp_address )));
+ tmp_address = cpu_to_le32 ( address );
+ if ( device->address_len == SPI_AUTODETECT_ADDRESS_LEN ) {
+ /* Autodetect address length. This relies on
+ * the device responding with a dummy zero
+ * data bit before the first real data bit.
+ */
+ DBGC ( spibit, "SPIBIT %p autodetecting device "
+ "address length\n", spibit );
+ assert ( address == 0 );
+ device->address_len = 0;
+ do {
+ spi_bit_transfer ( spibit, &tmp_address,
+ &tmp_address_detect, 1,
+ SPI_BIT_BIG_ENDIAN );
+ device->address_len++;
+ } while ( le32_to_cpu ( tmp_address_detect ) & 1 );
+ DBGC ( spibit, "SPIBIT %p autodetected device address "
+ "length %d\n", spibit, device->address_len );
+ } else {
+ spi_bit_transfer ( spibit, &tmp_address, NULL,
+ device->address_len,
+ SPI_BIT_BIG_ENDIAN );
+ }
+ }
+
+ /* Transmit/receive data */
+ spi_bit_transfer ( spibit, data_out, data_in, ( len * 8 ),
+ spibit->endianness );
+
+ /* Deassert chip select on specified slave */
+ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE );
+
+ return 0;
+}
+
+/**
+ * Initialise SPI bit-bashing interface
+ *
+ * @v spibit SPI bit-bashing interface
+ */
+void init_spi_bit_basher ( struct spi_bit_basher *spibit ) {
+ assert ( &spibit->basher.op->read != NULL );
+ assert ( &spibit->basher.op->write != NULL );
+ spibit->bus.rw = spi_bit_rw;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/block/scsi.c b/debian/grub-extras/disabled/gpxe/src/drivers/block/scsi.c
new file mode 100644
index 0000000..a51b3af
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/block/scsi.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/blockdev.h>
+#include <gpxe/process.h>
+#include <gpxe/scsi.h>
+
+/** @file
+ *
+ * SCSI block device
+ *
+ */
+
+/** Maximum number of dummy "read capacity (10)" operations
+ *
+ * These are issued at connection setup to draw out various useless
+ * power-on messages.
+ */
+#define SCSI_MAX_DUMMY_READ_CAP 10
+
+static inline __attribute__ (( always_inline )) struct scsi_device *
+block_to_scsi ( struct block_device *blockdev ) {
+ return container_of ( blockdev, struct scsi_device, blockdev );
+}
+
+/**
+ * Handle SCSI command with no backing device
+ *
+ * @v scsi SCSI device
+ * @v command SCSI command
+ * @ret rc Return status code
+ */
+int scsi_detached_command ( struct scsi_device *scsi __unused,
+ struct scsi_command *command __unused ) {
+ return -ENODEV;
+}
+
+/**
+ * Issue SCSI command
+ *
+ * @v scsi SCSI device
+ * @v command SCSI command
+ * @ret rc Return status code
+ */
+static int scsi_command ( struct scsi_device *scsi,
+ struct scsi_command *command ) {
+ int rc;
+
+ DBGC2 ( scsi, "SCSI %p " SCSI_CDB_FORMAT "\n",
+ scsi, SCSI_CDB_DATA ( command->cdb ) );
+
+ /* Clear sense response code before issuing command */
+ command->sense_response = 0;
+
+ /* Flag command as in-progress */
+ command->rc = -EINPROGRESS;
+
+ /* Issue SCSI command */
+ if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) {
+ /* Something went wrong with the issuing mechanism */
+ DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
+ scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Wait for command to complete */
+ while ( command->rc == -EINPROGRESS )
+ step();
+ if ( ( rc = command->rc ) != 0 ) {
+ /* Something went wrong with the command execution */
+ DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
+ scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Check for SCSI errors */
+ if ( command->status != 0 ) {
+ DBGC ( scsi, "SCSI %p " SCSI_CDB_FORMAT " status %02x sense "
+ "%02x\n", scsi, SCSI_CDB_DATA ( command->cdb ),
+ command->status, command->sense_response );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Read block from SCSI device using READ (10)
+ *
+ * @v blockdev Block device
+ * @v block LBA block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+static int scsi_read_10 ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer ) {
+ struct scsi_device *scsi = block_to_scsi ( blockdev );
+ struct scsi_command command;
+ struct scsi_cdb_read_10 *cdb = &command.cdb.read10;
+
+ /* Issue READ (10) */
+ memset ( &command, 0, sizeof ( command ) );
+ cdb->opcode = SCSI_OPCODE_READ_10;
+ cdb->lba = cpu_to_be32 ( block );
+ cdb->len = cpu_to_be16 ( count );
+ command.data_in = buffer;
+ command.data_in_len = ( count * blockdev->blksize );
+ return scsi_command ( scsi, &command );
+}
+
+/**
+ * Read block from SCSI device using READ (16)
+ *
+ * @v blockdev Block device
+ * @v block LBA block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+static int scsi_read_16 ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer ) {
+ struct scsi_device *scsi = block_to_scsi ( blockdev );
+ struct scsi_command command;
+ struct scsi_cdb_read_16 *cdb = &command.cdb.read16;
+
+ /* Issue READ (16) */
+ memset ( &command, 0, sizeof ( command ) );
+ cdb->opcode = SCSI_OPCODE_READ_16;
+ cdb->lba = cpu_to_be64 ( block );
+ cdb->len = cpu_to_be32 ( count );
+ command.data_in = buffer;
+ command.data_in_len = ( count * blockdev->blksize );
+ return scsi_command ( scsi, &command );
+}
+
+/**
+ * Write block to SCSI device using WRITE (10)
+ *
+ * @v blockdev Block device
+ * @v block LBA block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+static int scsi_write_10 ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer ) {
+ struct scsi_device *scsi = block_to_scsi ( blockdev );
+ struct scsi_command command;
+ struct scsi_cdb_write_10 *cdb = &command.cdb.write10;
+
+ /* Issue WRITE (10) */
+ memset ( &command, 0, sizeof ( command ) );
+ cdb->opcode = SCSI_OPCODE_WRITE_10;
+ cdb->lba = cpu_to_be32 ( block );
+ cdb->len = cpu_to_be16 ( count );
+ command.data_out = buffer;
+ command.data_out_len = ( count * blockdev->blksize );
+ return scsi_command ( scsi, &command );
+}
+
+/**
+ * Write block to SCSI device using WRITE (16)
+ *
+ * @v blockdev Block device
+ * @v block LBA block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+static int scsi_write_16 ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer ) {
+ struct scsi_device *scsi = block_to_scsi ( blockdev );
+ struct scsi_command command;
+ struct scsi_cdb_write_16 *cdb = &command.cdb.write16;
+
+ /* Issue WRITE (16) */
+ memset ( &command, 0, sizeof ( command ) );
+ cdb->opcode = SCSI_OPCODE_WRITE_16;
+ cdb->lba = cpu_to_be64 ( block );
+ cdb->len = cpu_to_be32 ( count );
+ command.data_out = buffer;
+ command.data_out_len = ( count * blockdev->blksize );
+ return scsi_command ( scsi, &command );
+}
+
+/**
+ * Read capacity of SCSI device via READ CAPACITY (10)
+ *
+ * @v blockdev Block device
+ * @ret rc Return status code
+ */
+static int scsi_read_capacity_10 ( struct block_device *blockdev ) {
+ struct scsi_device *scsi = block_to_scsi ( blockdev );
+ struct scsi_command command;
+ struct scsi_cdb_read_capacity_10 *cdb = &command.cdb.readcap10;
+ struct scsi_capacity_10 capacity;
+ int rc;
+
+ /* Issue READ CAPACITY (10) */
+ memset ( &command, 0, sizeof ( command ) );
+ cdb->opcode = SCSI_OPCODE_READ_CAPACITY_10;
+ command.data_in = virt_to_user ( &capacity );
+ command.data_in_len = sizeof ( capacity );
+
+ if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
+ return rc;
+
+ /* Fill in block device fields */
+ blockdev->blksize = be32_to_cpu ( capacity.blksize );
+ blockdev->blocks = ( be32_to_cpu ( capacity.lba ) + 1 );
+
+ return 0;
+}
+
+/**
+ * Read capacity of SCSI device via READ CAPACITY (16)
+ *
+ * @v blockdev Block device
+ * @ret rc Return status code
+ */
+static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
+ struct scsi_device *scsi = block_to_scsi ( blockdev );
+ struct scsi_command command;
+ struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
+ struct scsi_capacity_16 capacity;
+ int rc;
+
+ /* Issue READ CAPACITY (16) */
+ memset ( &command, 0, sizeof ( command ) );
+ cdb->opcode = SCSI_OPCODE_SERVICE_ACTION_IN;
+ cdb->service_action = SCSI_SERVICE_ACTION_READ_CAPACITY_16;
+ cdb->len = cpu_to_be32 ( sizeof ( capacity ) );
+ command.data_in = virt_to_user ( &capacity );
+ command.data_in_len = sizeof ( capacity );
+
+ if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
+ return rc;
+
+ /* Fill in block device fields */
+ blockdev->blksize = be32_to_cpu ( capacity.blksize );
+ blockdev->blocks = ( be64_to_cpu ( capacity.lba ) + 1 );
+ return 0;
+}
+
+static struct block_device_operations scsi_operations_16 = {
+ .read = scsi_read_16,
+ .write = scsi_write_16,
+};
+
+static struct block_device_operations scsi_operations_10 = {
+ .read = scsi_read_10,
+ .write = scsi_write_10,
+};
+
+/**
+ * Initialise SCSI device
+ *
+ * @v scsi SCSI device
+ * @ret rc Return status code
+ *
+ * Initialises a SCSI device. The scsi_device::command and
+ * scsi_device::lun fields must already be filled in. This function
+ * will configure scsi_device::blockdev, including issuing a READ
+ * CAPACITY call to determine the block size and total device size.
+ */
+int init_scsidev ( struct scsi_device *scsi ) {
+ unsigned int i;
+ int rc;
+
+ /* Issue some theoretically extraneous READ CAPACITY (10)
+ * commands, solely in order to draw out the "CHECK CONDITION
+ * (power-on occurred)", "CHECK CONDITION (reported LUNs data
+ * has changed)" etc. that some dumb targets insist on sending
+ * as an error at start of day. The precise command that we
+ * use is unimportant; we just need to provide the target with
+ * an opportunity to send its responses.
+ */
+ for ( i = 0 ; i < SCSI_MAX_DUMMY_READ_CAP ; i++ ) {
+ if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) == 0 )
+ break;
+ DBGC ( scsi, "SCSI %p ignoring start-of-day error (#%d)\n",
+ scsi, ( i + 1 ) );
+ }
+
+ /* Try READ CAPACITY (10), which is a mandatory command, first. */
+ scsi->blockdev.op = &scsi_operations_10;
+ if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) != 0 ) {
+ DBGC ( scsi, "SCSI %p could not READ CAPACITY (10): %s\n",
+ scsi, strerror ( rc ) );
+ return rc;
+ }
+
+ /* If capacity range was exceeded (i.e. capacity.lba was
+ * 0xffffffff, meaning that blockdev->blocks is now zero), use
+ * READ CAPACITY (16) instead. READ CAPACITY (16) is not
+ * mandatory, so we can't just use it straight off.
+ */
+ if ( scsi->blockdev.blocks == 0 ) {
+ scsi->blockdev.op = &scsi_operations_16;
+ if ( ( rc = scsi_read_capacity_16 ( &scsi->blockdev ) ) != 0 ){
+ DBGC ( scsi, "SCSI %p could not READ CAPACITY (16): "
+ "%s\n", scsi, strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ DBGC ( scsi, "SCSI %p using READ/WRITE (%d) commands\n", scsi,
+ ( ( scsi->blockdev.op == &scsi_operations_10 ) ? 10 : 16 ) );
+ DBGC ( scsi, "SCSI %p capacity is %ld MB (%#llx blocks)\n", scsi,
+ ( ( unsigned long ) ( scsi->blockdev.blocks >> 11 ) ),
+ scsi->blockdev.blocks );
+
+ return 0;
+}
+
+/**
+ * Parse SCSI LUN
+ *
+ * @v lun_string LUN string representation
+ * @v lun LUN to fill in
+ * @ret rc Return status code
+ */
+int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun ) {
+ char *p;
+ int i;
+
+ memset ( lun, 0, sizeof ( *lun ) );
+ if ( lun_string ) {
+ p = ( char * ) lun_string;
+ for ( i = 0 ; i < 4 ; i++ ) {
+ lun->u16[i] = htons ( strtoul ( p, &p, 16 ) );
+ if ( *p == '\0' )
+ break;
+ if ( *p != '-' )
+ return -EINVAL;
+ p++;
+ }
+ if ( *p )
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.c
new file mode 100644
index 0000000..1c58f77
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.c
@@ -0,0 +1,432 @@
+/*
+ * Split out into 3c509.c and 3c5x9.c, to make it possible to build a
+ * 3c529 module without including ISA, ISAPnP and EISA code.
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/io.h>
+#include <unistd.h>
+#include <gpxe/device.h>
+#include <gpxe/isa.h>
+#include "3c509.h"
+
+/*
+ * 3c509 cards have their own method of contention resolution; this
+ * effectively defines another bus type similar to ISAPnP. Even the
+ * original ISA cards can be programatically mapped to any I/O address
+ * in the range 0x200-0x3e0.
+ *
+ * However, there is a small problem: once you've activated a card,
+ * the only ways to deactivate it will also wipe its tag, meaning that
+ * you won't be able to subsequently reactivate it without going
+ * through the whole ID sequence again. The solution we adopt is to
+ * isolate and tag all cards at the start, and to immediately
+ * re-isolate and re-tag a card after disabling it.
+ *
+ */
+
+static void t509bus_remove ( struct root_device *rootdev );
+
+static unsigned int t509_id_port = 0;
+static unsigned int t509_max_tag = 0;
+
+/** A 3c509 device */
+struct t509_device {
+ /** Generic device */
+ struct device dev;
+ /** Tag */
+ unsigned int tag;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Driver-private data
+ *
+ * Use t509_set_drvdata() and t509_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+};
+
+/**
+ * Set 3c509 driver-private data
+ *
+ * @v t509 3c509 device
+ * @v priv Private data
+ */
+static inline void t509_set_drvdata ( struct t509_device *t509, void *priv ) {
+ t509->priv = priv;
+}
+
+/**
+ * Get 3c509 driver-private data
+ *
+ * @v t509 3c509 device
+ * @ret priv Private data
+ */
+static inline void * t509_get_drvdata ( struct t509_device *t509 ) {
+ return t509->priv;
+}
+
+/*
+ * t509 utility functions
+ *
+ */
+
+static inline void t509_set_id_port ( void ) {
+ outb ( 0x00, t509_id_port );
+}
+
+static inline void t509_wait_for_id_sequence ( void ) {
+ outb ( 0x00, t509_id_port );
+}
+
+static inline void t509_global_reset ( void ) {
+ outb ( 0xc0, t509_id_port );
+}
+
+static inline void t509_reset_tag ( void ) {
+ outb ( 0xd0, t509_id_port );
+}
+
+static inline void t509_set_tag ( uint8_t tag ) {
+ outb ( 0xd0 | tag, t509_id_port );
+}
+
+static inline void t509_select_tag ( uint8_t tag ) {
+ outb ( 0xd8 | tag, t509_id_port );
+}
+
+static inline void t509_activate ( uint16_t ioaddr ) {
+ outb ( 0xe0 | ( ioaddr >> 4 ), t509_id_port );
+}
+
+static inline void t509_deactivate_and_reset_tag ( uint16_t ioaddr ) {
+ outb ( GLOBAL_RESET, ioaddr + EP_COMMAND );
+}
+
+static inline void t509_load_eeprom_word ( uint8_t offset ) {
+ outb ( 0x80 | offset, t509_id_port );
+}
+
+/*
+ * Find a suitable ID port
+ *
+ */
+static inline int t509_find_id_port ( void ) {
+
+ for ( t509_id_port = EP_ID_PORT_START ;
+ t509_id_port < EP_ID_PORT_END ;
+ t509_id_port += EP_ID_PORT_INC ) {
+ t509_set_id_port ();
+ /* See if anything's listening */
+ outb ( 0xff, t509_id_port );
+ if ( inb ( t509_id_port ) & 0x01 ) {
+ /* Found a suitable port */
+ DBG ( "T509 using ID port at %04x\n", t509_id_port );
+ return 0;
+ }
+ }
+ /* No id port available */
+ DBG ( "T509 found no available ID port\n" );
+ return -ENOENT;
+}
+
+/*
+ * Send ID sequence to the ID port
+ *
+ */
+static void t509_send_id_sequence ( void ) {
+ unsigned short lrs_state, i;
+
+ t509_set_id_port ();
+ /* Reset IDS on cards */
+ t509_wait_for_id_sequence ();
+ lrs_state = 0xff;
+ for ( i = 0; i < 255; i++ ) {
+ outb ( lrs_state, t509_id_port );
+ lrs_state <<= 1;
+ lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+ }
+}
+
+/*
+ * We get eeprom data from the id_port given an offset into the eeprom.
+ * Basically; after the ID_sequence is sent to all of the cards; they enter
+ * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
+ * the eeprom data. We then read the port 16 times and with every read; the
+ * cards check for contention (ie: if one card writes a 0 bit and another
+ * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
+ * compares the data on the bus; if there is a difference then that card goes
+ * into ID_WAIT state again). In the meantime; one bit of data is returned in
+ * the AX register which is conveniently returned to us by inb(). Hence; we
+ * read 16 times getting one bit of data with each read.
+ */
+static uint16_t t509_id_read_eeprom ( int offset ) {
+ int i, data = 0;
+
+ t509_load_eeprom_word ( offset );
+ /* Do we really need this wait? Won't be noticeable anyway */
+ udelay(10000);
+
+ for ( i = 0; i < 16; i++ ) {
+ data = ( data << 1 ) | ( inw ( t509_id_port ) & 1 );
+ }
+ return data;
+}
+
+/*
+ * Isolate and tag all t509 cards
+ *
+ */
+static int t509_isolate ( void ) {
+ unsigned int i;
+ uint16_t contend[3];
+ int rc;
+
+ /* Find a suitable ID port */
+ if ( ( rc = t509_find_id_port() ) != 0 )
+ return rc;
+
+ while ( 1 ) {
+
+ /* All cards are in ID_WAIT state each time we go
+ * through this loop.
+ */
+
+ /* Send the ID sequence */
+ t509_send_id_sequence();
+
+ /* First time through, reset all tags. On subsequent
+ * iterations, kill off any already-tagged cards
+ */
+ if ( t509_max_tag == 0 ) {
+ t509_reset_tag();
+ } else {
+ t509_select_tag ( 0 );
+ }
+
+ /* Read the manufacturer ID, to see if there are any
+ * more cards
+ */
+ if ( t509_id_read_eeprom ( EEPROM_MFG_ID ) != MFG_ID ) {
+ DBG ( "T509 saw %s signs of life\n",
+ t509_max_tag ? "no further" : "no" );
+ break;
+ }
+
+ /* Perform contention selection on the MAC address */
+ for ( i = 0 ; i < 3 ; i++ ) {
+ contend[i] = t509_id_read_eeprom ( i );
+ }
+
+ /* Only one device will still be left alive. Tag it. */
+ ++t509_max_tag;
+ DBG ( "T509 found card %04x%04x%04x, assigning tag %02x\n",
+ contend[0], contend[1], contend[2], t509_max_tag );
+ t509_set_tag ( t509_max_tag );
+
+ /* Return all cards back to ID_WAIT state */
+ t509_wait_for_id_sequence();
+ }
+
+ DBG ( "T509 found %d cards using ID port %04x\n",
+ t509_max_tag, t509_id_port );
+ return 0;
+}
+
+/*
+ * Activate a T509 device
+ *
+ * The device will be enabled at whatever ioaddr is specified in the
+ * struct t509_device; there is no need to stick with the default
+ * ioaddr read from the EEPROM.
+ *
+ */
+static inline void activate_t509_device ( struct t509_device *t509 ) {
+ t509_send_id_sequence ();
+ t509_select_tag ( t509->tag );
+ t509_activate ( t509->ioaddr );
+ DBG ( "T509 activated device %02x at ioaddr %04x\n",
+ t509->tag, t509->ioaddr );
+}
+
+/*
+ * Deactivate a T509 device
+ *
+ * Disabling also clears the tag, so we immediately isolate and re-tag
+ * this card.
+ *
+ */
+static inline void deactivate_t509_device ( struct t509_device *t509 ) {
+ t509_deactivate_and_reset_tag ( t509->ioaddr );
+ udelay ( 1000 );
+ t509_send_id_sequence ();
+ t509_select_tag ( 0 );
+ t509_set_tag ( t509->tag );
+ t509_wait_for_id_sequence ();
+ DBG ( "T509 deactivated device at %04x and re-tagged as %02x\n",
+ t509->ioaddr, t509->tag );
+}
+
+/*
+ * The ISA probe function
+ *
+ */
+static int legacy_t509_probe ( struct nic *nic, void *hwdev ) {
+ struct t509_device *t509 = hwdev;
+
+ /* We could change t509->ioaddr if we wanted to */
+ activate_t509_device ( t509 );
+ nic->ioaddr = t509->ioaddr;
+
+ /* Hand off to generic t5x9 probe routine */
+ return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
+}
+
+static void legacy_t509_disable ( struct nic *nic, void *hwdev ) {
+ struct t509_device *t509 = hwdev;
+
+ t5x9_disable ( nic );
+ deactivate_t509_device ( t509 );
+}
+
+static inline void legacy_t509_set_drvdata ( void *hwdev, void *priv ) {
+ t509_set_drvdata ( hwdev, priv );
+}
+
+static inline void * legacy_t509_get_drvdata ( void *hwdev ) {
+ return t509_get_drvdata ( hwdev );
+}
+
+/**
+ * Probe a 3c509 device
+ *
+ * @v t509 3c509 device
+ * @ret rc Return status code
+ *
+ * Searches for a driver for the 3c509 device. If a driver is found,
+ * its probe() routine is called.
+ */
+static int t509_probe ( struct t509_device *t509 ) {
+ DBG ( "Adding 3c509 device %02x (I/O %04x)\n",
+ t509->tag, t509->ioaddr );
+ return legacy_probe ( t509, legacy_t509_set_drvdata, &t509->dev,
+ legacy_t509_probe, legacy_t509_disable );
+}
+
+/**
+ * Remove a 3c509 device
+ *
+ * @v t509 3c509 device
+ */
+static void t509_remove ( struct t509_device *t509 ) {
+ legacy_remove ( t509, legacy_t509_get_drvdata, legacy_t509_disable );
+ DBG ( "Removed 3c509 device %02x\n", t509->tag );
+}
+
+/**
+ * Probe 3c509 root bus
+ *
+ * @v rootdev 3c509 bus root device
+ *
+ * Scans the 3c509 bus for devices and registers all devices it can
+ * find.
+ */
+static int t509bus_probe ( struct root_device *rootdev ) {
+ struct t509_device *t509 = NULL;
+ unsigned int tag;
+ unsigned int iobase;
+ int rc;
+
+ /* Perform isolation and tagging */
+ if ( ( rc = t509_isolate() ) != 0 )
+ return rc;
+
+ for ( tag = 1 ; tag <= t509_max_tag ; tag++ ) {
+ /* Allocate struct t509_device */
+ if ( ! t509 )
+ t509 = malloc ( sizeof ( *t509 ) );
+ if ( ! t509 ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( t509, 0, sizeof ( *t509 ) );
+ t509->tag = tag;
+
+ /* Send the ID sequence */
+ t509_send_id_sequence ();
+
+ /* Select the specified tag */
+ t509_select_tag ( t509->tag );
+
+ /* Read the default I/O address */
+ iobase = t509_id_read_eeprom ( EEPROM_ADDR_CFG );
+ t509->ioaddr = 0x200 + ( ( iobase & 0x1f ) << 4 );
+
+ /* Send card back to ID_WAIT */
+ t509_wait_for_id_sequence();
+
+ /* Add to device hierarchy */
+ snprintf ( t509->dev.name, sizeof ( t509->dev.name ),
+ "t509%02x", tag );
+ t509->dev.desc.bus_type = BUS_TYPE_ISA;
+ t509->dev.desc.vendor = MFG_ID;
+ t509->dev.desc.device = PROD_ID;
+ t509->dev.parent = &rootdev->dev;
+ list_add ( &t509->dev.siblings, &rootdev->dev.children );
+ INIT_LIST_HEAD ( &t509->dev.children );
+
+ /* Look for a driver */
+ if ( t509_probe ( t509 ) == 0 ) {
+ /* t509dev registered, we can drop our ref */
+ t509 = NULL;
+ } else {
+ /* Not registered; re-use struct */
+ list_del ( &t509->dev.siblings );
+ }
+ }
+
+ free ( t509 );
+ return 0;
+
+ err:
+ free ( t509 );
+ t509bus_remove ( rootdev );
+ return rc;
+}
+
+/**
+ * Remove 3c509 root bus
+ *
+ * @v rootdev 3c509 bus root device
+ */
+static void t509bus_remove ( struct root_device *rootdev ) {
+ struct t509_device *t509;
+ struct t509_device *tmp;
+
+ list_for_each_entry_safe ( t509, tmp, &rootdev->dev.children,
+ dev.siblings ) {
+ t509_remove ( t509 );
+ list_del ( &t509->dev.siblings );
+ free ( t509 );
+ }
+}
+
+/** 3c509 bus root device driver */
+static struct root_driver t509_root_driver = {
+ .probe = t509bus_probe,
+ .remove = t509bus_remove,
+};
+
+/** 3c509 bus root device */
+struct root_device t509_root_device __root_device = {
+ .dev = { .name = "3c509" },
+ .driver = &t509_root_driver,
+};
+
+ISA_ROM ( "3c509", "3c509" );
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.h
new file mode 100644
index 0000000..f030d4b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c509.h
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by:
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+FILE_LICENCE ( BSD3 );
+
+#include "nic.h"
+
+/*
+ * Ethernet software status per interface.
+ */
+/*
+ * Some global constants
+ */
+
+#define TX_INIT_RATE 16
+#define TX_INIT_MAX_RATE 64
+#define RX_INIT_LATENCY 64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL 4
+
+#define EEPROMSIZE 0x40
+#define MAX_EEPROMBUSY 1000
+#define EP_ID_PORT_START 0x110 /* avoid 0x100 to avoid conflict with SB16 */
+#define EP_ID_PORT_INC 0x10
+#define EP_ID_PORT_END 0x200
+#define EP_TAG_MAX 0x7 /* must be 2^n - 1 */
+
+/*
+ * Commands to read/write EEPROM trough EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */
+#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY (1<<15)
+#define EEPROM_TST_MODE (1<<14)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+#define GO_WINDOW(b,x) outw(WINDOW_SELECT|(x), (b)+EP_COMMAND)
+
+/**************************************************************************
+ *
+ * These define the EEPROM data structure. They are used in the probe
+ * function to verify the existance of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0 0x0 /* Word */
+#define EEPROM_NODE_ADDR_1 0x1 /* Word */
+#define EEPROM_NODE_ADDR_2 0x2 /* Word */
+#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID 0x7 /* 0x6d50 */
+#define EEPROM_ADDR_CFG 0x8 /* Base addr */
+#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */
+
+/**************************************************************************
+ *
+ * These are the registers for the 3Com 3c509 and their bit patterns when
+ * applicable. They have been taken out the the "EtherLink III Parallel
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual
+ * from 3com.
+ *
+ * Getting this document out of 3Com is almost impossible. However,
+ * archived copies are available at
+ * http://www.osdever.net/cottontail/downloads/docs/3c5x9b.zip and
+ * several other places on the web (search for 3c5x9b.pdf).
+ *
+ **************************************************************************/
+
+#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a
+ * command reg. */
+#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status
+ * reg. */
+#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window
+ * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define EP_W0_EEPROM_DATA 0x0c
+#define EP_W0_EEPROM_COMMAND 0x0a
+#define EP_W0_RESOURCE_CFG 0x08
+#define EP_W0_ADDRESS_CFG 0x06
+#define EP_W0_CONFIG_CTRL 0x04
+/* Read */
+#define EP_W0_PRODUCT_ID 0x02
+#define EP_W0_MFG_ID 0x00
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define EP_W1_TX_PIO_WR_2 0x02
+#define EP_W1_TX_PIO_WR_1 0x00
+/* Read */
+#define EP_W1_FREE_TX 0x0c
+#define EP_W1_TX_STATUS 0x0b /* byte */
+#define EP_W1_TIMER 0x0a /* byte */
+#define EP_W1_RX_STATUS 0x08
+#define EP_W1_RX_PIO_RD_2 0x02
+#define EP_W1_RX_PIO_RD_1 0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define EP_W2_ADDR_5 0x05
+#define EP_W2_ADDR_4 0x04
+#define EP_W2_ADDR_3 0x03
+#define EP_W2_ADDR_2 0x02
+#define EP_W2_ADDR_1 0x01
+#define EP_W2_ADDR_0 0x00
+
+/*
+ * Window 3 registers. FIFO Management.
+ */
+/* Read */
+#define EP_W3_FREE_TX 0x0c
+#define EP_W3_FREE_RX 0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define EP_W4_MEDIA_TYPE 0x0a
+#define EP_W4_CTRLR_STATUS 0x08
+#define EP_W4_NET_DIAG 0x06
+#define EP_W4_FIFO_DIAG 0x04
+#define EP_W4_HOST_DIAG 0x02
+#define EP_W4_TX_DIAG 0x00
+
+/*
+ * Window 5 Registers. Results and Internal status.
+ */
+/* Read */
+#define EP_W5_READ_0_MASK 0x0c
+#define EP_W5_INTR_MASK 0x0a
+#define EP_W5_RX_FILTER 0x08
+#define EP_W5_RX_EARLY_THRESH 0x06
+#define EP_W5_TX_AVAIL_THRESH 0x02
+#define EP_W5_TX_START_THRESH 0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK 0x0c
+#define RX_TOTAL_OK 0x0a
+#define TX_DEFERRALS 0x08
+#define RX_FRAMES_OK 0x07
+#define TX_FRAMES_OK 0x06
+#define RX_OVERRUNS 0x05
+#define TX_COLLISIONS 0x04
+#define TX_AFTER_1_COLLISION 0x03
+#define TX_AFTER_X_COLLISIONS 0x02
+#define TX_NO_SQE 0x01
+#define TX_CD_LOST 0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ * 15-11: 5-bit code for command to be executed.
+ * 10-0: 11-bit arg if any. For commands with no args;
+ * this can be set to anything.
+ */
+#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms
+ * after issuing */
+#define WINDOW_SELECT (unsigned short) (0x1<<11)
+#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to
+ * determine whether
+ * this is needed. If
+ * so; wait 800 uSec
+ * before using trans-
+ * ceiver. */
+#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on
+ * power-up */
+#define RX_ENABLE (unsigned short) (0x4<<11)
+#define RX_RESET (unsigned short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11)
+#define TX_ENABLE (unsigned short) (0x9<<11)
+#define TX_DISABLE (unsigned short) (0xa<<11)
+#define TX_RESET (unsigned short) (0xb<<11)
+#define REQ_INTR (unsigned short) (0xc<<11)
+#define SET_INTR_MASK (unsigned short) (0xe<<11)
+#define SET_RD_0_MASK (unsigned short) (0xf<<11)
+#define SET_RX_FILTER (unsigned short) (0x10<<11)
+#define FIL_INDIVIDUAL (unsigned short) (0x1)
+#define FIL_GROUP (unsigned short) (0x2)
+#define FIL_BRDCST (unsigned short) (0x4)
+#define FIL_ALL (unsigned short) (0x8)
+#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11)
+#define SET_TX_START_THRESH (unsigned short) (0x13<<11)
+#define STATS_ENABLE (unsigned short) (0x15<<11)
+#define STATS_DISABLE (unsigned short) (0x16<<11)
+#define STOP_TRANSCEIVER (unsigned short) (0x17<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything. See the manual.
+ */
+#define ACK_INTR (unsigned short) (0x6800)
+#define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1)
+#define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2)
+#define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4)
+#define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8)
+#define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10)
+#define C_RX_EARLY (unsigned short) (ACK_INTR|0x20)
+#define C_INT_RQD (unsigned short) (ACK_INTR|0x40)
+#define C_UPD_STATS (unsigned short) (ACK_INTR|0x80)
+
+/*
+ * Status register. All windows.
+ *
+ * 15-13: Window number(0-7).
+ * 12: Command_in_progress.
+ * 11: reserved.
+ * 10: reserved.
+ * 9: reserved.
+ * 8: reserved.
+ * 7: Update Statistics.
+ * 6: Interrupt Requested.
+ * 5: RX Early.
+ * 4: RX Complete.
+ * 3: TX Available.
+ * 2: TX Complete.
+ * 1: Adapter Failure.
+ * 0: Interrupt Latch.
+ */
+#define S_INTR_LATCH (unsigned short) (0x1)
+#define S_CARD_FAILURE (unsigned short) (0x2)
+#define S_TX_COMPLETE (unsigned short) (0x4)
+#define S_TX_AVAIL (unsigned short) (0x8)
+#define S_RX_COMPLETE (unsigned short) (0x10)
+#define S_RX_EARLY (unsigned short) (0x20)
+#define S_INT_RQD (unsigned short) (0x40)
+#define S_UPD_STATS (unsigned short) (0x80)
+#define S_5_INTS (S_CARD_FAILURE|S_TX_COMPLETE|\
+ S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY)
+#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000)
+
+/*
+ * FIFO Registers.
+ * RX Status. Window 1/Port 08
+ *
+ * 15: Incomplete or FIFO empty.
+ * 14: 1: Error in RX Packet 0: Incomplete or no error.
+ * 13-11: Type of error.
+ * 1000 = Overrun.
+ * 1011 = Run Packet Error.
+ * 1100 = Alignment Error.
+ * 1101 = CRC Error.
+ * 1001 = Oversize Packet Error (>1514 bytes)
+ * 0010 = Dribble Bits.
+ * (all other error codes, no errors.)
+ *
+ * 10-0: RX Bytes (0-1514)
+ */
+#define ERR_RX_INCOMPLETE (unsigned short) (0x1<<15)
+#define ERR_RX (unsigned short) (0x1<<14)
+#define ERR_RX_OVERRUN (unsigned short) (0x8<<11)
+#define ERR_RX_RUN_PKT (unsigned short) (0xb<<11)
+#define ERR_RX_ALIGN (unsigned short) (0xc<<11)
+#define ERR_RX_CRC (unsigned short) (0xd<<11)
+#define ERR_RX_OVERSIZE (unsigned short) (0x9<<11)
+#define ERR_RX_DRIBBLE (unsigned short) (0x2<<11)
+
+/*
+ * FIFO Registers.
+ * TX Status. Window 1/Port 0B
+ *
+ * Reports the transmit status of a completed transmission. Writing this
+ * register pops the transmit completion stack.
+ *
+ * Window 1/Port 0x0b.
+ *
+ * 7: Complete
+ * 6: Interrupt on successful transmission requested.
+ * 5: Jabber Error (TP Only, TX Reset required. )
+ * 4: Underrun (TX Reset required. )
+ * 3: Maximum Collisions.
+ * 2: TX Status Overflow.
+ * 1-0: Undefined.
+ *
+ */
+#define TXS_COMPLETE 0x80
+#define TXS_SUCCES_INTR_REQ 0x40
+#define TXS_JABBER 0x20
+#define TXS_UNDERRUN 0x10
+#define TXS_MAX_COLLISION 0x8
+#define TXS_STATUS_OVERFLOW 0x4
+
+/*
+ * Configuration control register.
+ * Window 0/Port 04
+ */
+/* Read */
+#define IS_AUI (1<<13)
+#define IS_BNC (1<<12)
+#define IS_UTP (1<<9)
+/* Write */
+#define ENABLE_DRQ_IRQ 0x0001
+#define W0_P4_CMD_RESET_ADAPTER 0x4
+#define W0_P4_CMD_ENABLE_ADAPTER 0x1
+/*
+ * Media type and status.
+ * Window 4/Port 0A
+ */
+#define ENABLE_UTP 0xc0
+#define DISABLE_UTP 0x0
+
+/*
+ * Resource control register
+ */
+
+#define SET_IRQ(i) ( ((i)<<12) | 0xF00) /* set IRQ i */
+
+/*
+ * Receive status register
+ */
+
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+#define RX_ERROR 0x4000
+#define RX_INCOMPLETE 0x8000
+
+/*
+ * Misc defines for various things.
+ */
+#define MFG_ID 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */
+#define PROD_ID 0x9150
+
+#define AUI 0x1
+#define BNC 0x2
+#define UTP 0x4
+
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+
+/*
+ * Function shared between 3c509.c and 3c529.c
+ */
+extern int t5x9_probe ( struct nic *nic,
+ uint16_t prod_id_check, uint16_t prod_id_mask );
+extern void t5x9_disable ( struct nic *nic );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c515.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c515.c
new file mode 100644
index 0000000..eb9569f
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c515.c
@@ -0,0 +1,763 @@
+/*
+* 3c515.c -- 3COM 3C515 Fast Etherlink ISA 10/100BASE-TX driver for etherboot
+* Copyright (C) 2002 Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code:
+* Copyright (C) 1997-2002 Donald Becker 3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux.
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) ISAPNP Tools
+* Copyright (c) 2002 Jaroslav Kysela <perex@suse.cz> ISA Plug & Play support Linux Kernel
+* Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp> etherboot-5.0.5 3c595.c
+* Coptright (C) 1995 Martin Renters etherboot-5.0.5 3c509.c
+* Copyright (C) 1999 LightSys Technology Services, Inc. etherboot-5.0.5 3c90x.c
+* Portions Copyright (C) 1999 Steve Smith etherboot-5.0.5 3c90x.c
+*
+* The probe and reset functions and defines are direct copies from the
+* Becker code modified where necessary to make it work for etherboot
+*
+* The poll and transmit functions either contain code from or were written by referencing
+* the above referenced etherboot drivers. This driver would not have been
+* possible without this prior work
+*
+* REVISION HISTORY:
+* ================
+* v0.10 4-17-2002 TJL Initial implementation.
+* v0.11 4-17-2002 TJL Cleanup of the code
+* v0.12 4-26-2002 TJL Added ISA Plug and Play for Non-PNP Bioses
+* v0.13 6-10-2002 TJL Fixed ISA_PNP MAC Address problem
+* v0.14 9-23-2003 TJL Replaced delay with currticks
+*
+* Indent Options: indent -kr -i8
+* *********************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+#include <gpxe/isapnp.h>
+#include <gpxe/isa.h> /* for ISA_ROM */
+#include <gpxe/ethernet.h>
+
+static void t3c515_wait(unsigned int nticks)
+{
+ unsigned int to = currticks() + nticks;
+ while (currticks() < to)
+ /* wait */ ;
+}
+
+/* TJL definations */
+#define HZ 100
+static int if_port;
+static struct corkscrew_private *vp;
+/* Brought directly from 3c515.c by Becker */
+#define CORKSCREW 1
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt.
+static int max_interrupt_work = 20;
+*/
+
+/* Enable the automatic media selection code -- usually set. */
+#define AUTOMEDIA 1
+
+/* Allow the use of fragment bus master transfers instead of only
+ programmed-I/O for Vortex cards. Full-bus-master transfers are always
+ enabled by default on Boomerang cards. If VORTEX_BUS_MASTER is defined,
+ the feature may be turned on using 'options'. */
+#define VORTEX_BUS_MASTER
+
+/* A few values that may be tweaked. */
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE 16
+#define RX_RING_SIZE 16
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
+
+/* "Knobs" for adjusting internal parameters. */
+/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
+#define DRIVER_DEBUG 1
+/* Some values here only for performance evaluation and path-coverage
+ debugging.
+static int rx_nocopy, rx_copy, queued_packet;
+*/
+
+#define CORKSCREW_ID 10
+
+#define EL3WINDOW(win_num) \
+ outw(SelectWindow + (win_num), nic->ioaddr + EL3_CMD)
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+
+enum corkscrew_cmd {
+ TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
+ RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
+ UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
+ DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
+ RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
+ 10 << 11, TxReset = 11 << 11,
+ FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
+ SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
+ 17 << 11,
+ SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
+ StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
+ 21 << 11,
+ StatsDisable = 22 << 11, StopCoax = 23 << 11,
+};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+ RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
+};
+
+/* Bits in the general status register. */
+enum corkscrew_status {
+ IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
+ TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+ IntReq = 0x0040, StatsFull = 0x0080,
+ DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
+ DMAInProgress = 1 << 11, /* DMA controller is still busy. */
+ CmdInProgress = 1 << 12, /* EL3_CMD is still busy. */
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+ On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
+enum Window1 {
+ TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
+ RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
+ TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
+};
+enum Window0 {
+ Wn0IRQ = 0x08,
+#if defined(CORKSCREW)
+ Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */
+ Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
+#else
+ Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */
+ Wn0EepromData = 12, /* Window 0: EEPROM results register. */
+#endif
+};
+enum Win0_EEPROM_bits {
+ EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
+ EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
+ EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
+};
+
+enum Window3 { /* Window 3: MAC/config bits. */
+ Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
+};
+union wn3_config {
+ int i;
+ struct w3_config_fields {
+ unsigned int ram_size:3, ram_width:1, ram_speed:2,
+ rom_size:2;
+ int pad8:8;
+ unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1,
+ autoselect:1;
+ int pad24:7;
+ } u;
+};
+
+enum Window4 {
+ Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */
+};
+enum Win4_Media_bits {
+ Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */
+ Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */
+ Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */
+ Media_LnkBeat = 0x0800,
+};
+enum Window7 { /* Window 7: Bus Master control. */
+ Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+};
+
+/* Boomerang-style bus master control registers. Note ISA aliases! */
+enum MasterCtrl {
+ PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
+ 0x40c,
+ TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
+};
+
+/* The Rx and Tx descriptor lists.
+ Caution Alpha hackers: these types are 32 bits! Note also the 8 byte
+ alignment contraint on tx_ring[] and rx_ring[]. */
+struct boom_rx_desc {
+ u32 next;
+ s32 status;
+ u32 addr;
+ s32 length;
+};
+
+/* Values for the Rx status entry. */
+enum rx_desc_status {
+ RxDComplete = 0x00008000, RxDError = 0x4000,
+ /* See boomerang_rx() for actual error bits */
+};
+
+struct boom_tx_desc {
+ u32 next;
+ s32 status;
+ u32 addr;
+ s32 length;
+};
+
+struct corkscrew_private {
+ const char *product_name;
+ struct net_device *next_module;
+ /* The Rx and Tx rings are here to keep them quad-word-aligned. */
+ struct boom_rx_desc rx_ring[RX_RING_SIZE];
+ struct boom_tx_desc tx_ring[TX_RING_SIZE];
+ /* The addresses of transmit- and receive-in-place skbuffs. */
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+ struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
+ int capabilities; /* Adapter capabilities word. */
+ int options; /* User-settable misc. driver options. */
+ int last_rx_packets; /* For media autoselection. */
+ unsigned int available_media:8, /* From Wn3_Options */
+ media_override:3, /* Passed-in media type. */
+ default_media:3, /* Read from the EEPROM. */
+ full_duplex:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */
+ full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */
+ tx_full:1;
+};
+
+/* The action to take with a media selection timer tick.
+ Note that we deviate from the 3Com order by checking 10base2 before AUI.
+ */
+enum xcvr_types {
+ XCVR_10baseT =
+ 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+ XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
+};
+
+static struct media_table {
+ char *name;
+ unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */
+ mask:8, /* The transceiver-present bit in Wn3_Config. */
+ next:8; /* The media type to try next. */
+ short wait; /* Time before we check media status. */
+} media_tbl[] = {
+ {
+ "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10}
+ , {
+ "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10}
+ , {
+ "undefined", 0, 0x80, XCVR_10baseT, 10000}
+ , {
+ "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10}
+ , {
+ "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx,
+ (14 * HZ) / 10}
+ , {
+ "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10}
+ , {
+ "MII", 0, 0x40, XCVR_10baseT, 3 * HZ}
+ , {
+ "undefined", 0, 0x01, XCVR_10baseT, 10000}
+ , {
+ "Default", 0, 0xFF, XCVR_10baseT, 10000}
+,};
+
+/* TILEG Modified to remove reference to dev */
+static int corkscrew_found_device(int ioaddr, int irq, int product_index,
+ int options, struct nic *nic);
+static int corkscrew_probe1(int ioaddr, int irq, int product_index,
+ struct nic *nic);
+
+/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
+/* Note: this is the only limit on the number of cards supported!! */
+static int options = -1;
+
+/* End Brought directly from 3c515.c by Becker */
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void t515_reset(struct nic *nic)
+{
+ union wn3_config config;
+ int i;
+
+ /* Before initializing select the active media port. */
+ EL3WINDOW(3);
+ if (vp->full_duplex)
+ outb(0x20, nic->ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
+ config.i = inl(nic->ioaddr + Wn3_Config);
+
+ if (vp->media_override != 7) {
+ DBG ( "Media override to transceiver %d (%s).\n",
+ vp->media_override,
+ media_tbl[vp->media_override].name);
+ if_port = vp->media_override;
+ } else if (vp->autoselect) {
+ /* Find first available media type, starting with 100baseTx. */
+ if_port = 4;
+ while (!(vp->available_media & media_tbl[if_port].mask))
+ if_port = media_tbl[if_port].next;
+
+ DBG ( "Initial media type %s.\n",
+ media_tbl[if_port].name);
+ } else
+ if_port = vp->default_media;
+
+ config.u.xcvr = if_port;
+ outl(config.i, nic->ioaddr + Wn3_Config);
+
+ DBG ( "corkscrew_open() InternalConfig 0x%hX.\n",
+ config.i);
+
+ outw(TxReset, nic->ioaddr + EL3_CMD);
+ for (i = 20; i >= 0; i--)
+ if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
+ break;
+
+ outw(RxReset, nic->ioaddr + EL3_CMD);
+ /* Wait a few ticks for the RxReset command to complete. */
+ for (i = 20; i >= 0; i--)
+ if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
+ break;
+
+ outw(SetStatusEnb | 0x00, nic->ioaddr + EL3_CMD);
+
+#ifdef debug_3c515
+ EL3WINDOW(4);
+ DBG ( "FIXME: fix print for irq, not 9" );
+ DBG ( "corkscrew_open() irq %d media status 0x%hX.\n",
+ 9, inw(nic->ioaddr + Wn4_Media) );
+#endif
+
+ /* Set the station address and mask in window 2 each time opened. */
+ EL3WINDOW(2);
+ for (i = 0; i < 6; i++)
+ outb(nic->node_addr[i], nic->ioaddr + i);
+ for (; i < 12; i += 2)
+ outw(0, nic->ioaddr + i);
+
+ if (if_port == 3)
+ /* Start the thinnet transceiver. We should really wait 50ms... */
+ outw(StartCoax, nic->ioaddr + EL3_CMD);
+ EL3WINDOW(4);
+ outw((inw(nic->ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
+ media_tbl[if_port].media_bits, nic->ioaddr + Wn4_Media);
+
+ /* Switch to the stats window, and clear all stats by reading. */
+/* outw(StatsDisable, nic->ioaddr + EL3_CMD);*/
+ EL3WINDOW(6);
+ for (i = 0; i < 10; i++)
+ inb(nic->ioaddr + i);
+ inw(nic->ioaddr + 10);
+ inw(nic->ioaddr + 12);
+ /* New: On the Vortex we must also clear the BadSSD counter. */
+ EL3WINDOW(4);
+ inb(nic->ioaddr + 12);
+ /* ..and on the Boomerang we enable the extra statistics bits. */
+ outw(0x0040, nic->ioaddr + Wn4_NetDiag);
+
+ /* Switch to register set 7 for normal use. */
+ EL3WINDOW(7);
+
+ /* Temporarily left in place. If these FIXMEs are printed
+ it meand that special logic for that card may need to be added
+ see Becker's 3c515.c driver */
+ if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+ printf("FIXME: Is this if necessary");
+ vp->cur_rx = vp->dirty_rx = 0;
+ DBG ( " Filling in the Rx ring.\n" );
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ printf("FIXME: Is this if necessary");
+ }
+ }
+ if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
+ vp->cur_tx = vp->dirty_tx = 0;
+ outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold); /* Room for a packet. */
+ /* Clear the Tx ring. */
+ for (i = 0; i < TX_RING_SIZE; i++)
+ vp->tx_skbuff[i] = 0;
+ outl(0, nic->ioaddr + DownListPtr);
+ }
+ /* Set receiver mode: presumably accept b-case and phys addr only. */
+ outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
+ nic->ioaddr + EL3_CMD);
+
+ outw(RxEnable, nic->ioaddr + EL3_CMD); /* Enable the receiver. */
+ outw(TxEnable, nic->ioaddr + EL3_CMD); /* Enable transmitter. */
+ /* Allow status bits to be seen. */
+ outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
+ (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+ (vp->full_bus_master_rx ? UpComplete : RxComplete) |
+ (vp->bus_master ? DMADone : 0), nic->ioaddr + EL3_CMD);
+ /* Ack all pending events, and set active indicator mask. */
+ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+ nic->ioaddr + EL3_CMD);
+ outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
+ | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
+ nic->ioaddr + EL3_CMD);
+
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int t515_poll(struct nic *nic, int retrieve)
+{
+ short status, cst;
+ register short rx_fifo;
+
+ cst = inw(nic->ioaddr + EL3_STATUS);
+
+ if ((cst & RxComplete) == 0) {
+ /* Ack all pending events, and set active indicator mask. */
+ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+ nic->ioaddr + EL3_CMD);
+ outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete |
+ StatsFull | (vp->
+ bus_master ? DMADone : 0) | UpComplete |
+ DownComplete, nic->ioaddr + EL3_CMD);
+ return 0;
+ }
+ status = inw(nic->ioaddr + RxStatus);
+
+ if (status & RxDError) {
+ printf("RxDError\n");
+ outw(RxDiscard, nic->ioaddr + EL3_CMD);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo == 0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ DBG ( "[l=%d", rx_fifo );
+ insw(nic->ioaddr + RX_FIFO, nic->packet, rx_fifo / 2);
+ if (rx_fifo & 1)
+ nic->packet[rx_fifo - 1] = inb(nic->ioaddr + RX_FIFO);
+ nic->packetlen = rx_fifo;
+
+ while (1) {
+ status = inw(nic->ioaddr + RxStatus);
+ DBG ( "0x%hX*", status );
+ rx_fifo = status & RX_BYTES_MASK;
+
+ if (rx_fifo > 0) {
+ insw(nic->ioaddr + RX_FIFO, nic->packet + nic->packetlen,
+ rx_fifo / 2);
+ if (rx_fifo & 1)
+ nic->packet[nic->packetlen + rx_fifo - 1] =
+ inb(nic->ioaddr + RX_FIFO);
+ nic->packetlen += rx_fifo;
+ DBG ( "+%d", rx_fifo );
+ }
+ if ((status & RxComplete) == 0) {
+ DBG ( "=%d", nic->packetlen );
+ break;
+ }
+ udelay(1000);
+ }
+
+ /* acknowledge reception of packet */
+ outw(RxDiscard, nic->ioaddr + EL3_CMD);
+ while (inw(nic->ioaddr + EL3_STATUS) & CmdInProgress);
+#ifdef debug_3c515
+ {
+ unsigned short type = 0;
+ type = (nic->packet[12] << 8) | nic->packet[13];
+ if (nic->packet[0] + nic->packet[1] + nic->packet[2] +
+ nic->packet[3] + nic->packet[4] + nic->packet[5] ==
+ 0xFF * ETH_ALEN)
+ DBG ( ",t=0x%hX,b]", type );
+ else
+ DBG ( ",t=0x%hX]", type );
+ }
+#endif
+
+ return 1;
+}
+
+/*************************************************************************
+ 3Com 515 - specific routines
+**************************************************************************/
+static char padmap[] = {
+ 0, 3, 2, 1
+};
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void t515_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ register int len;
+ int pad;
+ int status;
+
+ DBG ( "{l=%d,t=0x%hX}", s + ETH_HLEN, t );
+
+ /* swap bytes of type */
+ t = htons(t);
+
+ len = s + ETH_HLEN; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c515 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ Copied from 3c595. Is this true for the 3c515?
+ */
+ if (len + pad > ETH_FRAME_LEN) {
+ return;
+ }
+ /* drop acknowledgements */
+ while ((status = inb(nic->ioaddr + TxStatus)) & TxComplete) {
+ /*if(status & (TXS_UNDERRUN|0x88|TXS_STATUS_OVERFLOW)) { */
+ outw(TxReset, nic->ioaddr + EL3_CMD);
+ outw(TxEnable, nic->ioaddr + EL3_CMD);
+/* } */
+
+ outb(0x0, nic->ioaddr + TxStatus);
+ }
+
+ while (inw(nic->ioaddr + TxFree) < len + pad + 4) {
+ /* no room in FIFO */
+ }
+
+ outw(len, nic->ioaddr + TX_FIFO);
+ outw(0x0, nic->ioaddr + TX_FIFO); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(nic->ioaddr + TX_FIFO, d, ETH_ALEN / 2);
+ outsw(nic->ioaddr + TX_FIFO, nic->node_addr, ETH_ALEN / 2);
+ outw(t, nic->ioaddr + TX_FIFO);
+ outsw(nic->ioaddr + TX_FIFO, p, s / 2);
+
+ if (s & 1)
+ outb(*(p + s - 1), nic->ioaddr + TX_FIFO);
+
+ while (pad--)
+ outb(0, nic->ioaddr + TX_FIFO); /* Padding */
+
+ /* wait for Tx complete */
+ while ((inw(nic->ioaddr + EL3_STATUS) & CmdInProgress) != 0);
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void t515_disable ( struct nic *nic,
+ struct isapnp_device *isapnp ) {
+
+ t515_reset(nic);
+
+ /* This is a hack. Since ltsp worked on my
+ system without any disable functionality I
+ have no way to determine if this works */
+
+ /* Disable the receiver and transmitter. */
+ outw(RxDisable, nic->ioaddr + EL3_CMD);
+ outw(TxDisable, nic->ioaddr + EL3_CMD);
+
+ if (if_port == XCVR_10base2)
+ /* Turn off thinnet power. Green! */
+ outw(StopCoax, nic->ioaddr + EL3_CMD);
+
+
+ outw(SetIntrEnb | 0x0000, nic->ioaddr + EL3_CMD);
+
+ deactivate_isapnp_device ( isapnp );
+ return;
+}
+
+static void t515_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations t515_operations = {
+ .connect = dummy_connect,
+ .poll = t515_poll,
+ .transmit = t515_transmit,
+ .irq = t515_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+You should omit the last argument struct pci_device * for a non-PCI NIC
+***************************************************************************/
+static int t515_probe ( struct nic *nic, struct isapnp_device *isapnp ) {
+
+ /* Direct copy from Beckers 3c515.c removing any ISAPNP sections */
+
+ nic->ioaddr = isapnp->ioaddr;
+ nic->irqno = isapnp->irqno;
+ activate_isapnp_device ( isapnp );
+
+ /* Check the resource configuration for a matching ioaddr. */
+ if ((unsigned)(inw(nic->ioaddr + 0x2002) & 0x1f0)
+ != (nic->ioaddr & 0x1f0)) {
+ DBG ( "3c515 ioaddr mismatch\n" );
+ return 0;
+ }
+
+ /* Verify by reading the device ID from the EEPROM. */
+ {
+ int timer;
+ outw(EEPROM_Read + 7, nic->ioaddr + Wn0EepromCmd);
+ /* Pause for at least 162 us. for the read to take place. */
+ for (timer = 4; timer >= 0; timer--) {
+ t3c515_wait(1);
+ if ((inw(nic->ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+ break;
+ }
+ if (inw(nic->ioaddr + Wn0EepromData) != 0x6d50) {
+ DBG ( "3c515 read incorrect vendor ID from EEPROM" );
+ return 0;
+ }
+
+ }
+ DBG ( "3c515 Resource configuration register 0x%X, DCR 0x%hX.\n",
+ inl(nic->ioaddr + 0x2002), inw(nic->ioaddr + 0x2000) );
+ corkscrew_found_device(nic->ioaddr, nic->irqno, CORKSCREW_ID,
+ options, nic);
+
+ t515_reset(nic);
+ nic->nic_op = &t515_operations;
+ return 1;
+}
+
+static int
+corkscrew_found_device(int ioaddr, int irq,
+ int product_index, int options, struct nic *nic)
+{
+ /* Direct copy from Becker 3c515.c with unecessary parts removed */
+ vp->product_name = "3c515";
+ vp->options = options;
+ if (options >= 0) {
+ vp->media_override =
+ ((options & 7) == 2) ? 0 : options & 7;
+ vp->full_duplex = (options & 8) ? 1 : 0;
+ vp->bus_master = (options & 16) ? 1 : 0;
+ } else {
+ vp->media_override = 7;
+ vp->full_duplex = 0;
+ vp->bus_master = 0;
+ }
+
+ corkscrew_probe1(ioaddr, irq, product_index, nic);
+ return 0;
+}
+
+static int
+corkscrew_probe1(int ioaddr, int irq, int product_index __unused,
+ struct nic *nic)
+{
+ unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
+ int i;
+
+ printf("3Com %s at 0x%hX, ", vp->product_name, ioaddr);
+
+ /* Read the station address from the EEPROM. */
+ EL3WINDOW(0);
+ for (i = 0; i < 0x18; i++) {
+ short *phys_addr = (short *) nic->node_addr;
+ int timer;
+ outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
+ /* Pause for at least 162 us. for the read to take place. */
+ for (timer = 4; timer >= 0; timer--) {
+ t3c515_wait(1);
+ if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
+ break;
+ }
+ eeprom[i] = inw(ioaddr + Wn0EepromData);
+ DBG ( "Value %d: %hX ", i, eeprom[i] );
+ checksum ^= eeprom[i];
+ if (i < 3)
+ phys_addr[i] = htons(eeprom[i]);
+ }
+ checksum = (checksum ^ (checksum >> 8)) & 0xff;
+ if (checksum != 0x00)
+ printf(" ***INVALID CHECKSUM 0x%hX*** ", checksum);
+
+ DBG ( "%s", eth_ntoa ( nic->node_addr ) );
+
+ if (eeprom[16] == 0x11c7) { /* Corkscrew */
+
+ }
+ printf(", IRQ %d\n", irq);
+ /* Tell them about an invalid IRQ. */
+ if ( (irq <= 0 || irq > 15) ) {
+ DBG (" *** Warning: this IRQ is unlikely to work! ***\n" );
+ }
+
+ {
+ char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
+ union wn3_config config;
+ EL3WINDOW(3);
+ vp->available_media = inw(ioaddr + Wn3_Options);
+ config.i = inl(ioaddr + Wn3_Config);
+ DBG ( " Internal config register is %4.4x, "
+ "transceivers 0x%hX.\n",
+ config.i, inw(ioaddr + Wn3_Options) );
+ printf
+ (" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+ 8 << config.u.ram_size,
+ config.u.ram_width ? "word" : "byte",
+ ram_split[config.u.ram_split],
+ config.u.autoselect ? "autoselect/" : "",
+ media_tbl[config.u.xcvr].name);
+ if_port = config.u.xcvr;
+ vp->default_media = config.u.xcvr;
+ vp->autoselect = config.u.autoselect;
+ }
+ if (vp->media_override != 7) {
+ printf(" Media override to transceiver type %d (%s).\n",
+ vp->media_override,
+ media_tbl[vp->media_override].name);
+ if_port = vp->media_override;
+ }
+
+ vp->capabilities = eeprom[16];
+ vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
+ /* Rx is broken at 10mbps, so we always disable it. */
+ /* vp->full_bus_master_rx = 0; */
+ vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
+
+ return 0;
+}
+
+static struct isapnp_device_id t515_adapters[] = {
+ { "3c515 (ISAPnP)", ISAPNP_VENDOR('T','C','M'), 0x5051 },
+};
+
+ISAPNP_DRIVER ( t515_driver, t515_adapters );
+
+DRIVER ( "3c515", nic_driver, isapnp_driver, t515_driver,
+ t515_probe, t515_disable );
+
+ISA_ROM ( "3c515", "3c515 Fast EtherLink ISAPnP" );
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c529.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c529.c
new file mode 100644
index 0000000..4282464
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c529.c
@@ -0,0 +1,62 @@
+/*
+ * Split out from 3c509.c to make build process more sane
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include "etherboot.h"
+#include <gpxe/mca.h>
+#include <gpxe/isa.h> /* for ISA_ROM */
+#include "nic.h"
+#include "3c509.h"
+
+/*
+ * Several other pieces of the MCA support code were shamelessly
+ * borrowed from the Linux kernel source.
+ *
+ * MCA support added by Adam Fritzler (mid@auk.cx)
+ *
+ * Generalised out of the 3c529 driver and into a bus type by Michael
+ * Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+static int t529_probe ( struct nic *nic, struct mca_device *mca ) {
+
+ /* Retrieve NIC parameters from MCA device parameters */
+ nic->ioaddr = ( ( mca->pos[4] & 0xfc ) | 0x02 ) << 8;
+ nic->irqno = mca->pos[5] & 0x0f;
+ printf ( "3c529 board found on MCA at %#hx IRQ %d -",
+ nic->ioaddr, nic->irqno );
+
+ /* Hand off to generic t5x9 probe routine */
+ return t5x9_probe ( nic, MCA_ID ( mca ), 0xffff );
+}
+
+static void t529_disable ( struct nic *nic, struct mca_device *mca __unused ) {
+ t5x9_disable ( nic );
+}
+
+static struct mca_device_id el3_mca_adapters[] = {
+ { "3Com 3c529 EtherLink III (10base2)", 0x627c },
+ { "3Com 3c529 EtherLink III (10baseT)", 0x627d },
+ { "3Com 3c529 EtherLink III (test mode)", 0x62db },
+ { "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 },
+ { "3Com 3c529 EtherLink III (TP)", 0x62f7 },
+};
+
+MCA_DRIVER ( t529_driver, el3_mca_adapters );
+
+DRIVER ( "3c529", nic_driver, mca_driver, t529_driver,
+ t529_probe, t529_disable );
+
+ISA_ROM( "3c529", "3c529 == MCA 3c509" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.c
new file mode 100644
index 0000000..07c85d0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.c
@@ -0,0 +1,553 @@
+/*
+* 3c595.c -- 3COM 3C595 Fast Etherlink III PCI driver for etherboot
+*
+* Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
+* All rights reserved.
+* Mar. 14, 2000
+*
+* This software may be used, modified, copied, distributed, and sold, in
+* both source and binary form provided that the above copyright and these
+* terms are retained. Under no circumstances are the authors responsible for
+* the proper functioning of this software, nor do the authors assume any
+* responsibility for damages incurred with its use.
+*
+* This code is based on Martin Renters' etherboot-4.4.3 3c509.c and
+* Herb Peyerl's FreeBSD 3.4-RELEASE if_vx.c driver.
+*
+* Copyright (C) 1993-1994, David Greenman, Martin Renters.
+* Copyright (C) 1993-1995, Andres Vega Garcia.
+* Copyright (C) 1995, Serge Babkin.
+*
+* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+*
+* timlegge 08-24-2003 Add Multicast Support
+*/
+
+FILE_LICENCE ( BSD2 );
+
+/* #define EDEBUG */
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include "3c595.h"
+
+static struct nic_operations t595_operations;
+
+static unsigned short eth_nic_base;
+static unsigned short vx_connector, vx_connectors;
+
+static struct connector_entry {
+ int bit;
+ char *name;
+} conn_tab[VX_CONNECTORS] = {
+#define CONNECTOR_UTP 0
+ { 0x08, "utp"},
+#define CONNECTOR_AUI 1
+ { 0x20, "aui"},
+/* dummy */
+ { 0, "???"},
+#define CONNECTOR_BNC 3
+ { 0x10, "bnc"},
+#define CONNECTOR_TX 4
+ { 0x02, "tx"},
+#define CONNECTOR_FX 5
+ { 0x04, "fx"},
+#define CONNECTOR_MII 6
+ { 0x40, "mii"},
+ { 0, "???"}
+};
+
+static void vxgetlink(void);
+static void vxsetlink(void);
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+static void t595_reset(struct nic *nic)
+{
+ int i;
+
+ /***********************************************************
+ Reset 3Com 595 card
+ *************************************************************/
+
+ /* stop card */
+ outw(RX_DISABLE, BASE + VX_COMMAND);
+ outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(TX_DISABLE, BASE + VX_COMMAND);
+ outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
+ udelay(8000);
+ outw(RX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(TX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(C_INTR_LATCH, BASE + VX_COMMAND);
+ outw(SET_RD_0_MASK, BASE + VX_COMMAND);
+ outw(SET_INTR_MASK, BASE + VX_COMMAND);
+ outw(SET_RX_FILTER, BASE + VX_COMMAND);
+
+ /*
+ * initialize card
+ */
+ VX_BUSY_WAIT;
+
+ GO_WINDOW(0);
+
+ /* Disable the card */
+/* outw(0, BASE + VX_W0_CONFIG_CTRL); */
+
+ /* Configure IRQ to none */
+/* outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */
+
+ /* Enable the card */
+/* outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */
+
+ GO_WINDOW(2);
+
+ /* Reload the ether_addr. */
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i);
+
+ outw(RX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+ outw(TX_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+
+ /* Window 1 is operating window */
+ GO_WINDOW(1);
+ for (i = 0; i < 31; i++)
+ inb(BASE + VX_W1_TX_STATUS);
+
+ outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
+ S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
+ outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
+ S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
+
+/*
+ * Attempt to get rid of any stray interrupts that occured during
+ * configuration. On the i386 this isn't possible because one may
+ * already be queued. However, a single stray interrupt is
+ * unimportant.
+ */
+
+ outw(ACK_INTR | 0xff, BASE + VX_COMMAND);
+
+ outw(SET_RX_FILTER | FIL_INDIVIDUAL |
+ FIL_BRDCST|FIL_MULTICAST, BASE + VX_COMMAND);
+
+ vxsetlink();
+/*{
+ int i,j;
+ i = CONNECTOR_TX;
+ GO_WINDOW(3);
+ j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
+ outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS));
+ GO_WINDOW(4);
+ outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
+ GO_WINDOW(1);
+}*/
+
+ /* start tranciever and receiver */
+ outw(RX_ENABLE, BASE + VX_COMMAND);
+ outw(TX_ENABLE, BASE + VX_COMMAND);
+
+}
+
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+static char padmap[] = {
+ 0, 3, 2, 1};
+
+static void t595_transmit(
+struct nic *nic,
+const char *d, /* Destination */
+unsigned int t, /* Type */
+unsigned int s, /* size */
+const char *p) /* Packet */
+{
+ register int len;
+ int pad;
+ int status;
+
+#ifdef EDEBUG
+ printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
+#endif
+
+ /* swap bytes of type */
+ t= htons(t);
+
+ len=s+ETH_HLEN; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c595 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ */
+ if (len + pad > ETH_FRAME_LEN) {
+ return;
+ }
+
+ /* drop acknowledgements */
+ while(( status=inb(BASE + VX_W1_TX_STATUS) )& TXS_COMPLETE ) {
+ if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
+ outw(TX_RESET, BASE + VX_COMMAND);
+ outw(TX_ENABLE, BASE + VX_COMMAND);
+ }
+
+ outb(0x0, BASE + VX_W1_TX_STATUS);
+ }
+
+ while (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) {
+ /* no room in FIFO */
+ }
+
+ outw(len, BASE + VX_W1_TX_PIO_WR_1);
+ outw(0x0, BASE + VX_W1_TX_PIO_WR_1); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
+ outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
+ outw(t, BASE + VX_W1_TX_PIO_WR_1);
+ outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2);
+ if (s & 1)
+ outb(*(p+s - 1), BASE + VX_W1_TX_PIO_WR_1);
+
+ while (pad--)
+ outb(0, BASE + VX_W1_TX_PIO_WR_1); /* Padding */
+
+ /* wait for Tx complete */
+ while((inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
+ ;
+}
+
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+static int t595_poll(struct nic *nic, int retrieve)
+{
+ /* common variables */
+ /* variables for 3C595 */
+ short status, cst;
+ register short rx_fifo;
+
+ cst=inw(BASE + VX_STATUS);
+
+#ifdef EDEBUG
+ if(cst & 0x1FFF)
+ printf("-%hX-",cst);
+#endif
+
+ if( (cst & S_RX_COMPLETE)==0 ) {
+ /* acknowledge everything */
+ outw(ACK_INTR | cst, BASE + VX_COMMAND);
+ outw(C_INTR_LATCH, BASE + VX_COMMAND);
+
+ return 0;
+ }
+
+ status = inw(BASE + VX_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+
+ if (status & ERR_RX) {
+ outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo==0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ /* read packet */
+#ifdef EDEBUG
+ printf("[l=%d",rx_fifo);
+#endif
+ insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
+ nic->packetlen=rx_fifo;
+
+ while(1) {
+ status = inw(BASE + VX_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+ rx_fifo = status & RX_BYTES_MASK;
+
+ if(rx_fifo>0) {
+ insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
+ nic->packetlen+=rx_fifo;
+#ifdef EDEBUG
+ printf("+%d",rx_fifo);
+#endif
+ }
+ if(( status & RX_INCOMPLETE )==0) {
+#ifdef EDEBUG
+ printf("=%d",nic->packetlen);
+#endif
+ break;
+ }
+ udelay(1000);
+ }
+
+ /* acknowledge reception of packet */
+ outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
+ while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS);
+#ifdef EDEBUG
+{
+ unsigned short type = 0; /* used by EDEBUG */
+ type = (nic->packet[12]<<8) | nic->packet[13];
+ if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
+ nic->packet[5] == 0xFF*ETH_ALEN)
+ printf(",t=%hX,b]",type);
+ else
+ printf(",t=%hX]",type);
+}
+#endif
+ return 1;
+}
+
+
+/*************************************************************************
+ 3Com 595 - specific routines
+**************************************************************************/
+
+static int
+eeprom_rdy()
+{
+ int i;
+
+ for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)
+ udelay(1000);
+ if (i >= MAX_EEPROMBUSY) {
+ /* printf("3c595: eeprom failed to come ready.\n"); */
+ printf("3c595: eeprom is busy.\n"); /* memory in EPROM is tight */
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * get_e: gets a 16 bits word from the EEPROM. we must have set the window
+ * before
+ */
+static int
+get_e(offset)
+int offset;
+{
+ if (!eeprom_rdy())
+ return (0xffff);
+ outw(EEPROM_CMD_RD | offset, BASE + VX_W0_EEPROM_COMMAND);
+ if (!eeprom_rdy())
+ return (0xffff);
+ return (inw(BASE + VX_W0_EEPROM_DATA));
+}
+
+static void
+vxgetlink(void)
+{
+ int n, k;
+
+ GO_WINDOW(3);
+ vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f;
+ for (n = 0, k = 0; k < VX_CONNECTORS; k++) {
+ if (vx_connectors & conn_tab[k].bit) {
+ if (n > 0) {
+ printf("/");
+ }
+ printf("%s", conn_tab[k].name );
+ n++;
+ }
+ }
+ if (vx_connectors == 0) {
+ printf("no connectors!");
+ return;
+ }
+ GO_WINDOW(3);
+ vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG)
+ & INTERNAL_CONNECTOR_MASK)
+ >> INTERNAL_CONNECTOR_BITS;
+ if (vx_connector & 0x10) {
+ vx_connector &= 0x0f;
+ printf("[*%s*]", conn_tab[vx_connector].name);
+ printf(": disable 'auto select' with DOS util!");
+ } else {
+ printf("[*%s*]", conn_tab[vx_connector].name);
+ }
+}
+
+static void
+vxsetlink(void)
+{
+ int i, j;
+ char *reason, *warning;
+ static char prev_conn = -1;
+
+ if (prev_conn == -1) {
+ prev_conn = vx_connector;
+ }
+
+ i = vx_connector; /* default in EEPROM */
+ reason = "default";
+ warning = 0;
+
+ if ((vx_connectors & conn_tab[vx_connector].bit) == 0) {
+ warning = "strange connector type in EEPROM.";
+ reason = "forced";
+ i = CONNECTOR_UTP;
+ }
+
+ if (warning != 0) {
+ printf("warning: %s\n", warning);
+ }
+ printf("selected %s. (%s)\n", conn_tab[i].name, reason);
+
+ /* Set the selected connector. */
+ GO_WINDOW(3);
+ j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
+ outl(j | (i <<INTERNAL_CONNECTOR_BITS), BASE + VX_W3_INTERNAL_CFG);
+
+ /* First, disable all. */
+ outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
+ udelay(8000);
+ GO_WINDOW(4);
+ outw(0, BASE + VX_W4_MEDIA_TYPE);
+
+ /* Second, enable the selected one. */
+ switch(i) {
+ case CONNECTOR_UTP:
+ GO_WINDOW(4);
+ outw(ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE);
+ break;
+ case CONNECTOR_BNC:
+ outw(START_TRANSCEIVER,BASE + VX_COMMAND);
+ udelay(8000);
+ break;
+ case CONNECTOR_TX:
+ case CONNECTOR_FX:
+ GO_WINDOW(4);
+ outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
+ break;
+ default: /* AUI and MII fall here */
+ break;
+ }
+ GO_WINDOW(1);
+}
+
+static void t595_disable ( struct nic *nic ) {
+
+ t595_reset(nic);
+
+ outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
+ udelay(8000);
+ GO_WINDOW(4);
+ outw(0, BASE + VX_W4_MEDIA_TYPE);
+ GO_WINDOW(1);
+}
+
+static void t595_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+static int t595_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+ unsigned short *p;
+
+ if (pci->ioaddr == 0)
+ return 0;
+ eth_nic_base = pci->ioaddr;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ GO_WINDOW(0);
+ outw(GLOBAL_RESET, BASE + VX_COMMAND);
+ VX_BUSY_WAIT;
+
+ vxgetlink();
+
+/*
+ printf("\nEEPROM:");
+ for (i = 0; i < (EEPROMSIZE/2); i++) {
+ printf("%hX:", get_e(i));
+ }
+ printf("\n");
+*/
+ /*
+ * Read the station address from the eeprom
+ */
+ p = (unsigned short *) nic->node_addr;
+ for (i = 0; i < 3; i++) {
+ GO_WINDOW(0);
+ p[i] = htons(get_e(EEPROM_OEM_ADDR_0 + i));
+ GO_WINDOW(2);
+ outw(ntohs(p[i]), BASE + VX_W2_ADDR_0 + (i * 2));
+ }
+
+ DBG ( "Ethernet address: %s\n", eth_ntoa (nic->node_addr) );
+
+ t595_reset(nic);
+ nic->nic_op = &t595_operations;
+ return 1;
+
+}
+
+static struct nic_operations t595_operations = {
+ .connect = dummy_connect,
+ .poll = t595_poll,
+ .transmit = t595_transmit,
+ .irq = t595_irq,
+
+};
+
+static struct pci_device_id t595_nics[] = {
+PCI_ROM(0x10b7, 0x5900, "3c590", "3Com590", 0), /* Vortex 10Mbps */
+PCI_ROM(0x10b7, 0x5950, "3c595", "3Com595", 0), /* Vortex 100baseTx */
+PCI_ROM(0x10b7, 0x5951, "3c595-1", "3Com595", 0), /* Vortex 100baseT4 */
+PCI_ROM(0x10b7, 0x5952, "3c595-2", "3Com595", 0), /* Vortex 100base-MII */
+PCI_ROM(0x10b7, 0x9000, "3c900-tpo", "3Com900-TPO", 0), /* 10 Base TPO */
+PCI_ROM(0x10b7, 0x9001, "3c900-t4", "3Com900-Combo", 0), /* 10/100 T4 */
+PCI_ROM(0x10b7, 0x9004, "3c900b-tpo", "3Com900B-TPO", 0), /* 10 Base TPO */
+PCI_ROM(0x10b7, 0x9005, "3c900b-combo", "3Com900B-Combo", 0), /* 10 Base Combo */
+PCI_ROM(0x10b7, 0x9006, "3c900b-tpb2", "3Com900B-2/T", 0), /* 10 Base TP and Base2 */
+PCI_ROM(0x10b7, 0x900a, "3c900b-fl", "3Com900B-FL", 0), /* 10 Base F */
+PCI_ROM(0x10b7, 0x9800, "3c980-cyclone-1", "3Com980-Cyclone", 0), /* Cyclone */
+PCI_ROM(0x10b7, 0x9805, "3c9805-1", "3Com9805", 0), /* Dual Port Server Cyclone */
+PCI_ROM(0x10b7, 0x7646, "3csoho100-tx-1", "3CSOHO100-TX", 0), /* Hurricane */
+PCI_ROM(0x10b7, 0x4500, "3c450-1", "3Com450 HomePNA Tornado", 0),
+};
+
+PCI_DRIVER ( t595_driver, t595_nics, PCI_NO_CLASS );
+
+DRIVER ( "3C595", nic_driver, pci_driver, t595_driver,
+ t595_probe, t595_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.h
new file mode 100644
index 0000000..e27d204
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c595.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+FILE_LICENCE ( BSD3 );
+
+/*
+ * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the
+ * 3c590 family.
+ */
+
+/*
+ * Modified by Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
+ * for etherboot
+ * Mar. 14, 2000
+*/
+
+/*
+ * Ethernet software status per interface.
+ */
+
+/*
+ * Some global constants
+ */
+
+#define TX_INIT_RATE 16
+#define TX_INIT_MAX_RATE 64
+#define RX_INIT_LATENCY 64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL 4
+
+#define EEPROMSIZE 0x40
+#define MAX_EEPROMBUSY 1000
+#define VX_LAST_TAG 0xd7
+#define VX_MAX_BOARDS 16
+#define VX_ID_PORT 0x100
+
+/*
+ * some macros to acces long named fields
+ */
+#define BASE (eth_nic_base)
+
+/*
+ * Commands to read/write EEPROM trough EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */
+#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY (1<<15)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+
+/**************************************************************************
+ * *
+ * These define the EEPROM data structure. They are used in the probe
+ * function to verify the existence of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0 0x0 /* Word */
+#define EEPROM_NODE_ADDR_1 0x1 /* Word */
+#define EEPROM_NODE_ADDR_2 0x2 /* Word */
+#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID 0x7 /* 0x6d50 */
+#define EEPROM_ADDR_CFG 0x8 /* Base addr */
+#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */
+#define EEPROM_OEM_ADDR_0 0xa /* Word */
+#define EEPROM_OEM_ADDR_1 0xb /* Word */
+#define EEPROM_OEM_ADDR_2 0xc /* Word */
+#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */
+
+#define NO_RX_OVN_ANOMALY (1<<5)
+
+/**************************************************************************
+ * *
+ * These are the registers for the 3Com 3c509 and their bit patterns when *
+ * applicable. They have been taken out the the "EtherLink III Parallel *
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual *
+ * from 3com. *
+ * *
+ **************************************************************************/
+
+#define VX_COMMAND 0x0e /* Write. BASE+0x0e is always a
+ * command reg. */
+#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status
+ * reg. */
+#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window
+ * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define VX_W0_EEPROM_DATA 0x0c
+#define VX_W0_EEPROM_COMMAND 0x0a
+#define VX_W0_RESOURCE_CFG 0x08
+#define VX_W0_ADDRESS_CFG 0x06
+#define VX_W0_CONFIG_CTRL 0x04
+ /* Read */
+#define VX_W0_PRODUCT_ID 0x02
+#define VX_W0_MFG_ID 0x00
+
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define VX_W1_TX_PIO_WR_2 0x02
+#define VX_W1_TX_PIO_WR_1 0x00
+/* Read */
+#define VX_W1_FREE_TX 0x0c
+#define VX_W1_TX_STATUS 0x0b /* byte */
+#define VX_W1_TIMER 0x0a /* byte */
+#define VX_W1_RX_STATUS 0x08
+#define VX_W1_RX_PIO_RD_2 0x02
+#define VX_W1_RX_PIO_RD_1 0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define VX_W2_ADDR_5 0x05
+#define VX_W2_ADDR_4 0x04
+#define VX_W2_ADDR_3 0x03
+#define VX_W2_ADDR_2 0x02
+#define VX_W2_ADDR_1 0x01
+#define VX_W2_ADDR_0 0x00
+
+/*
+ * Window 3 registers. FIFO Management.
+ */
+/* Read */
+#define VX_W3_INTERNAL_CFG 0x00
+#define VX_W3_RESET_OPT 0x08
+#define VX_W3_FREE_TX 0x0c
+#define VX_W3_FREE_RX 0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define VX_W4_MEDIA_TYPE 0x0a
+#define VX_W4_CTRLR_STATUS 0x08
+#define VX_W4_NET_DIAG 0x06
+#define VX_W4_FIFO_DIAG 0x04
+#define VX_W4_HOST_DIAG 0x02
+#define VX_W4_TX_DIAG 0x00
+
+/*
+ * Window 5 Registers. Results and Internal status.
+ */
+/* Read */
+#define VX_W5_READ_0_MASK 0x0c
+#define VX_W5_INTR_MASK 0x0a
+#define VX_W5_RX_FILTER 0x08
+#define VX_W5_RX_EARLY_THRESH 0x06
+#define VX_W5_TX_AVAIL_THRESH 0x02
+#define VX_W5_TX_START_THRESH 0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK 0x0c
+#define RX_TOTAL_OK 0x0a
+#define TX_DEFERRALS 0x08
+#define RX_FRAMES_OK 0x07
+#define TX_FRAMES_OK 0x06
+#define RX_OVERRUNS 0x05
+#define TX_COLLISIONS 0x04
+#define TX_AFTER_1_COLLISION 0x03
+#define TX_AFTER_X_COLLISIONS 0x02
+#define TX_NO_SQE 0x01
+#define TX_CD_LOST 0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ * 15-11: 5-bit code for command to be executed.
+ * 10-0: 11-bit arg if any. For commands with no args;
+ * this can be set to anything.
+ */
+#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms
+ * after issuing */
+#define WINDOW_SELECT (unsigned short) (0x1<<11)
+#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to
+ * determine whether
+ * this is needed. If
+ * so; wait 800 uSec
+ * before using trans-
+ * ceiver. */
+#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on
+ * power-up */
+#define RX_ENABLE (unsigned short) (0x4<<11)
+#define RX_RESET (unsigned short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11)
+#define TX_ENABLE (unsigned short) (0x9<<11)
+#define TX_DISABLE (unsigned short) (0xa<<11)
+#define TX_RESET (unsigned short) (0xb<<11)
+#define REQ_INTR (unsigned short) (0xc<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything. See the manual.
+ */
+#define ACK_INTR (unsigned short) (0x6800)
+# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1)
+# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2)
+# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4)
+# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8)
+# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10)
+# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20)
+# define C_INT_RQD (unsigned short) (ACK_INTR|0x40)
+# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80)
+#define SET_INTR_MASK (unsigned short) (0xe<<11)
+#define SET_RD_0_MASK (unsigned short) (0xf<<11)
+#define SET_RX_FILTER (unsigned short) (0x10<<11)
+# define FIL_INDIVIDUAL (unsigned short) (0x1)
+# define FIL_MULTICAST (unsigned short) (0x02)
+# define FIL_BRDCST (unsigned short) (0x04)
+# define FIL_PROMISC (unsigned short) (0x08)
+#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11)
+#define SET_TX_START_THRESH (unsigned short) (0x13<<11)
+#define STATS_ENABLE (unsigned short) (0x15<<11)
+#define STATS_DISABLE (unsigned short) (0x16<<11)
+#define STOP_TRANSCEIVER (unsigned short) (0x17<<11)
+
+/*
+ * Status register. All windows.
+ *
+ * 15-13: Window number(0-7).
+ * 12: Command_in_progress.
+ * 11: reserved.
+ * 10: reserved.
+ * 9: reserved.
+ * 8: reserved.
+ * 7: Update Statistics.
+ * 6: Interrupt Requested.
+ * 5: RX Early.
+ * 4: RX Complete.
+ * 3: TX Available.
+ * 2: TX Complete.
+ * 1: Adapter Failure.
+ * 0: Interrupt Latch.
+ */
+#define S_INTR_LATCH (unsigned short) (0x1)
+#define S_CARD_FAILURE (unsigned short) (0x2)
+#define S_TX_COMPLETE (unsigned short) (0x4)
+#define S_TX_AVAIL (unsigned short) (0x8)
+#define S_RX_COMPLETE (unsigned short) (0x10)
+#define S_RX_EARLY (unsigned short) (0x20)
+#define S_INT_RQD (unsigned short) (0x40)
+#define S_UPD_STATS (unsigned short) (0x80)
+#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000)
+
+#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS)
+
+/* Address Config. Register.
+ * Window 0/Port 06
+ */
+
+#define ACF_CONNECTOR_BITS 14
+#define ACF_CONNECTOR_UTP 0
+#define ACF_CONNECTOR_AUI 1
+#define ACF_CONNECTOR_BNC 3
+
+#define INTERNAL_CONNECTOR_BITS 20
+#define INTERNAL_CONNECTOR_MASK 0x01700000
+
+/*
+ * FIFO Registers. RX Status.
+ *
+ * 15: Incomplete or FIFO empty.
+ * 14: 1: Error in RX Packet 0: Incomplete or no error.
+ * 13-11: Type of error.
+ * 1000 = Overrun.
+ * 1011 = Run Packet Error.
+ * 1100 = Alignment Error.
+ * 1101 = CRC Error.
+ * 1001 = Oversize Packet Error (>1514 bytes)
+ * 0010 = Dribble Bits.
+ * (all other error codes, no errors.)
+ *
+ * 10-0: RX Bytes (0-1514)
+ */
+#define ERR_INCOMPLETE (unsigned short) (0x8000)
+#define ERR_RX (unsigned short) (0x4000)
+#define ERR_MASK (unsigned short) (0x7800)
+#define ERR_OVERRUN (unsigned short) (0x4000)
+#define ERR_RUNT (unsigned short) (0x5800)
+#define ERR_ALIGNMENT (unsigned short) (0x6000)
+#define ERR_CRC (unsigned short) (0x6800)
+#define ERR_OVERSIZE (unsigned short) (0x4800)
+#define ERR_DRIBBLE (unsigned short) (0x1000)
+
+/*
+ * TX Status.
+ *
+ * Reports the transmit status of a completed transmission. Writing this
+ * register pops the transmit completion stack.
+ *
+ * Window 1/Port 0x0b.
+ *
+ * 7: Complete
+ * 6: Interrupt on successful transmission requested.
+ * 5: Jabber Error (TP Only, TX Reset required. )
+ * 4: Underrun (TX Reset required. )
+ * 3: Maximum Collisions.
+ * 2: TX Status Overflow.
+ * 1-0: Undefined.
+ *
+ */
+#define TXS_COMPLETE 0x80
+#define TXS_INTR_REQ 0x40
+#define TXS_JABBER 0x20
+#define TXS_UNDERRUN 0x10
+#define TXS_MAX_COLLISION 0x8
+#define TXS_STATUS_OVERFLOW 0x4
+
+#define RS_AUI (1<<5)
+#define RS_BNC (1<<4)
+#define RS_UTP (1<<3)
+#define RS_T4 (1<<0)
+#define RS_TX (1<<1)
+#define RS_FX (1<<2)
+#define RS_MII (1<<6)
+
+
+/*
+ * FIFO Status (Window 4)
+ *
+ * Supports FIFO diagnostics
+ *
+ * Window 4/Port 0x04.1
+ *
+ * 15: 1=RX receiving (RO). Set when a packet is being received
+ * into the RX FIFO.
+ * 14: Reserved
+ * 13: 1=RX underrun (RO). Generates Adapter Failure interrupt.
+ * Requires RX Reset or Global Reset command to recover.
+ * It is generated when you read past the end of a packet -
+ * reading past what has been received so far will give bad
+ * data.
+ * 12: 1=RX status overrun (RO). Set when there are already 8
+ * packets in the RX FIFO. While this bit is set, no additional
+ * packets are received. Requires no action on the part of
+ * the host. The condition is cleared once a packet has been
+ * read out of the RX FIFO.
+ * 11: 1=RX overrun (RO). Set when the RX FIFO is full (there
+ * may not be an overrun packet yet). While this bit is set,
+ * no additional packets will be received (some additional
+ * bytes can still be pending between the wire and the RX
+ * FIFO). Requires no action on the part of the host. The
+ * condition is cleared once a few bytes have been read out
+ * from the RX FIFO.
+ * 10: 1=TX overrun (RO). Generates adapter failure interrupt.
+ * Requires TX Reset or Global Reset command to recover.
+ * Disables Transmitter.
+ * 9-8: Unassigned.
+ * 7-0: Built in self test bits for the RX and TX FIFO's.
+ */
+#define FIFOS_RX_RECEIVING (unsigned short) 0x8000
+#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000
+#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000
+#define FIFOS_RX_OVERRUN (unsigned short) 0x0800
+#define FIFOS_TX_OVERRUN (unsigned short) 0x0400
+
+/*
+ * Misc defines for various things.
+ */
+#define TAG_ADAPTER 0xd0
+#define ACTIVATE_ADAPTER_TO_CONFIG 0xff
+#define ENABLE_DRQ_IRQ 0x0001
+#define MFG_ID 0x506d /* `TCM' */
+#define PROD_ID 0x5090
+#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND)
+#define JABBER_GUARD_ENABLE 0x40
+#define LINKBEAT_ENABLE 0x80
+#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE)
+#define DISABLE_UTP 0x0
+#define RX_BYTES_MASK (unsigned short) (0x07ff)
+#define RX_ERROR 0x4000
+#define RX_INCOMPLETE 0x8000
+#define TX_INDICATE 1<<15
+#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+
+#define VX_IOSIZE 0x20
+
+#define VX_CONNECTORS 8
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c5x9.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c5x9.c
new file mode 100644
index 0000000..87c9f29
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c5x9.c
@@ -0,0 +1,416 @@
+/**************************************************************************
+ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters.
+ Date: Mar 22 1995
+
+ This code is based heavily on David Greenman's if_ed.c driver and
+ Andres Vega Garcia's if_ep.c driver.
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ Copyright (C) 1993-1995, Andres Vega Garcia.
+ Copyright (C) 1995, Serge Babkin.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
+
+$Id$
+
+***************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+/* #define EDEBUG */
+
+#include <gpxe/ethernet.h>
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/isa.h>
+#include "3c509.h"
+
+static enum { none, bnc, utp } connector = none; /* for 3C509 */
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+void t5x9_disable ( struct nic *nic ) {
+ /* stop card */
+ outw(RX_DISABLE, nic->ioaddr + EP_COMMAND);
+ outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
+ while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+ ;
+ outw(TX_DISABLE, nic->ioaddr + EP_COMMAND);
+ outw(STOP_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
+ udelay(1000);
+ outw(RX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(TX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
+ outw(SET_RD_0_MASK, nic->ioaddr + EP_COMMAND);
+ outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
+ outw(SET_RX_FILTER, nic->ioaddr + EP_COMMAND);
+
+ /*
+ * wait for reset to complete
+ */
+ while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+ ;
+
+ GO_WINDOW(nic->ioaddr,0);
+
+ /* Disable the card */
+ outw(0, nic->ioaddr + EP_W0_CONFIG_CTRL);
+
+ /* Configure IRQ to none */
+ outw(SET_IRQ(0), nic->ioaddr + EP_W0_RESOURCE_CFG);
+}
+
+static void t509_enable ( struct nic *nic ) {
+ int i;
+
+ /* Enable the card */
+ GO_WINDOW(nic->ioaddr,0);
+ outw(ENABLE_DRQ_IRQ, nic->ioaddr + EP_W0_CONFIG_CTRL);
+
+ GO_WINDOW(nic->ioaddr,2);
+
+ /* Reload the ether_addr. */
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(nic->node_addr[i], nic->ioaddr + EP_W2_ADDR_0 + i);
+
+ outw(RX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(TX_RESET, nic->ioaddr + EP_COMMAND);
+
+ /* Window 1 is operating window */
+ GO_WINDOW(nic->ioaddr,1);
+ for (i = 0; i < 31; i++)
+ inb(nic->ioaddr + EP_W1_TX_STATUS);
+
+ /* get rid of stray intr's */
+ outw(ACK_INTR | 0xff, nic->ioaddr + EP_COMMAND);
+
+ outw(SET_RD_0_MASK | S_5_INTS, nic->ioaddr + EP_COMMAND);
+
+ outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND);
+
+ outw(SET_RX_FILTER | FIL_GROUP | FIL_INDIVIDUAL | FIL_BRDCST,
+ nic->ioaddr + EP_COMMAND);
+
+ /* configure BNC */
+ if (connector == bnc) {
+ outw(START_TRANSCEIVER, nic->ioaddr + EP_COMMAND);
+ udelay(1000);
+ }
+ /* configure UTP */
+ else if (connector == utp) {
+ GO_WINDOW(nic->ioaddr,4);
+ outw(ENABLE_UTP, nic->ioaddr + EP_W4_MEDIA_TYPE);
+ sleep(2); /* Give time for media to negotiate */
+ GO_WINDOW(nic->ioaddr,1);
+ }
+
+ /* start transceiver and receiver */
+ outw(RX_ENABLE, nic->ioaddr + EP_COMMAND);
+ outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
+
+ /* set early threshold for minimal packet length */
+ outw(SET_RX_EARLY_THRESH | ETH_ZLEN, nic->ioaddr + EP_COMMAND);
+ outw(SET_TX_START_THRESH | 16, nic->ioaddr + EP_COMMAND);
+}
+
+static void t509_reset ( struct nic *nic ) {
+ t5x9_disable ( nic );
+ t509_enable ( nic );
+}
+
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+static char padmap[] = {
+ 0, 3, 2, 1};
+
+static void t509_transmit(
+struct nic *nic,
+const char *d, /* Destination */
+unsigned int t, /* Type */
+unsigned int s, /* size */
+const char *p) /* Packet */
+{
+ register unsigned int len;
+ int pad;
+ int status;
+
+#ifdef EDEBUG
+ printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
+#endif
+
+ /* swap bytes of type */
+ t= htons(t);
+
+ len=s+ETH_HLEN; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c509 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ */
+ if (len + pad > ETH_FRAME_LEN) {
+ return;
+ }
+
+ /* drop acknowledgements */
+ while ((status=inb(nic->ioaddr + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
+ if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
+ outw(TX_RESET, nic->ioaddr + EP_COMMAND);
+ outw(TX_ENABLE, nic->ioaddr + EP_COMMAND);
+ }
+ outb(0x0, nic->ioaddr + EP_W1_TX_STATUS);
+ }
+
+ while (inw(nic->ioaddr + EP_W1_FREE_TX) < (unsigned short)len + pad + 4)
+ ; /* no room in FIFO */
+
+ outw(len, nic->ioaddr + EP_W1_TX_PIO_WR_1);
+ outw(0x0, nic->ioaddr + EP_W1_TX_PIO_WR_1); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
+ outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
+ outw(t, nic->ioaddr + EP_W1_TX_PIO_WR_1);
+ outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, p, s / 2);
+ if (s & 1)
+ outb(*(p+s - 1), nic->ioaddr + EP_W1_TX_PIO_WR_1);
+
+ while (pad--)
+ outb(0, nic->ioaddr + EP_W1_TX_PIO_WR_1); /* Padding */
+
+ /* wait for Tx complete */
+ while((inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
+ ;
+}
+
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+static int t509_poll(struct nic *nic, int retrieve)
+{
+ /* common variables */
+ /* variables for 3C509 */
+ short status, cst;
+ register short rx_fifo;
+
+ cst=inw(nic->ioaddr + EP_STATUS);
+
+#ifdef EDEBUG
+ if(cst & 0x1FFF)
+ printf("-%hX-",cst);
+#endif
+
+ if( (cst & S_RX_COMPLETE)==0 ) {
+ /* acknowledge everything */
+ outw(ACK_INTR| (cst & S_5_INTS), nic->ioaddr + EP_COMMAND);
+ outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND);
+
+ return 0;
+ }
+
+ status = inw(nic->ioaddr + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+
+ if (status & ERR_RX) {
+ outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo==0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ /* read packet */
+#ifdef EDEBUG
+ printf("[l=%d",rx_fifo);
+#endif
+ insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
+ nic->packetlen=rx_fifo;
+
+ while(1) {
+ status = inw(nic->ioaddr + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%hX*",status);
+#endif
+ rx_fifo = status & RX_BYTES_MASK;
+ if(rx_fifo>0) {
+ insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
+ if(rx_fifo & 1)
+ nic->packet[nic->packetlen+rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1);
+ nic->packetlen+=rx_fifo;
+#ifdef EDEBUG
+ printf("+%d",rx_fifo);
+#endif
+ }
+ if(( status & RX_INCOMPLETE )==0) {
+#ifdef EDEBUG
+ printf("=%d",nic->packetlen);
+#endif
+ break;
+ }
+ udelay(1000); /* if incomplete wait 1 ms */
+ }
+ /* acknowledge reception of packet */
+ outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND);
+ while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+ ;
+#ifdef EDEBUG
+{
+ unsigned short type = 0; /* used by EDEBUG */
+ type = (nic->packet[12]<<8) | nic->packet[13];
+ if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
+ nic->packet[5] == 0xFF*ETH_ALEN)
+ printf(",t=%hX,b]",type);
+ else
+ printf(",t=%hX]",type);
+}
+#endif
+ return (1);
+}
+
+/**************************************************************************
+ETH_IRQ - interrupt handling
+***************************************************************************/
+static void t509_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/*************************************************************************
+ 3Com 509 - specific routines
+**************************************************************************/
+
+static int eeprom_rdy ( uint16_t ioaddr ) {
+ int i;
+
+ for (i = 0; is_eeprom_busy(ioaddr) && i < MAX_EEPROMBUSY; i++);
+ if (i >= MAX_EEPROMBUSY) {
+ /* printf("3c509: eeprom failed to come ready.\n"); */
+ /* memory in EPROM is tight */
+ /* printf("3c509: eeprom busy.\n"); */
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * get_e: gets a 16 bits word from the EEPROM.
+ */
+static int get_e ( uint16_t ioaddr, int offset ) {
+ GO_WINDOW(ioaddr,0);
+ if (!eeprom_rdy(ioaddr))
+ return (0xffff);
+ outw(EEPROM_CMD_RD | offset, ioaddr + EP_W0_EEPROM_COMMAND);
+ if (!eeprom_rdy(ioaddr))
+ return (0xffff);
+ return (inw(ioaddr + EP_W0_EEPROM_DATA));
+}
+
+static struct nic_operations t509_operations = {
+ .connect = dummy_connect,
+ .poll = t509_poll,
+ .transmit = t509_transmit,
+ .irq = t509_irq,
+};
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+int t5x9_probe ( struct nic *nic,
+ uint16_t prod_id_check, uint16_t prod_id_mask ) {
+ uint16_t prod_id;
+ int i,j;
+ unsigned short *p;
+
+ /* Check product ID */
+ prod_id = get_e ( nic->ioaddr, EEPROM_PROD_ID );
+ if ( ( prod_id & prod_id_mask ) != prod_id_check ) {
+ printf ( "EEPROM Product ID is incorrect (%hx & %hx != %hx)\n",
+ prod_id, prod_id_mask, prod_id_check );
+ return 0;
+ }
+
+ /* test for presence of connectors */
+ GO_WINDOW(nic->ioaddr,0);
+ i = inw(nic->ioaddr + EP_W0_CONFIG_CTRL);
+ j = (inw(nic->ioaddr + EP_W0_ADDRESS_CFG) >> 14) & 0x3;
+
+ switch(j) {
+ case 0:
+ if (i & IS_UTP) {
+ printf("10baseT\n");
+ connector = utp;
+ } else {
+ printf("10baseT not present\n");
+ return 0;
+ }
+ break;
+ case 1:
+ if (i & IS_AUI) {
+ printf("10base5\n");
+ } else {
+ printf("10base5 not present\n");
+ return 0;
+ }
+ break;
+ case 3:
+ if (i & IS_BNC) {
+ printf("10base2\n");
+ connector = bnc;
+ } else {
+ printf("10base2 not present\n");
+ return 0;
+ }
+ break;
+ default:
+ printf("unknown connector\n");
+ return 0;
+ }
+
+ /*
+ * Read the station address from the eeprom
+ */
+ p = (unsigned short *) nic->node_addr;
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ p[i] = htons(get_e(nic->ioaddr,i));
+ GO_WINDOW(nic->ioaddr,2);
+ outw(ntohs(p[i]), nic->ioaddr + EP_W2_ADDR_0 + (i * 2));
+ }
+
+ DBG ( "Ethernet Address: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ t509_reset(nic);
+
+ nic->nic_op = &t509_operations;
+ return 1;
+
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.c
new file mode 100644
index 0000000..9c1879b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.c
@@ -0,0 +1,994 @@
+/*
+ * 3c90x.c -- This file implements a gPXE API 3c90x driver
+ *
+ * Originally written for etherboot by:
+ * Greg Beeley, Greg.Beeley@LightSys.org
+ * Modified by Steve Smith,
+ * Steve.Smith@Juno.Com. Alignment bug fix Neil Newell (nn@icenoir.net).
+ * Almost totally Rewritten to use gPXE API, implementation of tx/rx ring support
+ * by Thomas Miletich, thomas.miletich@gmail.com
+ * Thanks to Marty Connor and Stefan Hajnoczi for their help and feedback,
+ * and to Daniel Verkamp for his help with testing.
+ *
+ * Copyright (c) 2009 Thomas Miletich
+ *
+ * Copyright (c) 1999 LightSys Technology Services, Inc.
+ * Portions Copyright (c) 1999 Steve Smith
+ *
+ * This program may be re-distributed in source or binary form, modified,
+ * sold, or copied for any purpose, provided that the above copyright message
+ * and this text are included with all source copies or derivative works, and
+ * provided that the above copyright message and this text are included in the
+ * documentation of any binary-only distributions. This program is distributed
+ * WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
+ * PURPOSE or MERCHANTABILITY. Please read the associated documentation
+ * "3c90x.txt" before compiling and using this driver.
+ *
+ * [ --mdc 20090313 The 3c90x.txt file is now at:
+ * http://etherboot.org/wiki/appnotes/3c90x_issues ]
+ *
+ * This program was written with the assistance of the 3com documentation for
+ * the 3c905B-TX card, as well as with some assistance from the 3c59x
+ * driver Donald Becker wrote for the Linux kernel, and with some assistance
+ * from the remainder of the Etherboot distribution.
+ *
+ * Indented with unix 'indent' command:
+ * $ indent -kr -i8 3c90x.c
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/io.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/malloc.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/pci.h>
+#include <gpxe/timer.h>
+#include <gpxe/nvs.h>
+
+#include "3c90x.h"
+
+/**
+ * a3c90x_internal_IssueCommand: sends a command to the 3c90x card
+ * and waits for it's completion
+ *
+ * @v ioaddr IOAddress of the NIC
+ * @v cmd Command to be issued
+ * @v param Command parameter
+ */
+static void a3c90x_internal_IssueCommand(int ioaddr, int cmd, int param)
+{
+ unsigned int val = (cmd << 11) | param;
+ int cnt = 0;
+
+ DBGP("a3c90x_internal_IssueCommand\n");
+
+ /* Send the cmd to the cmd register */
+ outw(val, ioaddr + regCommandIntStatus_w);
+
+ /* Wait for the cmd to complete */
+ for (cnt = 0; cnt < 100000; cnt++) {
+ if (inw(ioaddr + regCommandIntStatus_w) & INT_CMDINPROGRESS) {
+ continue;
+ } else {
+ DBG2("Command 0x%04X finished in time. cnt = %d.\n", cmd, cnt);
+ return;
+ }
+ }
+
+ DBG("Command 0x%04X DID NOT finish in time. cnt = %d.\n", cmd, cnt);
+}
+
+/**
+ * a3c90x_internal_SetWindow: selects a register window set.
+ *
+ * @v inf_3c90x private NIC data
+ * @v window window to be selected
+ */
+static void a3c90x_internal_SetWindow(struct INF_3C90X *inf_3c90x, int window)
+{
+ DBGP("a3c90x_internal_SetWindow\n");
+ /* Window already as set? */
+ if (inf_3c90x->CurrentWindow == window)
+ return;
+
+ /* Issue the window command. */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSelectRegisterWindow, window);
+ inf_3c90x->CurrentWindow = window;
+
+ return;
+}
+
+static void a3c90x_internal_WaitForEeprom(struct INF_3C90X *inf_3c90x)
+{
+ int cnt = 0;
+
+ DBGP("a3c90x_internal_WaitForEeprom\n");
+
+ while (eepromBusy & inw(inf_3c90x->IOAddr + regEepromCommand_0_w)) {
+ if (cnt == EEPROM_TIMEOUT) {
+ DBG("Read from eeprom failed: timeout\n");
+ return;
+ }
+ udelay(1);
+ cnt++;
+ }
+}
+
+/**
+ * a3c90x_internal_ReadEeprom - nvs routine to read eeprom data
+ * We only support reading one word(2 byte). The nvs subsystem will make sure
+ * that the routine will never be called with len != 2.
+ *
+ * @v nvs nvs data.
+ * @v address eeprom address to read data from.
+ * @v data data is put here.
+ * @v len number of bytes to read.
+ */
+static int
+a3c90x_internal_ReadEeprom(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
+{
+ unsigned short *dest = (unsigned short *) data;
+ struct INF_3C90X *inf_3c90x =
+ container_of(nvs, struct INF_3C90X, nvs);
+
+ DBGP("a3c90x_internal_ReadEeprom\n");
+
+ /* we support reading 2 bytes only */
+ assert(len == 2);
+
+ /* Select correct window */
+ a3c90x_internal_SetWindow(inf_3c90x, winEepromBios0);
+
+ /* set eepromRead bits in command sent to NIC */
+ address += (inf_3c90x->is3c556 ? eepromRead_556 : eepromRead);
+
+ a3c90x_internal_WaitForEeprom(inf_3c90x);
+ /* send address to NIC */
+ outw(address, inf_3c90x->IOAddr + regEepromCommand_0_w);
+ a3c90x_internal_WaitForEeprom(inf_3c90x);
+
+ /* read value */
+ *dest = inw(inf_3c90x->IOAddr + regEepromData_0_w);
+
+ return 0;
+}
+
+/**
+ * a3c90x_internal_WriteEeprom - nvs routine to write eeprom data
+ * currently not implemented
+ *
+ * @v nvs nvs data.
+ * @v address eeprom address to read data from.
+ * @v data data is put here.
+ * @v len number of bytes to read.
+ */
+static int
+a3c90x_internal_WriteEeprom(struct nvs_device *nvs __unused,
+ unsigned int address __unused,
+ const void *data __unused, size_t len __unused)
+{
+ return -ENOTSUP;
+}
+
+static void a3c90x_internal_ReadEepromContents(struct INF_3C90X *inf_3c90x)
+{
+ int eeprom_size = (inf_3c90x->isBrev ? 0x20 : 0x17) * 2;
+
+ DBGP("a3c90x_internal_ReadEepromContents\n");
+
+ nvs_read(&inf_3c90x->nvs, 0, inf_3c90x->eeprom, eeprom_size);
+}
+
+/**
+ * a3c90x_reset: exported function that resets the card to its default
+ * state. This is so the Linux driver can re-set the card up the way
+ * it wants to. If CFG_3C90X_PRESERVE_XCVR is defined, then the reset will
+ * not alter the selected transceiver that we used to download the boot
+ * image.
+ *
+ * @v inf_3c90x Private NIC data
+ */
+static void a3c90x_reset(struct INF_3C90X *inf_3c90x)
+{
+ DBGP("a3c90x_reset\n");
+ /* Send the reset command to the card */
+ DBG("3c90x: Issuing RESET\n");
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdGlobalReset, 0);
+
+ /* global reset command resets station mask, non-B revision cards
+ * require explicit reset of values
+ */
+ a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
+ outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 0);
+ outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 2);
+ outw(0, inf_3c90x->IOAddr + regStationMask_2_3w + 4);
+
+ /* Issue transmit reset, wait for command completion */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxReset, 0);
+
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxEnable, 0);
+
+ /*
+ * reset of the receiver on B-revision cards re-negotiates the link
+ * takes several seconds (a computer eternity)
+ */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxReset,
+ inf_3c90x->isBrev ? 0x04 : 0x00);
+
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxEnable, 0);
+
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetInterruptEnable, 0);
+ /* enable rxComplete and txComplete */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetIndicationEnable,
+ INT_TXCOMPLETE | INT_UPCOMPLETE);
+ /* acknowledge any pending status flags */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdAcknowledgeInterrupt, 0x661);
+
+ return;
+}
+
+/**
+ * a3c90x_setup_tx_ring - Allocates TX ring, initialize tx_desc values
+ *
+ * @v p Private NIC data
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_setup_tx_ring(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_setup_tx_ring\n");
+ p->tx_ring =
+ malloc_dma(TX_RING_SIZE * sizeof(struct TXD), TX_RING_ALIGN);
+
+ if (!p->tx_ring) {
+ DBG("Could not allocate TX-ring\n");
+ return -ENOMEM;
+ }
+
+ memset(p->tx_ring, 0, TX_RING_SIZE * sizeof(struct TXD));
+ p->tx_cur = 0;
+ p->tx_cnt = 0;
+ p->tx_tail = 0;
+
+ return 0;
+}
+
+/**
+ * a3c90x_process_tx_packets - Checks for successfully sent packets,
+ * reports them to gPXE with netdev_tx_complete();
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_process_tx_packets(struct net_device *netdev)
+{
+ struct INF_3C90X *p = netdev_priv(netdev);
+ unsigned int downlist_ptr;
+
+ DBGP("a3c90x_process_tx_packets\n");
+
+ DBG(" tx_cnt: %d\n", p->tx_cnt);
+
+ while (p->tx_tail != p->tx_cur) {
+
+ downlist_ptr = inl(p->IOAddr + regDnListPtr_l);
+
+ DBG(" downlist_ptr: %#08x\n", downlist_ptr);
+ DBG(" tx_tail: %d tx_cur: %d\n", p->tx_tail, p->tx_cur);
+
+ /* NIC is currently working on this tx desc */
+ if(downlist_ptr == virt_to_bus(p->tx_ring + p->tx_tail))
+ return;
+
+ netdev_tx_complete(netdev, p->tx_iobuf[p->tx_tail]);
+
+ DBG("transmitted packet\n");
+ DBG(" size: %zd\n", iob_len(p->tx_iobuf[p->tx_tail]));
+
+ p->tx_tail = (p->tx_tail + 1) % TX_RING_SIZE;
+ p->tx_cnt--;
+ }
+}
+
+static void a3c90x_free_tx_ring(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_free_tx_ring\n");
+
+ free_dma(p->tx_ring, TX_RING_SIZE * sizeof(struct TXD));
+ p->tx_ring = NULL;
+ /* io_buffers are free()ed by netdev_tx_complete[,_err]() */
+}
+
+/**
+ * a3c90x_transmit - Transmits a packet.
+ *
+ * @v netdev Network device info
+ * @v iob io_buffer containing the data to be send
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_transmit(struct net_device *netdev,
+ struct io_buffer *iob)
+{
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+ struct TXD *tx_cur_desc;
+ struct TXD *tx_prev_desc;
+
+ unsigned int len;
+ unsigned int downlist_ptr;
+
+ DBGP("a3c90x_transmit\n");
+
+ if (inf_3c90x->tx_cnt == TX_RING_SIZE) {
+ DBG("TX-Ring overflow\n");
+ return -ENOBUFS;
+ }
+
+ inf_3c90x->tx_iobuf[inf_3c90x->tx_cur] = iob;
+ tx_cur_desc = inf_3c90x->tx_ring + inf_3c90x->tx_cur;
+
+ tx_prev_desc = inf_3c90x->tx_ring +
+ (((inf_3c90x->tx_cur + TX_RING_SIZE) - 1) % TX_RING_SIZE);
+
+ len = iob_len(iob);
+
+ /* Setup the DPD (download descriptor) */
+ tx_cur_desc->DnNextPtr = 0;
+
+ /* FrameStartHeader differs in 90x and >= 90xB
+ * It contains length in 90x and a round up boundary and packet ID for
+ * 90xB and 90xC. We can leave this to 0 for 90xB and 90xC.
+ */
+ tx_cur_desc->FrameStartHeader =
+ fshTxIndicate | (inf_3c90x->isBrev ? 0x00 : len);
+
+ tx_cur_desc->DataAddr = virt_to_bus(iob->data);
+ tx_cur_desc->DataLength = len | downLastFrag;
+
+ /* We have to stall the download engine, so the NIC won't access the
+ * tx descriptor while we modify it. There is a way around this
+ * from revision B and upwards. To stay compatible with older revisions
+ * we don't use it here.
+ */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdStallCtl,
+ dnStall);
+
+ tx_prev_desc->DnNextPtr = virt_to_bus(tx_cur_desc);
+
+ downlist_ptr = inl(inf_3c90x->IOAddr + regDnListPtr_l);
+ if (downlist_ptr == 0) {
+ /* currently no DownList, sending a new one */
+ outl(virt_to_bus(tx_cur_desc),
+ inf_3c90x->IOAddr + regDnListPtr_l);
+ }
+
+ /* End Stall */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdStallCtl,
+ dnUnStall);
+
+ inf_3c90x->tx_cur = (inf_3c90x->tx_cur + 1) % TX_RING_SIZE;
+ inf_3c90x->tx_cnt++;
+
+ return 0;
+}
+
+/**
+ * a3c90x_prepare_rx_desc - fills the rx desc with initial data
+ *
+ * @v p NIC private data
+ * @v index Index for rx_iobuf and rx_ring array
+ */
+
+static void a3c90x_prepare_rx_desc(struct INF_3C90X *p, unsigned int index)
+{
+ DBGP("a3c90x_prepare_rx_desc\n");
+ DBG("Populating rx_desc %d\n", index);
+
+ /* We have to stall the upload engine, so the NIC won't access the
+ * rx descriptor while we modify it. There is a way around this
+ * from revision B and upwards. To stay compatible with older revisions
+ * we don't use it here.
+ */
+ a3c90x_internal_IssueCommand(p->IOAddr, cmdStallCtl, upStall);
+
+ p->rx_ring[index].DataAddr = virt_to_bus(p->rx_iobuf[index]->data);
+ p->rx_ring[index].DataLength = RX_BUF_SIZE | upLastFrag;
+ p->rx_ring[index].UpPktStatus = 0;
+
+ /* unstall upload engine */
+ a3c90x_internal_IssueCommand(p->IOAddr, cmdStallCtl, upUnStall);
+}
+
+/**
+ * a3c90x_refill_rx_ring -checks every entry in the rx ring and reallocates
+ * them as necessary. Then it calls a3c90x_prepare_rx_desc to fill the rx desc
+ * with initial data.
+ *
+ * @v p NIC private data
+ */
+static void a3c90x_refill_rx_ring(struct INF_3C90X *p)
+{
+ int i;
+ unsigned int status;
+ struct RXD *rx_cur_desc;
+
+ DBGP("a3c90x_refill_rx_ring\n");
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_cur_desc = p->rx_ring + i;
+ status = rx_cur_desc->UpPktStatus;
+
+ /* only refill used descriptor */
+ if (!(status & upComplete))
+ continue;
+
+ /* we still need to process this descriptor */
+ if (p->rx_iobuf[i] != NULL)
+ continue;
+
+ p->rx_iobuf[i] = alloc_iob(RX_BUF_SIZE);
+ if (p->rx_iobuf[i] == NULL) {
+ DBG("alloc_iob() failed\n");
+ break;
+ }
+
+ a3c90x_prepare_rx_desc(p, i);
+ }
+}
+
+/**
+ * a3c90x_setup_rx_ring - Allocates RX ring, initialize rx_desc values
+ *
+ * @v p Private NIC data
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_setup_rx_ring(struct INF_3C90X *p)
+{
+ int i;
+
+ DBGP("a3c90x_setup_rx_ring\n");
+
+ p->rx_ring =
+ malloc_dma(RX_RING_SIZE * sizeof(struct RXD), RX_RING_ALIGN);
+
+ if (!p->rx_ring) {
+ DBG("Could not allocate RX-ring\n");
+ return -ENOMEM;
+ }
+
+ p->rx_cur = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ p->rx_ring[i].UpNextPtr =
+ virt_to_bus(p->rx_ring + (i + 1));
+
+ /* these are needed so refill_rx_ring initializes the ring */
+ p->rx_ring[i].UpPktStatus = upComplete;
+ p->rx_iobuf[i] = NULL;
+ }
+
+ /* Loop the ring */
+ p->rx_ring[i - 1].UpNextPtr = virt_to_bus(p->rx_ring);
+
+ a3c90x_refill_rx_ring(p);
+
+ return 0;
+}
+
+static void a3c90x_free_rx_ring(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_free_rx_ring\n");
+
+ free_dma(p->rx_ring, RX_RING_SIZE * sizeof(struct RXD));
+ p->rx_ring = NULL;
+}
+
+static void a3c90x_free_rx_iobuf(struct INF_3C90X *p)
+{
+ int i;
+
+ DBGP("a3c90x_free_rx_iobuf\n");
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ free_iob(p->rx_iobuf[i]);
+ p->rx_iobuf[i] = NULL;
+ }
+}
+
+/**
+ * a3c90x_process_rx_packets - Checks for received packets,
+ * reports them to gPXE with netdev_rx() or netdev_rx_err() if there was an
+ * error while receiving the packet
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_process_rx_packets(struct net_device *netdev)
+{
+ int i;
+ unsigned int rx_status;
+ struct INF_3C90X *p = netdev_priv(netdev);
+ struct RXD *rx_cur_desc;
+
+ DBGP("a3c90x_process_rx_packets\n");
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_cur_desc = p->rx_ring + p->rx_cur;
+ rx_status = rx_cur_desc->UpPktStatus;
+
+ if (!(rx_status & upComplete) && !(rx_status & upError))
+ break;
+
+ if (p->rx_iobuf[p->rx_cur] == NULL)
+ break;
+
+ if (rx_status & upError) {
+ DBG("Corrupted packet received\n");
+ netdev_rx_err(netdev, p->rx_iobuf[p->rx_cur],
+ -EINVAL);
+ } else {
+ /* if we're here, we've got good packet */
+ int packet_len;
+
+ packet_len = rx_status & 0x1FFF;
+ iob_put(p->rx_iobuf[p->rx_cur], packet_len);
+
+ DBG("received packet\n");
+ DBG(" size: %d\n", packet_len);
+
+ netdev_rx(netdev, p->rx_iobuf[p->rx_cur]);
+ }
+
+ p->rx_iobuf[p->rx_cur] = NULL; /* invalidate rx desc */
+ p->rx_cur = (p->rx_cur + 1) % RX_RING_SIZE;
+ }
+ a3c90x_refill_rx_ring(p);
+
+}
+
+/**
+ * a3c90x_poll - Routine that gets called periodically.
+ * Here we hanle transmitted and received packets.
+ * We could also check the link status from time to time, which we
+ * currently don't do.
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_poll(struct net_device *netdev)
+{
+ struct INF_3C90X *p = netdev_priv(netdev);
+ uint16_t raw_status, int_status;
+
+ DBGP("a3c90x_poll\n");
+
+ raw_status = inw(p->IOAddr + regCommandIntStatus_w);
+ int_status = (raw_status & 0x0FFF);
+
+ if ( int_status == 0 )
+ return;
+
+ a3c90x_internal_IssueCommand(p->IOAddr, cmdAcknowledgeInterrupt,
+ int_status);
+
+ if (int_status & INT_TXCOMPLETE)
+ outb(0x00, p->IOAddr + regTxStatus_b);
+
+ DBG("poll: status = %#04x\n", raw_status);
+
+ a3c90x_process_tx_packets(netdev);
+
+ a3c90x_process_rx_packets(netdev);
+}
+
+
+
+static void a3c90x_free_resources(struct INF_3C90X *p)
+{
+ DBGP("a3c90x_free_resources\n");
+
+ a3c90x_free_tx_ring(p);
+ a3c90x_free_rx_ring(p);
+ a3c90x_free_rx_iobuf(p);
+}
+
+/**
+ * a3c90x_remove - Routine to remove the card. Unregisters
+ * the NIC from gPXE, disables RX/TX and resets the card.
+ *
+ * @v pci PCI device info
+ */
+static void a3c90x_remove(struct pci_device *pci)
+{
+ struct net_device *netdev = pci_get_drvdata(pci);
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_remove\n");
+
+ a3c90x_reset(inf_3c90x);
+
+ /* Disable the receiver and transmitter. */
+ outw(cmdRxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+ outw(cmdTxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+
+ unregister_netdev(netdev);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+static void a3c90x_irq(struct net_device *netdev, int enable)
+{
+ struct INF_3C90X *p = netdev_priv(netdev);
+
+ DBGP("a3c90x_irq\n");
+
+ if (enable == 0) {
+ /* disable interrupts */
+ a3c90x_internal_IssueCommand(p->IOAddr,
+ cmdSetInterruptEnable, 0);
+ } else {
+ a3c90x_internal_IssueCommand(p->IOAddr,
+ cmdSetInterruptEnable,
+ INT_TXCOMPLETE |
+ INT_UPCOMPLETE);
+ a3c90x_internal_IssueCommand(p->IOAddr,
+ cmdAcknowledgeInterrupt,
+ 0x661);
+ }
+}
+
+/**
+ * a3c90x_hw_start - Initialize hardware, copy MAC address
+ * to NIC registers, set default receiver
+ */
+static void a3c90x_hw_start(struct net_device *netdev)
+{
+ int i, c;
+ unsigned int cfg;
+ unsigned int mopt;
+ unsigned short linktype;
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_hw_start\n");
+
+ /* 3C556: Invert MII power */
+ if (inf_3c90x->is3c556) {
+ unsigned int tmp;
+ a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
+ tmp = inw(inf_3c90x->IOAddr + regResetOptions_2_w);
+ tmp |= 0x4000;
+ outw(tmp, inf_3c90x->IOAddr + regResetOptions_2_w);
+ }
+
+ /* Copy MAC address into the NIC registers */
+ a3c90x_internal_SetWindow(inf_3c90x, winAddressing2);
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(netdev->ll_addr[i],
+ inf_3c90x->IOAddr + regStationAddress_2_3w + i);
+ for (i = 0; i < ETH_ALEN; i++)
+ outb(0, inf_3c90x->IOAddr + regStationMask_2_3w + i);
+
+ /* Read the media options register, print a message and set default
+ * xcvr.
+ *
+ * Uses Media Option command on B revision, Reset Option on non-B
+ * revision cards -- same register address
+ */
+ a3c90x_internal_SetWindow(inf_3c90x, winTxRxOptions3);
+ mopt = inw(inf_3c90x->IOAddr + regResetMediaOptions_3_w);
+
+ /* mask out VCO bit that is defined as 10baseFL bit on B-rev cards */
+ if (!inf_3c90x->isBrev) {
+ mopt &= 0x7F;
+ }
+
+ DBG("Connectors present: ");
+ c = 0;
+ linktype = 0x0008;
+ if (mopt & 0x01) {
+ DBG("%s100Base-T4", (c++) ? ", " : "");
+ linktype = linkMII;
+ }
+ if (mopt & 0x04) {
+ DBG("%s100Base-FX", (c++) ? ", " : "");
+ linktype = link100BaseFX;
+ }
+ if (mopt & 0x10) {
+ DBG("%s10Base-2", (c++) ? ", " : "");
+ linktype = link10Base2;
+ }
+ if (mopt & 0x20) {
+ DBG("%sAUI", (c++) ? ", " : "");
+ linktype = linkAUI;
+ }
+ if (mopt & 0x40) {
+ DBG("%sMII", (c++) ? ", " : "");
+ linktype = linkMII;
+ }
+ if ((mopt & 0xA) == 0xA) {
+ DBG("%s10Base-T / 100Base-TX", (c++) ? ", " : "");
+ linktype = linkAutoneg;
+ } else if ((mopt & 0xA) == 0x2) {
+ DBG("%s100Base-TX", (c++) ? ", " : "");
+ linktype = linkAutoneg;
+ } else if ((mopt & 0xA) == 0x8) {
+ DBG("%s10Base-T", (c++) ? ", " : "");
+ linktype = linkAutoneg;
+ }
+ DBG(".\n");
+
+ /* Determine transceiver type to use, depending on value stored in
+ * eeprom 0x16
+ */
+ if (inf_3c90x->isBrev) {
+ if ((inf_3c90x->eeprom[0x16] & 0xFF00) == XCVR_MAGIC) {
+ /* User-defined */
+ linktype = inf_3c90x->eeprom[0x16] & 0x000F;
+ }
+ } else {
+ /* I don't know what MII MAC only mode is!!! */
+ if (linktype == linkExternalMII) {
+ if (inf_3c90x->isBrev)
+ DBG("WARNING: MII External MAC Mode only supported on B-revision " "cards!!!!\nFalling Back to MII Mode\n");
+ linktype = linkMII;
+ }
+ }
+
+ /* enable DC converter for 10-Base-T */
+ if (linktype == link10Base2) {
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdEnableDcConverter, 0);
+ }
+
+ /* Set the link to the type we just determined. */
+ a3c90x_internal_SetWindow(inf_3c90x, winTxRxOptions3);
+ cfg = inl(inf_3c90x->IOAddr + regInternalConfig_3_l);
+ cfg &= ~(0xF << 20);
+ cfg |= (linktype << 20);
+
+ DBG("Setting internal cfg register: 0x%08X (linktype: 0x%02X)\n",
+ cfg, linktype);
+
+ outl(cfg, inf_3c90x->IOAddr + regInternalConfig_3_l);
+
+ /* Now that we set the xcvr type, reset the Tx and Rx */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxReset, 0x00);
+
+ if (!inf_3c90x->isBrev)
+ outb(0x01, inf_3c90x->IOAddr + regTxFreeThresh_b);
+
+ /* Set the RX filter = receive only individual pkts & multicast & bcast. */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdSetRxFilter,
+ 0x01 + 0x02 + 0x04);
+
+
+ /*
+ * set Indication and Interrupt flags , acknowledge any IRQ's
+ */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetInterruptEnable,
+ INT_TXCOMPLETE | INT_UPCOMPLETE);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdSetIndicationEnable,
+ INT_TXCOMPLETE | INT_UPCOMPLETE);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr,
+ cmdAcknowledgeInterrupt, 0x661);
+}
+
+/**
+ * a3c90x_open - Routine to initialize the card. Initialize hardware,
+ * allocate TX and RX ring, send RX ring address to the NIC.
+ *
+ * @v netdev Network device info
+ *
+ * @ret Returns 0 on success, negative on failure
+ */
+static int a3c90x_open(struct net_device *netdev)
+{
+ int rc;
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_open\n");
+
+ a3c90x_hw_start(netdev);
+
+ rc = a3c90x_setup_tx_ring(inf_3c90x);
+ if (rc != 0) {
+ DBG("Error setting up TX Ring\n");
+ goto error;
+ }
+
+ rc = a3c90x_setup_rx_ring(inf_3c90x);
+ if (rc != 0) {
+ DBG("Error setting up RX Ring\n");
+ goto error;
+ }
+
+ /* send rx_ring address to NIC */
+ outl(virt_to_bus(inf_3c90x->rx_ring),
+ inf_3c90x->IOAddr + regUpListPtr_l);
+
+ /* enable packet transmission and reception */
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdTxEnable, 0);
+ a3c90x_internal_IssueCommand(inf_3c90x->IOAddr, cmdRxEnable, 0);
+
+ return 0;
+
+ error:
+ a3c90x_free_resources(inf_3c90x);
+ a3c90x_reset(inf_3c90x);
+ return rc;
+}
+
+/**
+ * a3c90x_close - free()s TX and RX ring, disablex RX/TX, resets NIC
+ *
+ * @v netdev Network device info
+ */
+static void a3c90x_close(struct net_device *netdev)
+{
+ struct INF_3C90X *inf_3c90x = netdev_priv(netdev);
+
+ DBGP("a3c90x_close\n");
+
+ a3c90x_reset(inf_3c90x);
+ outw(cmdRxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+ outw(cmdTxDisable, inf_3c90x->IOAddr + regCommandIntStatus_w);
+ a3c90x_free_resources(inf_3c90x);
+}
+
+static struct net_device_operations a3c90x_operations = {
+ .open = a3c90x_open,
+ .close = a3c90x_close,
+ .poll = a3c90x_poll,
+ .transmit = a3c90x_transmit,
+ .irq = a3c90x_irq,
+};
+
+/**
+ * a3c90x_probe: exported routine to probe for the 3c905 card.
+ * If this routine is called, the pci functions did find the
+ * card. We read the eeprom here and get the MAC address.
+ * Initialization is done in a3c90x_open().
+ *
+ * @v pci PCI device info
+ * @ pci_id PCI device IDs
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int a3c90x_probe(struct pci_device *pci,
+ const struct pci_device_id *pci_id __unused)
+{
+
+ struct net_device *netdev;
+ struct INF_3C90X *inf_3c90x;
+ unsigned char *HWAddr;
+ int rc;
+
+ DBGP("a3c90x_probe\n");
+
+ if (pci->ioaddr == 0)
+ return -EINVAL;
+
+ netdev = alloc_etherdev(sizeof(*inf_3c90x));
+ if (!netdev)
+ return -ENOMEM;
+
+ netdev_init(netdev, &a3c90x_operations);
+ pci_set_drvdata(pci, netdev);
+ netdev->dev = &pci->dev;
+
+ inf_3c90x = netdev_priv(netdev);
+ memset(inf_3c90x, 0, sizeof(*inf_3c90x));
+
+ adjust_pci_device(pci);
+
+ inf_3c90x->is3c556 = (pci->device == 0x6055);
+ inf_3c90x->IOAddr = pci->ioaddr;
+ inf_3c90x->CurrentWindow = winNone;
+
+ inf_3c90x->isBrev = 1;
+ switch (pci->device) {
+ case 0x9000: /* 10 Base TPO */
+ case 0x9001: /* 10/100 T4 */
+ case 0x9050: /* 10/100 TPO */
+ case 0x9051: /* 10 Base Combo */
+ inf_3c90x->isBrev = 0;
+ break;
+ }
+
+ DBG("[3c90x]: found NIC(0x%04X, 0x%04X), isBrev=%d, is3c556=%d\n",
+ pci->vendor, pci->device, inf_3c90x->isBrev,
+ inf_3c90x->is3c556);
+
+ /* initialize nvs device */
+ inf_3c90x->nvs.word_len_log2 = 1; /* word */
+ inf_3c90x->nvs.size = (inf_3c90x->isBrev ? 0x20 : 0x17);
+ inf_3c90x->nvs.block_size = 1;
+ inf_3c90x->nvs.read = a3c90x_internal_ReadEeprom;
+ inf_3c90x->nvs.write = a3c90x_internal_WriteEeprom;
+
+ /* reset NIC before accessing any data from it */
+ a3c90x_reset(inf_3c90x);
+
+ /* load eeprom contents to inf_3c90x->eeprom */
+ a3c90x_internal_ReadEepromContents(inf_3c90x);
+
+ HWAddr = netdev->hw_addr;
+
+ /* Retrieve the Hardware address */
+ HWAddr[0] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] >> 8;
+ HWAddr[1] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] & 0xFF;
+ HWAddr[2] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] >> 8;
+ HWAddr[3] = inf_3c90x->eeprom[eepromHwAddrOffset + 1] & 0xFF;
+ HWAddr[4] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] >> 8;
+ HWAddr[5] = inf_3c90x->eeprom[eepromHwAddrOffset + 2] & 0xFF;
+
+ /* we don't handle linkstates yet, so we're always up */
+ netdev_link_up(netdev);
+
+ if ((rc = register_netdev(netdev)) != 0) {
+ DBG("3c90x: register_netdev() failed\n");
+ netdev_put(netdev);
+ return rc;
+ }
+
+ return 0;
+}
+
+static struct pci_device_id a3c90x_nics[] = {
+/* Original 90x revisions: */
+ PCI_ROM(0x10b7, 0x6055, "3c556", "3C556", 0), /* Huricane */
+ PCI_ROM(0x10b7, 0x9000, "3c905-tpo", "3Com900-TPO", 0), /* 10 Base TPO */
+ PCI_ROM(0x10b7, 0x9001, "3c905-t4", "3Com900-Combo", 0), /* 10/100 T4 */
+ PCI_ROM(0x10b7, 0x9050, "3c905-tpo100", "3Com905-TX", 0), /* 100 Base TX / 10/100 TPO */
+ PCI_ROM(0x10b7, 0x9051, "3c905-combo", "3Com905-T4", 0), /* 100 Base T4 / 10 Base Combo */
+/* Newer 90xB revisions: */
+ PCI_ROM(0x10b7, 0x9004, "3c905b-tpo", "3Com900B-TPO", 0), /* 10 Base TPO */
+ PCI_ROM(0x10b7, 0x9005, "3c905b-combo", "3Com900B-Combo", 0), /* 10 Base Combo */
+ PCI_ROM(0x10b7, 0x9006, "3c905b-tpb2", "3Com900B-2/T", 0), /* 10 Base TP and Base2 */
+ PCI_ROM(0x10b7, 0x900a, "3c905b-fl", "3Com900B-FL", 0), /* 10 Base FL */
+ PCI_ROM(0x10b7, 0x9055, "3c905b-tpo100", "3Com905B-TX", 0), /* 10/100 TPO */
+ PCI_ROM(0x10b7, 0x9056, "3c905b-t4", "3Com905B-T4", 0), /* 10/100 T4 */
+ PCI_ROM(0x10b7, 0x9058, "3c905b-9058", "3Com905B-9058", 0), /* Cyclone 10/100/BNC */
+ PCI_ROM(0x10b7, 0x905a, "3c905b-fx", "3Com905B-FL", 0), /* 100 Base FX / 10 Base FX */
+/* Newer 90xC revision: */
+ PCI_ROM(0x10b7, 0x9200, "3c905c-tpo", "3Com905C-TXM", 0), /* 10/100 TPO (3C905C-TXM) */
+ PCI_ROM(0x10b7, 0x9202, "3c920b-emb-ati", "3c920B-EMB-WNM (ATI Radeon 9100 IGP)", 0), /* 3c920B-EMB-WNM (ATI Radeon 9100 IGP) */
+ PCI_ROM(0x10b7, 0x9210, "3c920b-emb-wnm", "3Com20B-EMB WNM", 0),
+ PCI_ROM(0x10b7, 0x9800, "3c980", "3Com980-Cyclone", 0), /* Cyclone */
+ PCI_ROM(0x10b7, 0x9805, "3c9805", "3Com9805", 0), /* Dual Port Server Cyclone */
+ PCI_ROM(0x10b7, 0x7646, "3csoho100-tx", "3CSOHO100-TX", 0), /* Hurricane */
+ PCI_ROM(0x10b7, 0x4500, "3c450", "3Com450 HomePNA Tornado", 0),
+ PCI_ROM(0x10b7, 0x1201, "3c982a", "3Com982A", 0),
+ PCI_ROM(0x10b7, 0x1202, "3c982b", "3Com982B", 0),
+};
+
+struct pci_driver a3c90x_driver __pci_driver = {
+ .ids = a3c90x_nics,
+ .id_count = (sizeof(a3c90x_nics) / sizeof(a3c90x_nics[0])),
+ .probe = a3c90x_probe,
+ .remove = a3c90x_remove,
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.h
new file mode 100644
index 0000000..acbb29d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/3c90x.h
@@ -0,0 +1,302 @@
+/*
+ * 3c90x.c -- This file implements the 3c90x driver for etherboot. Written
+ * by Greg Beeley, Greg.Beeley@LightSys.org. Modified by Steve Smith,
+ * Steve.Smith@Juno.Com. Alignment bug fix Neil Newell (nn@icenoir.net).
+ *
+ * Port from etherboot to gPXE API, implementation of tx/rx ring support
+ * by Thomas Miletich, thomas.miletich@gmail.com
+ * Thanks to Marty Connor and Stefan Hajnoczi for their help and feedback.
+ *
+ * This program Copyright (C) 1999 LightSys Technology Services, Inc.
+ * Portions Copyright (C) 1999 Steve Smith
+ *
+ * This program may be re-distributed in source or binary form, modified,
+ * sold, or copied for any purpose, provided that the above copyright message
+ * and this text are included with all source copies or derivative works, and
+ * provided that the above copyright message and this text are included in the
+ * documentation of any binary-only distributions. This program is distributed
+ * WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
+ * PURPOSE or MERCHANTABILITY. Please read the associated documentation
+ * "3c90x.txt" before compiling and using this driver.
+ *
+ * --------
+ *
+ * Program written with the assistance of the 3com documentation for
+ * the 3c905B-TX card, as well as with some assistance from the 3c59x
+ * driver Donald Becker wrote for the Linux kernel, and with some assistance
+ * from the remainder of the Etherboot distribution.
+ *
+ * REVISION HISTORY:
+ *
+ * v0.10 1-26-1998 GRB Initial implementation.
+ * v0.90 1-27-1998 GRB System works.
+ * v1.00pre1 2-11-1998 GRB Got prom boot issue fixed.
+ * v2.0 9-24-1999 SCS Modified for 3c905 (from 3c905b code)
+ * Re-wrote poll and transmit for
+ * better error recovery and heavy
+ * network traffic operation
+ * v2.01 5-26-2003 NN Fixed driver alignment issue which
+ * caused system lockups if driver structures
+ * not 8-byte aligned.
+ * v2.02 11-28-2007 GSt Got polling working again by replacing
+ * "for(i=0;i<40000;i++);" with "mdelay(1);"
+ *
+ *
+ * indent options: indent -kr -i8 3c90x.c
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#ifndef __3C90X_H_
+#define __3C90X_H_
+
+static struct net_device_operations a3c90x_operations;
+
+#define XCVR_MAGIC (0x5A00)
+
+/* Register definitions for the 3c905 */
+enum Registers {
+ regPowerMgmtCtrl_w = 0x7c, /* 905B Revision Only */
+ regUpMaxBurst_w = 0x7a, /* 905B Revision Only */
+ regDnMaxBurst_w = 0x78, /* 905B Revision Only */
+ regDebugControl_w = 0x74, /* 905B Revision Only */
+ regDebugData_l = 0x70, /* 905B Revision Only */
+ regRealTimeCnt_l = 0x40, /* Universal */
+ regUpBurstThresh_b = 0x3e, /* 905B Revision Only */
+ regUpPoll_b = 0x3d, /* 905B Revision Only */
+ regUpPriorityThresh_b = 0x3c, /* 905B Revision Only */
+ regUpListPtr_l = 0x38, /* Universal */
+ regCountdown_w = 0x36, /* Universal */
+ regFreeTimer_w = 0x34, /* Universal */
+ regUpPktStatus_l = 0x30, /* Universal with Exception, pg 130 */
+ regTxFreeThresh_b = 0x2f, /* 90X Revision Only */
+ regDnPoll_b = 0x2d, /* 905B Revision Only */
+ regDnPriorityThresh_b = 0x2c, /* 905B Revision Only */
+ regDnBurstThresh_b = 0x2a, /* 905B Revision Only */
+ regDnListPtr_l = 0x24, /* Universal with Exception, pg 107 */
+ regDmaCtrl_l = 0x20, /* Universal with Exception, pg 106 */
+ /* */
+ regIntStatusAuto_w = 0x1e, /* 905B Revision Only */
+ regTxStatus_b = 0x1b, /* Universal with Exception, pg 113 */
+ regTimer_b = 0x1a, /* Universal */
+ regTxPktId_b = 0x18, /* 905B Revision Only */
+ regCommandIntStatus_w = 0x0e, /* Universal (Command Variations) */
+};
+
+/* following are windowed registers */
+enum Registers7 {
+ regPowerMgmtEvent_7_w = 0x0c, /* 905B Revision Only */
+ regVlanEtherType_7_w = 0x04, /* 905B Revision Only */
+ regVlanMask_7_w = 0x00, /* 905B Revision Only */
+};
+
+enum Registers6 {
+ regBytesXmittedOk_6_w = 0x0c, /* Universal */
+ regBytesRcvdOk_6_w = 0x0a, /* Universal */
+ regUpperFramesOk_6_b = 0x09, /* Universal */
+ regFramesDeferred_6_b = 0x08, /* Universal */
+ regFramesRecdOk_6_b = 0x07, /* Universal with Exceptions, pg 142 */
+ regFramesXmittedOk_6_b = 0x06, /* Universal */
+ regRxOverruns_6_b = 0x05, /* Universal */
+ regLateCollisions_6_b = 0x04, /* Universal */
+ regSingleCollisions_6_b = 0x03, /* Universal */
+ regMultipleCollisions_6_b = 0x02, /* Universal */
+ regSqeErrors_6_b = 0x01, /* Universal */
+ regCarrierLost_6_b = 0x00, /* Universal */
+};
+
+enum Registers5 {
+ regIndicationEnable_5_w = 0x0c, /* Universal */
+ regInterruptEnable_5_w = 0x0a, /* Universal */
+ regTxReclaimThresh_5_b = 0x09, /* 905B Revision Only */
+ regRxFilter_5_b = 0x08, /* Universal */
+ regRxEarlyThresh_5_w = 0x06, /* Universal */
+ regTxStartThresh_5_w = 0x00, /* Universal */
+};
+
+enum Registers4 {
+ regUpperBytesOk_4_b = 0x0d, /* Universal */
+ regBadSSD_4_b = 0x0c, /* Universal */
+ regMediaStatus_4_w = 0x0a, /* Universal with Exceptions, pg 201 */
+ regPhysicalMgmt_4_w = 0x08, /* Universal */
+ regNetworkDiagnostic_4_w = 0x06, /* Universal with Exceptions, pg 203 */
+ regFifoDiagnostic_4_w = 0x04, /* Universal with Exceptions, pg 196 */
+ regVcoDiagnostic_4_w = 0x02, /* Undocumented? */
+};
+
+enum Registers3 {
+ regTxFree_3_w = 0x0c, /* Universal */
+ regRxFree_3_w = 0x0a, /* Universal with Exceptions, pg 125 */
+ regResetMediaOptions_3_w = 0x08, /* Media Options on B Revision, */
+ /* Reset Options on Non-B Revision */
+ regMacControl_3_w = 0x06, /* Universal with Exceptions, pg 199 */
+ regMaxPktSize_3_w = 0x04, /* 905B Revision Only */
+ regInternalConfig_3_l = 0x00, /* Universal, different bit */
+ /* definitions, pg 59 */
+};
+
+enum Registers2 {
+ regResetOptions_2_w = 0x0c, /* 905B Revision Only */
+ regStationMask_2_3w = 0x06, /* Universal with Exceptions, pg 127 */
+ regStationAddress_2_3w = 0x00, /* Universal with Exceptions, pg 127 */
+};
+
+enum Registers1 {
+ regRxStatus_1_w = 0x0a, /* 90X Revision Only, Pg 126 */
+};
+
+enum Registers0 {
+ regEepromData_0_w = 0x0c, /* Universal */
+ regEepromCommand_0_w = 0x0a, /* Universal */
+ regBiosRomData_0_b = 0x08, /* 905B Revision Only */
+ regBiosRomAddr_0_l = 0x04, /* 905B Revision Only */
+};
+
+
+/* The names for the eight register windows */
+enum Windows {
+ winNone = 0xff,
+ winPowerVlan7 = 0x07,
+ winStatistics6 = 0x06,
+ winTxRxControl5 = 0x05,
+ winDiagnostics4 = 0x04,
+ winTxRxOptions3 = 0x03,
+ winAddressing2 = 0x02,
+ winUnused1 = 0x01,
+ winEepromBios0 = 0x00,
+};
+
+
+/* Command definitions for the 3c90X */
+enum Commands {
+ cmdGlobalReset = 0x00, /* Universal with Exceptions, pg 151 */
+ cmdSelectRegisterWindow = 0x01, /* Universal */
+ cmdEnableDcConverter = 0x02, /* */
+ cmdRxDisable = 0x03, /* */
+ cmdRxEnable = 0x04, /* Universal */
+ cmdRxReset = 0x05, /* Universal */
+ cmdStallCtl = 0x06, /* Universal */
+ cmdTxEnable = 0x09, /* Universal */
+ cmdTxDisable = 0x0A, /* */
+ cmdTxReset = 0x0B, /* Universal */
+ cmdRequestInterrupt = 0x0C, /* */
+ cmdAcknowledgeInterrupt = 0x0D, /* Universal */
+ cmdSetInterruptEnable = 0x0E, /* Universal */
+ cmdSetIndicationEnable = 0x0F, /* Universal */
+ cmdSetRxFilter = 0x10, /* Universal */
+ cmdSetRxEarlyThresh = 0x11, /* */
+ cmdSetTxStartThresh = 0x13, /* */
+ cmdStatisticsEnable = 0x15, /* */
+ cmdStatisticsDisable = 0x16, /* */
+ cmdDisableDcConverter = 0x17, /* */
+ cmdSetTxReclaimThresh = 0x18, /* */
+ cmdSetHashFilterBit = 0x19, /* */
+};
+
+enum FrameStartHeader {
+ fshTxIndicate = 0x8000,
+ fshDnComplete = 0x10000,
+};
+
+enum UpDownDesc {
+ upLastFrag = (1 << 31),
+ downLastFrag = (1 << 31),
+};
+
+enum UpPktStatus {
+ upComplete = (1 << 15),
+ upError = (1 << 14),
+};
+
+enum Stalls {
+ upStall = 0x00,
+ upUnStall = 0x01,
+
+ dnStall = 0x02,
+ dnUnStall = 0x03,
+};
+
+enum Resources {
+ resRxRing = 0x00,
+ resTxRing = 0x02,
+ resRxIOBuf = 0x04
+};
+
+enum eeprom {
+ eepromBusy = (1 << 15),
+ eepromRead = ((0x02) << 6),
+ eepromRead_556 = 0x230,
+ eepromHwAddrOffset = 0x0a,
+};
+
+/* Bit 4 is only used in revison B and upwards */
+enum linktype {
+ link10BaseT = 0x00,
+ linkAUI = 0x01,
+ link10Base2 = 0x03,
+ link100BaseFX = 0x05,
+ linkMII = 0x06,
+ linkAutoneg = 0x08,
+ linkExternalMII = 0x09,
+};
+
+/* Values for int status register bitmask */
+#define INT_INTERRUPTLATCH (1<<0)
+#define INT_HOSTERROR (1<<1)
+#define INT_TXCOMPLETE (1<<2)
+#define INT_RXCOMPLETE (1<<4)
+#define INT_RXEARLY (1<<5)
+#define INT_INTREQUESTED (1<<6)
+#define INT_UPDATESTATS (1<<7)
+#define INT_LINKEVENT (1<<8)
+#define INT_DNCOMPLETE (1<<9)
+#define INT_UPCOMPLETE (1<<10)
+#define INT_CMDINPROGRESS (1<<12)
+#define INT_WINDOWNUMBER (7<<13)
+
+/* Buffer sizes */
+#define TX_RING_SIZE 8
+#define RX_RING_SIZE 8
+#define TX_RING_ALIGN 16
+#define RX_RING_ALIGN 16
+#define RX_BUF_SIZE 1536
+
+/* Timeouts for eeprom and command completion */
+/* Timeout 1 second, to be save */
+#define EEPROM_TIMEOUT 1 * 1000 * 1000
+
+/* TX descriptor */
+struct TXD {
+ volatile unsigned int DnNextPtr;
+ volatile unsigned int FrameStartHeader;
+ volatile unsigned int DataAddr;
+ volatile unsigned int DataLength;
+} __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */
+
+/* RX descriptor */
+struct RXD {
+ volatile unsigned int UpNextPtr;
+ volatile unsigned int UpPktStatus;
+ volatile unsigned int DataAddr;
+ volatile unsigned int DataLength;
+} __attribute__ ((aligned(8))); /* 64-bit aligned for bus mastering */
+
+/* Private NIC dats */
+struct INF_3C90X {
+ unsigned int is3c556;
+ unsigned char isBrev;
+ unsigned char CurrentWindow;
+ unsigned int IOAddr;
+ unsigned short eeprom[0x21];
+ unsigned int tx_cur; /* current entry in tx_ring */
+ unsigned int tx_cnt; /* current number of used tx descriptors */
+ unsigned int tx_tail; /* entry of last finished packet */
+ unsigned int rx_cur;
+ struct TXD *tx_ring;
+ struct RXD *rx_ring;
+ struct io_buffer *tx_iobuf[TX_RING_SIZE];
+ struct io_buffer *rx_iobuf[RX_RING_SIZE];
+ struct nvs_device nvs;
+};
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.c
new file mode 100644
index 0000000..1b1fdc1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.c
@@ -0,0 +1,693 @@
+/* Advanced Micro Devices Inc. AMD8111E Linux Network Driver
+ * Copyright (C) 2004 Advanced Micro Devices
+ * Copyright (C) 2005 Liu Tao <liutao1980@gmail.com> [etherboot port]
+ *
+ * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
+ * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
+ * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
+ * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.[ pcnet32.c ]
+ * Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "nic.h"
+#include "mii.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include "string.h"
+#include "stdint.h"
+#include "amd8111e.h"
+
+
+/* driver definitions */
+#define NUM_TX_SLOTS 2
+#define NUM_RX_SLOTS 4
+#define TX_SLOTS_MASK 1
+#define RX_SLOTS_MASK 3
+
+#define TX_BUF_LEN 1536
+#define RX_BUF_LEN 1536
+
+#define TX_PKT_LEN_MAX (ETH_FRAME_LEN - ETH_HLEN)
+#define RX_PKT_LEN_MIN 60
+#define RX_PKT_LEN_MAX ETH_FRAME_LEN
+
+#define TX_TIMEOUT 3000
+#define TX_PROCESS_TIME 10
+#define TX_RETRY (TX_TIMEOUT / TX_PROCESS_TIME)
+
+#define PHY_RW_RETRY 10
+
+
+struct amd8111e_tx_desc {
+ u16 buf_len;
+ u16 tx_flags;
+ u16 tag_ctrl_info;
+ u16 tag_ctrl_cmd;
+ u32 buf_phy_addr;
+ u32 reserved;
+};
+
+struct amd8111e_rx_desc {
+ u32 reserved;
+ u16 msg_len;
+ u16 tag_ctrl_info;
+ u16 buf_len;
+ u16 rx_flags;
+ u32 buf_phy_addr;
+};
+
+struct eth_frame {
+ u8 dst_addr[ETH_ALEN];
+ u8 src_addr[ETH_ALEN];
+ u16 type;
+ u8 data[ETH_FRAME_LEN - ETH_HLEN];
+} __attribute__((packed));
+
+struct amd8111e_priv {
+ struct amd8111e_tx_desc tx_ring[NUM_TX_SLOTS];
+ struct amd8111e_rx_desc rx_ring[NUM_RX_SLOTS];
+ unsigned char tx_buf[NUM_TX_SLOTS][TX_BUF_LEN];
+ unsigned char rx_buf[NUM_RX_SLOTS][RX_BUF_LEN];
+ unsigned long tx_idx, rx_idx;
+ int tx_consistent;
+
+ char opened;
+ char link;
+ char speed;
+ char duplex;
+ int ext_phy_addr;
+ u32 ext_phy_id;
+
+ struct pci_device *pdev;
+ struct nic *nic;
+ void *mmio;
+};
+
+static struct amd8111e_priv amd8111e;
+
+
+/********************************************************
+ * locale functions *
+ ********************************************************/
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp);
+static int amd8111e_start(struct amd8111e_priv *lp);
+static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val);
+#if 0
+static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val);
+#endif
+static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp);
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp);
+static void amd8111e_enable_interrupt(struct amd8111e_priv *lp);
+static void amd8111e_force_interrupt(struct amd8111e_priv *lp);
+static int amd8111e_get_mac_address(struct amd8111e_priv *lp);
+static int amd8111e_init_rx_ring(struct amd8111e_priv *lp);
+static int amd8111e_init_tx_ring(struct amd8111e_priv *lp);
+static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index);
+static void amd8111e_wait_link(struct amd8111e_priv *lp);
+static void amd8111e_poll_link(struct amd8111e_priv *lp);
+static void amd8111e_restart(struct amd8111e_priv *lp);
+
+
+/*
+ * This function clears necessary the device registers.
+ */
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp)
+{
+ unsigned int reg_val;
+ void *mmio = lp->mmio;
+
+ /* stop the chip */
+ writel(RUN, mmio + CMD0);
+
+ /* Clear RCV_RING_BASE_ADDR */
+ writel(0, mmio + RCV_RING_BASE_ADDR0);
+
+ /* Clear XMT_RING_BASE_ADDR */
+ writel(0, mmio + XMT_RING_BASE_ADDR0);
+ writel(0, mmio + XMT_RING_BASE_ADDR1);
+ writel(0, mmio + XMT_RING_BASE_ADDR2);
+ writel(0, mmio + XMT_RING_BASE_ADDR3);
+
+ /* Clear CMD0 */
+ writel(CMD0_CLEAR, mmio + CMD0);
+
+ /* Clear CMD2 */
+ writel(CMD2_CLEAR, mmio + CMD2);
+
+ /* Clear CMD7 */
+ writel(CMD7_CLEAR, mmio + CMD7);
+
+ /* Clear DLY_INT_A and DLY_INT_B */
+ writel(0x0, mmio + DLY_INT_A);
+ writel(0x0, mmio + DLY_INT_B);
+
+ /* Clear FLOW_CONTROL */
+ writel(0x0, mmio + FLOW_CONTROL);
+
+ /* Clear INT0 write 1 to clear register */
+ reg_val = readl(mmio + INT0);
+ writel(reg_val, mmio + INT0);
+
+ /* Clear STVAL */
+ writel(0x0, mmio + STVAL);
+
+ /* Clear INTEN0 */
+ writel(INTEN0_CLEAR, mmio + INTEN0);
+
+ /* Clear LADRF */
+ writel(0x0, mmio + LADRF);
+
+ /* Set SRAM_SIZE & SRAM_BOUNDARY registers */
+ writel(0x80010, mmio + SRAM_SIZE);
+
+ /* Clear RCV_RING0_LEN */
+ writel(0x0, mmio + RCV_RING_LEN0);
+
+ /* Clear XMT_RING0/1/2/3_LEN */
+ writel(0x0, mmio + XMT_RING_LEN0);
+ writel(0x0, mmio + XMT_RING_LEN1);
+ writel(0x0, mmio + XMT_RING_LEN2);
+ writel(0x0, mmio + XMT_RING_LEN3);
+
+ /* Clear XMT_RING_LIMIT */
+ writel(0x0, mmio + XMT_RING_LIMIT);
+
+ /* Clear MIB */
+ writew(MIB_CLEAR, mmio + MIB_ADDR);
+
+ /* Clear LARF */
+ writel( 0, mmio + LADRF);
+ writel( 0, mmio + LADRF + 4);
+
+ /* SRAM_SIZE register */
+ reg_val = readl(mmio + SRAM_SIZE);
+
+ /* Set default value to CTRL1 Register */
+ writel(CTRL1_DEFAULT, mmio + CTRL1);
+
+ /* To avoid PCI posting bug */
+ readl(mmio + CMD2);
+}
+
+/*
+ * This function initializes the device registers and starts the device.
+ */
+static int amd8111e_start(struct amd8111e_priv *lp)
+{
+ struct nic *nic = lp->nic;
+ void *mmio = lp->mmio;
+ int i, reg_val;
+
+ /* stop the chip */
+ writel(RUN, mmio + CMD0);
+
+ /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
+ writew(0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
+
+ /* enable the port manager and set auto negotiation always */
+ writel(VAL1 | EN_PMGR, mmio + CMD3 );
+ writel(XPHYANE | XPHYRST, mmio + CTRL2);
+
+ /* set control registers */
+ reg_val = readl(mmio + CTRL1);
+ reg_val &= ~XMTSP_MASK;
+ writel(reg_val | XMTSP_128 | CACHE_ALIGN, mmio + CTRL1);
+
+ /* initialize tx and rx ring base addresses */
+ amd8111e_init_tx_ring(lp);
+ amd8111e_init_rx_ring(lp);
+ writel(virt_to_bus(lp->tx_ring), mmio + XMT_RING_BASE_ADDR0);
+ writel(virt_to_bus(lp->rx_ring), mmio + RCV_RING_BASE_ADDR0);
+ writew(NUM_TX_SLOTS, mmio + XMT_RING_LEN0);
+ writew(NUM_RX_SLOTS, mmio + RCV_RING_LEN0);
+
+ /* set default IPG to 96 */
+ writew(DEFAULT_IPG, mmio + IPG);
+ writew(DEFAULT_IPG - IFS1_DELTA, mmio + IFS1);
+
+ /* AutoPAD transmit, Retransmit on Underflow */
+ writel(VAL0 | APAD_XMT | REX_RTRY | REX_UFLO, mmio + CMD2);
+
+ /* JUMBO disabled */
+ writel(JUMBO, mmio + CMD3);
+
+ /* Setting the MAC address to the device */
+ for(i = 0; i < ETH_ALEN; i++)
+ writeb(nic->node_addr[i], mmio + PADR + i);
+
+ /* set RUN bit to start the chip, interrupt not enabled */
+ writel(VAL2 | RDMD0 | VAL0 | RUN, mmio + CMD0);
+
+ /* To avoid PCI posting bug */
+ readl(mmio + CMD0);
+ return 0;
+}
+
+/*
+This function will read the PHY registers.
+*/
+static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val)
+{
+ void *mmio = lp->mmio;
+ unsigned int reg_val;
+ unsigned int retry = PHY_RW_RETRY;
+
+ reg_val = readl(mmio + PHY_ACCESS);
+ while (reg_val & PHY_CMD_ACTIVE)
+ reg_val = readl(mmio + PHY_ACCESS);
+
+ writel(PHY_RD_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16),
+ mmio + PHY_ACCESS);
+ do {
+ reg_val = readl(mmio + PHY_ACCESS);
+ udelay(30); /* It takes 30 us to read/write data */
+ } while (--retry && (reg_val & PHY_CMD_ACTIVE));
+
+ if (reg_val & PHY_RD_ERR) {
+ *val = 0;
+ return -1;
+ }
+
+ *val = reg_val & 0xffff;
+ return 0;
+}
+
+/*
+This function will write into PHY registers.
+*/
+#if 0
+static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val)
+{
+ void *mmio = lp->mmio;
+ unsigned int reg_val;
+ unsigned int retry = PHY_RW_RETRY;
+
+ reg_val = readl(mmio + PHY_ACCESS);
+ while (reg_val & PHY_CMD_ACTIVE)
+ reg_val = readl(mmio + PHY_ACCESS);
+
+ writel(PHY_WR_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16) | val,
+ mmio + PHY_ACCESS);
+ do {
+ reg_val = readl(mmio + PHY_ACCESS);
+ udelay(30); /* It takes 30 us to read/write the data */
+ } while (--retry && (reg_val & PHY_CMD_ACTIVE));
+
+ if(reg_val & PHY_RD_ERR)
+ return -1;
+
+ return 0;
+}
+#endif
+
+static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp)
+{
+ int i;
+
+ lp->ext_phy_id = 0;
+ lp->ext_phy_addr = 1;
+
+ for (i = 0x1e; i >= 0; i--) {
+ u32 id1, id2;
+
+ if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
+ continue;
+ if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
+ continue;
+ lp->ext_phy_id = (id1 << 16) | id2;
+ lp->ext_phy_addr = i;
+ break;
+ }
+
+ if (lp->ext_phy_id)
+ printf("Found MII PHY ID 0x%08x at address 0x%02x\n",
+ (unsigned int) lp->ext_phy_id, lp->ext_phy_addr);
+ else
+ printf("Couldn't detect MII PHY, assuming address 0x01\n");
+}
+
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp)
+{
+ void *mmio = lp->mmio;
+ unsigned int int0;
+
+ writel(INTREN, mmio + CMD0);
+ writel(INTEN0_CLEAR, mmio + INTEN0);
+ int0 = readl(mmio + INT0);
+ writel(int0, mmio + INT0);
+ readl(mmio + INT0);
+}
+
+static void amd8111e_enable_interrupt(struct amd8111e_priv *lp)
+{
+ void *mmio = lp->mmio;
+
+ writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
+ writel(VAL0 | INTREN, mmio + CMD0);
+ readl(mmio + CMD0);
+}
+
+static void amd8111e_force_interrupt(struct amd8111e_priv *lp)
+{
+ void *mmio = lp->mmio;
+
+ writel(VAL0 | UINTCMD, mmio + CMD0);
+ readl(mmio + CMD0);
+}
+
+static int amd8111e_get_mac_address(struct amd8111e_priv *lp)
+{
+ struct nic *nic = lp->nic;
+ void *mmio = lp->mmio;
+ int i;
+
+ /* BIOS should have set mac address to PADR register,
+ * so we read PADR to get it.
+ */
+ for (i = 0; i < ETH_ALEN; i++)
+ nic->node_addr[i] = readb(mmio + PADR + i);
+
+ DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ return 0;
+}
+
+static int amd8111e_init_rx_ring(struct amd8111e_priv *lp)
+{
+ int i;
+
+ lp->rx_idx = 0;
+
+ /* Initilaizing receive descriptors */
+ for (i = 0; i < NUM_RX_SLOTS; i++) {
+ lp->rx_ring[i].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[i]));
+ lp->rx_ring[i].buf_len = cpu_to_le16(RX_BUF_LEN);
+ wmb();
+ lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
+ }
+
+ return 0;
+}
+
+static int amd8111e_init_tx_ring(struct amd8111e_priv *lp)
+{
+ int i;
+
+ lp->tx_idx = 0;
+ lp->tx_consistent = 1;
+
+ /* Initializing transmit descriptors */
+ for (i = 0; i < NUM_TX_SLOTS; i++) {
+ lp->tx_ring[i].tx_flags = 0;
+ lp->tx_ring[i].buf_phy_addr = 0;
+ lp->tx_ring[i].buf_len = 0;
+ }
+
+ return 0;
+}
+
+static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index)
+{
+ volatile u16 status;
+ int retry = TX_RETRY;
+
+ status = le16_to_cpu(lp->tx_ring[index].tx_flags);
+ while (--retry && (status & OWN_BIT)) {
+ mdelay(TX_PROCESS_TIME);
+ status = le16_to_cpu(lp->tx_ring[index].tx_flags);
+ }
+ if (status & OWN_BIT) {
+ printf("Error: tx slot %d timeout, stat = 0x%x\n", index, status);
+ amd8111e_restart(lp);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void amd8111e_wait_link(struct amd8111e_priv *lp)
+{
+ unsigned int status;
+ u32 reg_val;
+
+ do {
+ /* read phy to update STAT0 register */
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
+ status = readl(lp->mmio + STAT0);
+ } while (!(status & AUTONEG_COMPLETE) || !(status & LINK_STATS));
+}
+
+static void amd8111e_poll_link(struct amd8111e_priv *lp)
+{
+ unsigned int status, speed;
+ u32 reg_val;
+
+ if (!lp->link) {
+ /* read phy to update STAT0 register */
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
+ amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
+ status = readl(lp->mmio + STAT0);
+
+ if (status & LINK_STATS) {
+ lp->link = 1;
+ speed = (status & SPEED_MASK) >> 7;
+ if (speed == PHY_SPEED_100)
+ lp->speed = 1;
+ else
+ lp->speed = 0;
+ if (status & FULL_DPLX)
+ lp->duplex = 1;
+ else
+ lp->duplex = 0;
+
+ printf("Link is up: %s Mbps %s duplex\n",
+ lp->speed ? "100" : "10", lp->duplex ? "full" : "half");
+ }
+ } else {
+ status = readl(lp->mmio + STAT0);
+ if (!(status & LINK_STATS)) {
+ lp->link = 0;
+ printf("Link is down\n");
+ }
+ }
+}
+
+static void amd8111e_restart(struct amd8111e_priv *lp)
+{
+ printf("\nStarting nic...\n");
+ amd8111e_disable_interrupt(lp);
+ amd8111e_init_hw_default(lp);
+ amd8111e_probe_ext_phy(lp);
+ amd8111e_get_mac_address(lp);
+ amd8111e_start(lp);
+
+ printf("Waiting link up...\n");
+ lp->link = 0;
+ amd8111e_wait_link(lp);
+ amd8111e_poll_link(lp);
+}
+
+
+/********************************************************
+ * Interface Functions *
+ ********************************************************/
+
+static void amd8111e_transmit(struct nic *nic, const char *dst_addr,
+ unsigned int type, unsigned int size, const char *packet)
+{
+ struct amd8111e_priv *lp = nic->priv_data;
+ struct eth_frame *frame;
+ unsigned int index;
+
+ /* check packet size */
+ if (size > TX_PKT_LEN_MAX) {
+ printf("amd8111e_transmit(): too large packet, drop\n");
+ return;
+ }
+
+ /* get tx slot */
+ index = lp->tx_idx;
+ if (amd8111e_wait_tx_ring(lp, index))
+ return;
+
+ /* fill frame */
+ frame = (struct eth_frame *)lp->tx_buf[index];
+ memset(frame->data, 0, TX_PKT_LEN_MAX);
+ memcpy(frame->dst_addr, dst_addr, ETH_ALEN);
+ memcpy(frame->src_addr, nic->node_addr, ETH_ALEN);
+ frame->type = htons(type);
+ memcpy(frame->data, packet, size);
+
+ /* start xmit */
+ lp->tx_ring[index].buf_len = cpu_to_le16(ETH_HLEN + size);
+ lp->tx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(frame));
+ wmb();
+ lp->tx_ring[index].tx_flags =
+ cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT | ADD_FCS_BIT | LTINT_BIT);
+ writel(VAL1 | TDMD0, lp->mmio + CMD0);
+ readl(lp->mmio + CMD0);
+
+ /* update slot pointer */
+ lp->tx_idx = (lp->tx_idx + 1) & TX_SLOTS_MASK;
+}
+
+static int amd8111e_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+
+ struct amd8111e_priv *lp = nic->priv_data;
+ u16 status, pkt_len;
+ unsigned int index, pkt_ok;
+
+ amd8111e_poll_link(lp);
+
+ index = lp->rx_idx;
+ status = le16_to_cpu(lp->rx_ring[index].rx_flags);
+ pkt_len = le16_to_cpu(lp->rx_ring[index].msg_len) - 4; /* remove 4bytes FCS */
+
+ if (status & OWN_BIT)
+ return 0;
+
+ if (status & ERR_BIT)
+ pkt_ok = 0;
+ else if (!(status & STP_BIT))
+ pkt_ok = 0;
+ else if (!(status & ENP_BIT))
+ pkt_ok = 0;
+ else if (pkt_len < RX_PKT_LEN_MIN)
+ pkt_ok = 0;
+ else if (pkt_len > RX_PKT_LEN_MAX)
+ pkt_ok = 0;
+ else
+ pkt_ok = 1;
+
+ if (pkt_ok) {
+ if (!retrieve)
+ return 1;
+ nic->packetlen = pkt_len;
+ memcpy(nic->packet, lp->rx_buf[index], nic->packetlen);
+ }
+
+ lp->rx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[index]));
+ lp->rx_ring[index].buf_len = cpu_to_le16(RX_BUF_LEN);
+ wmb();
+ lp->rx_ring[index].rx_flags = cpu_to_le16(OWN_BIT);
+ writel(VAL2 | RDMD0, lp->mmio + CMD0);
+ readl(lp->mmio + CMD0);
+
+ lp->rx_idx = (lp->rx_idx + 1) & RX_SLOTS_MASK;
+ return pkt_ok;
+}
+
+static void amd8111e_disable(struct nic *nic)
+{
+ struct amd8111e_priv *lp = nic->priv_data;
+
+ /* disable interrupt */
+ amd8111e_disable_interrupt(lp);
+
+ /* stop chip */
+ amd8111e_init_hw_default(lp);
+
+ /* unmap mmio */
+ iounmap(lp->mmio);
+
+ /* update status */
+ lp->opened = 0;
+}
+
+static void amd8111e_irq(struct nic *nic, irq_action_t action)
+{
+ struct amd8111e_priv *lp = nic->priv_data;
+
+ switch (action) {
+ case DISABLE:
+ amd8111e_disable_interrupt(lp);
+ break;
+ case ENABLE:
+ amd8111e_enable_interrupt(lp);
+ break;
+ case FORCE:
+ amd8111e_force_interrupt(lp);
+ break;
+ }
+}
+
+static struct nic_operations amd8111e_operations = {
+ .connect = dummy_connect,
+ .poll = amd8111e_poll,
+ .transmit = amd8111e_transmit,
+ .irq = amd8111e_irq,
+};
+
+static int amd8111e_probe(struct nic *nic, struct pci_device *pdev)
+{
+ struct amd8111e_priv *lp = &amd8111e;
+ unsigned long mmio_start, mmio_len;
+
+ nic->ioaddr = pdev->ioaddr;
+ nic->irqno = pdev->irq;
+
+ mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+
+ memset(lp, 0, sizeof(*lp));
+ lp->pdev = pdev;
+ lp->nic = nic;
+ lp->mmio = ioremap(mmio_start, mmio_len);
+ lp->opened = 1;
+ adjust_pci_device(pdev);
+
+ nic->priv_data = lp;
+
+ amd8111e_restart(lp);
+
+ nic->nic_op = &amd8111e_operations;
+ return 1;
+}
+
+static struct pci_device_id amd8111e_nics[] = {
+ PCI_ROM(0x1022, 0x7462, "amd8111e", "AMD8111E", 0),
+};
+
+PCI_DRIVER ( amd8111e_driver, amd8111e_nics, PCI_NO_CLASS );
+
+DRIVER ( "AMD8111E", nic_driver, pci_driver, amd8111e_driver,
+ amd8111e_probe, amd8111e_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.h
new file mode 100644
index 0000000..a402a63
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/amd8111e.h
@@ -0,0 +1,631 @@
+/*
+ * Advanced Micro Devices Inc. AMD8111E Linux Network Driver
+ * Copyright (C) 2003 Advanced Micro Devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+
+Module Name:
+
+ amd8111e.h
+
+Abstract:
+
+ AMD8111 based 10/100 Ethernet Controller driver definitions.
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+ 3.0.0
+ Initial Revision.
+ 3.0.1
+*/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _AMD811E_H
+#define _AMD811E_H
+
+/* Command style register access
+
+Registers CMD0, CMD2, CMD3,CMD7 and INTEN0 uses a write access technique called command style access. It allows the write to selected bits of this register without altering the bits that are not selected. Command style registers are divided into 4 bytes that can be written independently. Higher order bit of each byte is the value bit that specifies the value that will be written into the selected bits of register.
+
+eg., if the value 10011010b is written into the least significant byte of a command style register, bits 1,3 and 4 of the register will be set to 1, and the other bits will not be altered. If the value 00011010b is written into the same byte, bits 1,3 and 4 will be cleared to 0 and the other bits will not be altered.
+
+*/
+
+/* Offset for Memory Mapped Registers. */
+/* 32 bit registers */
+
+#define ASF_STAT 0x00 /* ASF status register */
+#define CHIPID 0x04 /* Chip ID regsiter */
+#define MIB_DATA 0x10 /* MIB data register */
+#define MIB_ADDR 0x14 /* MIB address register */
+#define STAT0 0x30 /* Status0 register */
+#define INT0 0x38 /* Interrupt0 register */
+#define INTEN0 0x40 /* Interrupt0 enable register*/
+#define CMD0 0x48 /* Command0 register */
+#define CMD2 0x50 /* Command2 register */
+#define CMD3 0x54 /* Command3 resiter */
+#define CMD7 0x64 /* Command7 register */
+
+#define CTRL1 0x6C /* Control1 register */
+#define CTRL2 0x70 /* Control2 register */
+
+#define XMT_RING_LIMIT 0x7C /* Transmit ring limit register */
+
+#define AUTOPOLL0 0x88 /* Auto-poll0 register */
+#define AUTOPOLL1 0x8A /* Auto-poll1 register */
+#define AUTOPOLL2 0x8C /* Auto-poll2 register */
+#define AUTOPOLL3 0x8E /* Auto-poll3 register */
+#define AUTOPOLL4 0x90 /* Auto-poll4 register */
+#define AUTOPOLL5 0x92 /* Auto-poll5 register */
+
+#define AP_VALUE 0x98 /* Auto-poll value register */
+#define DLY_INT_A 0xA8 /* Group A delayed interrupt register */
+#define DLY_INT_B 0xAC /* Group B delayed interrupt register */
+
+#define FLOW_CONTROL 0xC8 /* Flow control register */
+#define PHY_ACCESS 0xD0 /* PHY access register */
+
+#define STVAL 0xD8 /* Software timer value register */
+
+#define XMT_RING_BASE_ADDR0 0x100 /* Transmit ring0 base addr register */
+#define XMT_RING_BASE_ADDR1 0x108 /* Transmit ring1 base addr register */
+#define XMT_RING_BASE_ADDR2 0x110 /* Transmit ring2 base addr register */
+#define XMT_RING_BASE_ADDR3 0x118 /* Transmit ring2 base addr register */
+
+#define RCV_RING_BASE_ADDR0 0x120 /* Transmit ring0 base addr register */
+
+#define PMAT0 0x190 /* OnNow pattern register0 */
+#define PMAT1 0x194 /* OnNow pattern register1 */
+
+/* 16bit registers */
+
+#define XMT_RING_LEN0 0x140 /* Transmit Ring0 length register */
+#define XMT_RING_LEN1 0x144 /* Transmit Ring1 length register */
+#define XMT_RING_LEN2 0x148 /* Transmit Ring2 length register */
+#define XMT_RING_LEN3 0x14C /* Transmit Ring3 length register */
+
+#define RCV_RING_LEN0 0x150 /* Receive Ring0 length register */
+
+#define SRAM_SIZE 0x178 /* SRAM size register */
+#define SRAM_BOUNDARY 0x17A /* SRAM boundary register */
+
+/* 48bit register */
+
+#define PADR 0x160 /* Physical address register */
+
+#define IFS1 0x18C /* Inter-frame spacing Part1 register */
+#define IFS 0x18D /* Inter-frame spacing register */
+#define IPG 0x18E /* Inter-frame gap register */
+/* 64bit register */
+
+#define LADRF 0x168 /* Logical address filter register */
+
+
+/* Register Bit Definitions */
+typedef enum {
+
+ ASF_INIT_DONE = (1 << 1),
+ ASF_INIT_PRESENT = (1 << 0),
+
+}STAT_ASF_BITS;
+
+typedef enum {
+
+ MIB_CMD_ACTIVE = (1 << 15 ),
+ MIB_RD_CMD = (1 << 13 ),
+ MIB_CLEAR = (1 << 12 ),
+ MIB_ADDRESS = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)|
+ (1 << 4) | (1 << 5),
+}MIB_ADDR_BITS;
+
+
+typedef enum {
+
+ PMAT_DET = (1 << 12),
+ MP_DET = (1 << 11),
+ LC_DET = (1 << 10),
+ SPEED_MASK = (1 << 9)|(1 << 8)|(1 << 7),
+ FULL_DPLX = (1 << 6),
+ LINK_STATS = (1 << 5),
+ AUTONEG_COMPLETE = (1 << 4),
+ MIIPD = (1 << 3),
+ RX_SUSPENDED = (1 << 2),
+ TX_SUSPENDED = (1 << 1),
+ RUNNING = (1 << 0),
+
+}STAT0_BITS;
+
+#define PHY_SPEED_10 0x2
+#define PHY_SPEED_100 0x3
+
+/* INT0 0x38, 32bit register */
+typedef enum {
+
+ INTR = (1 << 31),
+ PCSINT = (1 << 28),
+ LCINT = (1 << 27),
+ APINT5 = (1 << 26),
+ APINT4 = (1 << 25),
+ APINT3 = (1 << 24),
+ TINT_SUM = (1 << 23),
+ APINT2 = (1 << 22),
+ APINT1 = (1 << 21),
+ APINT0 = (1 << 20),
+ MIIPDTINT = (1 << 19),
+ MCCINT = (1 << 17),
+ MREINT = (1 << 16),
+ RINT_SUM = (1 << 15),
+ SPNDINT = (1 << 14),
+ MPINT = (1 << 13),
+ SINT = (1 << 12),
+ TINT3 = (1 << 11),
+ TINT2 = (1 << 10),
+ TINT1 = (1 << 9),
+ TINT0 = (1 << 8),
+ UINT = (1 << 7),
+ STINT = (1 << 4),
+ RINT0 = (1 << 0),
+
+}INT0_BITS;
+
+typedef enum {
+
+ VAL3 = (1 << 31), /* VAL bit for byte 3 */
+ VAL2 = (1 << 23), /* VAL bit for byte 2 */
+ VAL1 = (1 << 15), /* VAL bit for byte 1 */
+ VAL0 = (1 << 7), /* VAL bit for byte 0 */
+
+}VAL_BITS;
+
+typedef enum {
+
+ /* VAL3 */
+ LCINTEN = (1 << 27),
+ APINT5EN = (1 << 26),
+ APINT4EN = (1 << 25),
+ APINT3EN = (1 << 24),
+ /* VAL2 */
+ APINT2EN = (1 << 22),
+ APINT1EN = (1 << 21),
+ APINT0EN = (1 << 20),
+ MIIPDTINTEN = (1 << 19),
+ MCCIINTEN = (1 << 18),
+ MCCINTEN = (1 << 17),
+ MREINTEN = (1 << 16),
+ /* VAL1 */
+ SPNDINTEN = (1 << 14),
+ MPINTEN = (1 << 13),
+ TINTEN3 = (1 << 11),
+ SINTEN = (1 << 12),
+ TINTEN2 = (1 << 10),
+ TINTEN1 = (1 << 9),
+ TINTEN0 = (1 << 8),
+ /* VAL0 */
+ STINTEN = (1 << 4),
+ RINTEN0 = (1 << 0),
+
+ INTEN0_CLEAR = 0x1F7F7F1F, /* Command style register */
+
+}INTEN0_BITS;
+
+typedef enum {
+ /* VAL2 */
+ RDMD0 = (1 << 16),
+ /* VAL1 */
+ TDMD3 = (1 << 11),
+ TDMD2 = (1 << 10),
+ TDMD1 = (1 << 9),
+ TDMD0 = (1 << 8),
+ /* VAL0 */
+ UINTCMD = (1 << 6),
+ RX_FAST_SPND = (1 << 5),
+ TX_FAST_SPND = (1 << 4),
+ RX_SPND = (1 << 3),
+ TX_SPND = (1 << 2),
+ INTREN = (1 << 1),
+ RUN = (1 << 0),
+
+ CMD0_CLEAR = 0x000F0F7F, /* Command style register */
+
+}CMD0_BITS;
+
+typedef enum {
+
+ /* VAL3 */
+ CONDUIT_MODE = (1 << 29),
+ /* VAL2 */
+ RPA = (1 << 19),
+ DRCVPA = (1 << 18),
+ DRCVBC = (1 << 17),
+ PROM = (1 << 16),
+ /* VAL1 */
+ ASTRP_RCV = (1 << 13),
+ RCV_DROP0 = (1 << 12),
+ EMBA = (1 << 11),
+ DXMT2PD = (1 << 10),
+ LTINTEN = (1 << 9),
+ DXMTFCS = (1 << 8),
+ /* VAL0 */
+ APAD_XMT = (1 << 6),
+ DRTY = (1 << 5),
+ INLOOP = (1 << 4),
+ EXLOOP = (1 << 3),
+ REX_RTRY = (1 << 2),
+ REX_UFLO = (1 << 1),
+ REX_LCOL = (1 << 0),
+
+ CMD2_CLEAR = 0x3F7F3F7F, /* Command style register */
+
+}CMD2_BITS;
+
+typedef enum {
+
+ /* VAL3 */
+ ASF_INIT_DONE_ALIAS = (1 << 29),
+ /* VAL2 */
+ JUMBO = (1 << 21),
+ VSIZE = (1 << 20),
+ VLONLY = (1 << 19),
+ VL_TAG_DEL = (1 << 18),
+ /* VAL1 */
+ EN_PMGR = (1 << 14),
+ INTLEVEL = (1 << 13),
+ FORCE_FULL_DUPLEX = (1 << 12),
+ FORCE_LINK_STATUS = (1 << 11),
+ APEP = (1 << 10),
+ MPPLBA = (1 << 9),
+ /* VAL0 */
+ RESET_PHY_PULSE = (1 << 2),
+ RESET_PHY = (1 << 1),
+ PHY_RST_POL = (1 << 0),
+
+}CMD3_BITS;
+
+
+typedef enum {
+
+ /* VAL0 */
+ PMAT_SAVE_MATCH = (1 << 4),
+ PMAT_MODE = (1 << 3),
+ MPEN_SW = (1 << 1),
+ LCMODE_SW = (1 << 0),
+
+ CMD7_CLEAR = 0x0000001B /* Command style register */
+
+}CMD7_BITS;
+
+
+typedef enum {
+
+ RESET_PHY_WIDTH = (0xF << 16) | (0xF<< 20), /* 0x00FF0000 */
+ XMTSP_MASK = (1 << 9) | (1 << 8), /* 9:8 */
+ XMTSP_128 = (1 << 9), /* 9 */
+ XMTSP_64 = (1 << 8),
+ CACHE_ALIGN = (1 << 4),
+ BURST_LIMIT_MASK = (0xF << 0 ),
+ CTRL1_DEFAULT = 0x00010111,
+
+}CTRL1_BITS;
+
+typedef enum {
+
+ FMDC_MASK = (1 << 9)|(1 << 8), /* 9:8 */
+ XPHYRST = (1 << 7),
+ XPHYANE = (1 << 6),
+ XPHYFD = (1 << 5),
+ XPHYSP = (1 << 4) | (1 << 3), /* 4:3 */
+ APDW_MASK = (1 << 2) | (1 << 1) | (1 << 0), /* 2:0 */
+
+}CTRL2_BITS;
+
+/* XMT_RING_LIMIT 0x7C, 32bit register */
+typedef enum {
+
+ XMT_RING2_LIMIT = (0xFF << 16), /* 23:16 */
+ XMT_RING1_LIMIT = (0xFF << 8), /* 15:8 */
+ XMT_RING0_LIMIT = (0xFF << 0), /* 7:0 */
+
+}XMT_RING_LIMIT_BITS;
+
+typedef enum {
+
+ AP_REG0_EN = (1 << 15),
+ AP_REG0_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PHY0_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL0_BITS;
+
+/* AUTOPOLL1 0x8A, 16bit register */
+typedef enum {
+
+ AP_REG1_EN = (1 << 15),
+ AP_REG1_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP1 = (1 << 6),
+ AP_PHY1_DFLT = (1 << 5),
+ AP_PHY1_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL1_BITS;
+
+
+typedef enum {
+
+ AP_REG2_EN = (1 << 15),
+ AP_REG2_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP2 = (1 << 6),
+ AP_PHY2_DFLT = (1 << 5),
+ AP_PHY2_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL2_BITS;
+
+typedef enum {
+
+ AP_REG3_EN = (1 << 15),
+ AP_REG3_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP3 = (1 << 6),
+ AP_PHY3_DFLT = (1 << 5),
+ AP_PHY3_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL3_BITS;
+
+
+typedef enum {
+
+ AP_REG4_EN = (1 << 15),
+ AP_REG4_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP4 = (1 << 6),
+ AP_PHY4_DFLT = (1 << 5),
+ AP_PHY4_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL4_BITS;
+
+
+typedef enum {
+
+ AP_REG5_EN = (1 << 15),
+ AP_REG5_ADDR_MASK = (0xF << 8) |(1 << 12),/* 12:8 */
+ AP_PRE_SUP5 = (1 << 6),
+ AP_PHY5_DFLT = (1 << 5),
+ AP_PHY5_ADDR_MASK = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL5_BITS;
+
+
+
+
+/* AP_VALUE 0x98, 32bit ragister */
+typedef enum {
+
+ AP_VAL_ACTIVE = (1 << 31),
+ AP_VAL_RD_CMD = ( 1 << 29),
+ AP_ADDR = (1 << 18)|(1 << 17)|(1 << 16), /* 18:16 */
+ AP_VAL = (0xF << 0) | (0xF << 4) |( 0xF << 8) |
+ (0xF << 12), /* 15:0 */
+
+}AP_VALUE_BITS;
+
+typedef enum {
+
+ DLY_INT_A_R3 = (1 << 31),
+ DLY_INT_A_R2 = (1 << 30),
+ DLY_INT_A_R1 = (1 << 29),
+ DLY_INT_A_R0 = (1 << 28),
+ DLY_INT_A_T3 = (1 << 27),
+ DLY_INT_A_T2 = (1 << 26),
+ DLY_INT_A_T1 = (1 << 25),
+ DLY_INT_A_T0 = ( 1 << 24),
+ EVENT_COUNT_A = (0xF << 16) | (0x1 << 20),/* 20:16 */
+ MAX_DELAY_TIME_A = (0xF << 0) | (0xF << 4) | (1 << 8)|
+ (1 << 9) | (1 << 10), /* 10:0 */
+
+}DLY_INT_A_BITS;
+
+typedef enum {
+
+ DLY_INT_B_R3 = (1 << 31),
+ DLY_INT_B_R2 = (1 << 30),
+ DLY_INT_B_R1 = (1 << 29),
+ DLY_INT_B_R0 = (1 << 28),
+ DLY_INT_B_T3 = (1 << 27),
+ DLY_INT_B_T2 = (1 << 26),
+ DLY_INT_B_T1 = (1 << 25),
+ DLY_INT_B_T0 = ( 1 << 24),
+ EVENT_COUNT_B = (0xF << 16) | (0x1 << 20),/* 20:16 */
+ MAX_DELAY_TIME_B = (0xF << 0) | (0xF << 4) | (1 << 8)|
+ (1 << 9) | (1 << 10), /* 10:0 */
+}DLY_INT_B_BITS;
+
+
+/* FLOW_CONTROL 0xC8, 32bit register */
+typedef enum {
+
+ PAUSE_LEN_CHG = (1 << 30),
+ FTPE = (1 << 22),
+ FRPE = (1 << 21),
+ NAPA = (1 << 20),
+ NPA = (1 << 19),
+ FIXP = ( 1 << 18),
+ FCCMD = ( 1 << 16),
+ PAUSE_LEN = (0xF << 0) | (0xF << 4) |( 0xF << 8) | (0xF << 12), /* 15:0 */
+
+}FLOW_CONTROL_BITS;
+
+/* PHY_ ACCESS 0xD0, 32bit register */
+typedef enum {
+
+ PHY_CMD_ACTIVE = (1 << 31),
+ PHY_WR_CMD = (1 << 30),
+ PHY_RD_CMD = (1 << 29),
+ PHY_RD_ERR = (1 << 28),
+ PHY_PRE_SUP = (1 << 27),
+ PHY_ADDR = (1 << 21) | (1 << 22) | (1 << 23)|
+ (1 << 24) |(1 << 25),/* 25:21 */
+ PHY_REG_ADDR = (1 << 16) | (1 << 17) | (1 << 18)| (1 << 19) | (1 << 20),/* 20:16 */
+ PHY_DATA = (0xF << 0)|(0xF << 4) |(0xF << 8)|
+ (0xF << 12),/* 15:0 */
+
+}PHY_ACCESS_BITS;
+
+
+/* PMAT0 0x190, 32bit register */
+typedef enum {
+ PMR_ACTIVE = (1 << 31),
+ PMR_WR_CMD = (1 << 30),
+ PMR_RD_CMD = (1 << 29),
+ PMR_BANK = (1 <<28),
+ PMR_ADDR = (0xF << 16)|(1 << 20)|(1 << 21)|
+ (1 << 22),/* 22:16 */
+ PMR_B4 = (0xF << 0) | (0xF << 4),/* 15:0 */
+}PMAT0_BITS;
+
+
+/* PMAT1 0x194, 32bit register */
+typedef enum {
+ PMR_B3 = (0xF << 24) | (0xF <<28),/* 31:24 */
+ PMR_B2 = (0xF << 16) |(0xF << 20),/* 23:16 */
+ PMR_B1 = (0xF << 8) | (0xF <<12), /* 15:8 */
+ PMR_B0 = (0xF << 0)|(0xF << 4),/* 7:0 */
+}PMAT1_BITS;
+
+/************************************************************************/
+/* */
+/* MIB counter definitions */
+/* */
+/************************************************************************/
+
+#define rcv_miss_pkts 0x00
+#define rcv_octets 0x01
+#define rcv_broadcast_pkts 0x02
+#define rcv_multicast_pkts 0x03
+#define rcv_undersize_pkts 0x04
+#define rcv_oversize_pkts 0x05
+#define rcv_fragments 0x06
+#define rcv_jabbers 0x07
+#define rcv_unicast_pkts 0x08
+#define rcv_alignment_errors 0x09
+#define rcv_fcs_errors 0x0A
+#define rcv_good_octets 0x0B
+#define rcv_mac_ctrl 0x0C
+#define rcv_flow_ctrl 0x0D
+#define rcv_pkts_64_octets 0x0E
+#define rcv_pkts_65to127_octets 0x0F
+#define rcv_pkts_128to255_octets 0x10
+#define rcv_pkts_256to511_octets 0x11
+#define rcv_pkts_512to1023_octets 0x12
+#define rcv_pkts_1024to1518_octets 0x13
+#define rcv_unsupported_opcode 0x14
+#define rcv_symbol_errors 0x15
+#define rcv_drop_pkts_ring1 0x16
+#define rcv_drop_pkts_ring2 0x17
+#define rcv_drop_pkts_ring3 0x18
+#define rcv_drop_pkts_ring4 0x19
+#define rcv_jumbo_pkts 0x1A
+
+#define xmt_underrun_pkts 0x20
+#define xmt_octets 0x21
+#define xmt_packets 0x22
+#define xmt_broadcast_pkts 0x23
+#define xmt_multicast_pkts 0x24
+#define xmt_collisions 0x25
+#define xmt_unicast_pkts 0x26
+#define xmt_one_collision 0x27
+#define xmt_multiple_collision 0x28
+#define xmt_deferred_transmit 0x29
+#define xmt_late_collision 0x2A
+#define xmt_excessive_defer 0x2B
+#define xmt_loss_carrier 0x2C
+#define xmt_excessive_collision 0x2D
+#define xmt_back_pressure 0x2E
+#define xmt_flow_ctrl 0x2F
+#define xmt_pkts_64_octets 0x30
+#define xmt_pkts_65to127_octets 0x31
+#define xmt_pkts_128to255_octets 0x32
+#define xmt_pkts_256to511_octets 0x33
+#define xmt_pkts_512to1023_octets 0x34
+#define xmt_pkts_1024to1518_octet 0x35
+#define xmt_oversize_pkts 0x36
+#define xmt_jumbo_pkts 0x37
+
+/* ipg parameters */
+#define DEFAULT_IPG 0x60
+#define IFS1_DELTA 36
+#define IPG_CONVERGE_JIFFIES (HZ/2)
+#define IPG_STABLE_TIME 5
+#define MIN_IPG 96
+#define MAX_IPG 255
+#define IPG_STEP 16
+#define CSTATE 1
+#define SSTATE 2
+
+/* amd8111e decriptor flag definitions */
+typedef enum {
+
+ OWN_BIT = (1 << 15),
+ ADD_FCS_BIT = (1 << 13),
+ LTINT_BIT = (1 << 12),
+ STP_BIT = (1 << 9),
+ ENP_BIT = (1 << 8),
+ KILL_BIT = (1 << 6),
+ TCC_VLAN_INSERT = (1 << 1),
+ TCC_VLAN_REPLACE = (1 << 1) |( 1<< 0),
+
+}TX_FLAG_BITS;
+
+typedef enum {
+ ERR_BIT = (1 << 14),
+ FRAM_BIT = (1 << 13),
+ OFLO_BIT = (1 << 12),
+ CRC_BIT = (1 << 11),
+ PAM_BIT = (1 << 6),
+ LAFM_BIT = (1 << 5),
+ BAM_BIT = (1 << 4),
+ TT_VLAN_TAGGED = (1 << 3) |(1 << 2),/* 0x000 */
+ TT_PRTY_TAGGED = (1 << 3),/* 0x0008 */
+
+}RX_FLAG_BITS;
+
+#define RESET_RX_FLAGS 0x0000
+#define TT_MASK 0x000c
+#define TCC_MASK 0x0003
+
+/* driver ioctl parameters */
+#define AMD8111E_REG_DUMP_LEN 13*sizeof(u32)
+
+/* crc generator constants */
+#define CRC32 0xedb88320
+#define INITCRC 0xFFFFFFFF
+
+/* kernel provided writeq does not write 64 bits into the amd8111e device register instead writes only higher 32bits data into lower 32bits of the register.
+BUG? */
+#define amd8111e_writeq(_UlData,_memMap) \
+ writel(*(u32*)(&_UlData), _memMap); \
+ writel(*(u32*)((u8*)(&_UlData)+4), _memMap+4)
+
+/* maps the external speed options to internal value */
+typedef enum {
+ SPEED_AUTONEG,
+ SPEED10_HALF,
+ SPEED10_FULL,
+ SPEED100_HALF,
+ SPEED100_FULL,
+}EXT_PHY_OPTION;
+
+
+#endif /* _AMD8111E_H */
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.c
new file mode 100644
index 0000000..5101a54
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.c
@@ -0,0 +1,1694 @@
+/*
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * Modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+FILE_LICENCE ( BSD3 );
+
+#include <stdlib.h>
+#include <gpxe/malloc.h>
+#include <gpxe/timer.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/pci.h>
+#include <gpxe/pci_io.h>
+
+#include "base.h"
+#include "reg.h"
+
+#define ATH5K_CALIB_INTERVAL 10 /* Calibrate PHY every 10 seconds */
+#define ATH5K_RETRIES 4 /* Number of times to retry packet sends */
+#define ATH5K_DESC_ALIGN 16 /* Alignment for TX/RX descriptors */
+
+/******************\
+* Internal defines *
+\******************/
+
+/* Known PCI ids */
+static struct pci_device_id ath5k_nics[] = {
+ PCI_ROM(0x168c, 0x0207, "ath5210e", "Atheros 5210 early", AR5K_AR5210),
+ PCI_ROM(0x168c, 0x0007, "ath5210", "Atheros 5210", AR5K_AR5210),
+ PCI_ROM(0x168c, 0x0011, "ath5311", "Atheros 5311 (AHB)", AR5K_AR5211),
+ PCI_ROM(0x168c, 0x0012, "ath5211", "Atheros 5211", AR5K_AR5211),
+ PCI_ROM(0x168c, 0x0013, "ath5212", "Atheros 5212", AR5K_AR5212),
+ PCI_ROM(0xa727, 0x0013, "ath5212c","3com Ath 5212", AR5K_AR5212),
+ PCI_ROM(0x10b7, 0x0013, "rdag675", "3com 3CRDAG675", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x1014, "ath5212m", "Ath 5212 miniPCI", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0014, "ath5212x14", "Atheros 5212 x14", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0015, "ath5212x15", "Atheros 5212 x15", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0016, "ath5212x16", "Atheros 5212 x16", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0017, "ath5212x17", "Atheros 5212 x17", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0018, "ath5212x18", "Atheros 5212 x18", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x0019, "ath5212x19", "Atheros 5212 x19", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001a, "ath2413", "Atheros 2413 Griffin", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001b, "ath5413", "Atheros 5413 Eagle", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001c, "ath5212e", "Atheros 5212 PCI-E", AR5K_AR5212),
+ PCI_ROM(0x168c, 0x001d, "ath2417", "Atheros 2417 Nala", AR5K_AR5212),
+};
+
+/* Known SREVs */
+static const struct ath5k_srev_name srev_names[] = {
+ { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
+ { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
+ { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
+ { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B },
+ { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 },
+ { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 },
+ { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 },
+ { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A },
+ { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 },
+ { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 },
+ { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 },
+ { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 },
+ { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 },
+ { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 },
+ { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 },
+ { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
+ { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
+ { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
+ { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
+ { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
+ { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
+ { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A },
+ { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
+ { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
+ { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
+ { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B },
+ { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
+ { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
+ { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B },
+ { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 },
+ { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
+ { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
+ { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
+ { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
+ { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
+ { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
+};
+
+#define ATH5K_SPMBL_NO 1
+#define ATH5K_SPMBL_YES 2
+#define ATH5K_SPMBL_BOTH 3
+
+static const struct {
+ u16 bitrate;
+ u8 short_pmbl;
+ u8 hw_code;
+} ath5k_rates[] = {
+ { 10, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_1M },
+ { 20, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_2M },
+ { 55, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_5_5M },
+ { 110, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_11M },
+ { 60, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_6M },
+ { 90, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_9M },
+ { 120, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_12M },
+ { 180, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_18M },
+ { 240, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_24M },
+ { 360, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_36M },
+ { 480, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_48M },
+ { 540, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_54M },
+ { 20, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE },
+ { 55, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE },
+ { 110, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE },
+ { 0, 0, 0 },
+};
+
+#define ATH5K_NR_RATES 15
+
+/*
+ * Prototypes - PCI stack related functions
+ */
+static int ath5k_probe(struct pci_device *pdev,
+ const struct pci_device_id *id);
+static void ath5k_remove(struct pci_device *pdev);
+
+struct pci_driver ath5k_pci_driver __pci_driver = {
+ .ids = ath5k_nics,
+ .id_count = sizeof(ath5k_nics) / sizeof(ath5k_nics[0]),
+ .probe = ath5k_probe,
+ .remove = ath5k_remove,
+};
+
+
+
+/*
+ * Prototypes - MAC 802.11 stack related functions
+ */
+static int ath5k_tx(struct net80211_device *dev, struct io_buffer *skb);
+static int ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan);
+static int ath5k_reset_wake(struct ath5k_softc *sc);
+static int ath5k_start(struct net80211_device *dev);
+static void ath5k_stop(struct net80211_device *dev);
+static int ath5k_config(struct net80211_device *dev, int changed);
+static void ath5k_poll(struct net80211_device *dev);
+static void ath5k_irq(struct net80211_device *dev, int enable);
+
+static struct net80211_device_operations ath5k_ops = {
+ .open = ath5k_start,
+ .close = ath5k_stop,
+ .transmit = ath5k_tx,
+ .poll = ath5k_poll,
+ .irq = ath5k_irq,
+ .config = ath5k_config,
+};
+
+/*
+ * Prototypes - Internal functions
+ */
+/* Attach detach */
+static int ath5k_attach(struct net80211_device *dev);
+static void ath5k_detach(struct net80211_device *dev);
+/* Channel/mode setup */
+static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
+ struct net80211_channel *channels,
+ unsigned int mode,
+ unsigned int max);
+static int ath5k_setup_bands(struct net80211_device *dev);
+static int ath5k_chan_set(struct ath5k_softc *sc,
+ struct net80211_channel *chan);
+static void ath5k_setcurmode(struct ath5k_softc *sc,
+ unsigned int mode);
+static void ath5k_mode_setup(struct ath5k_softc *sc);
+
+/* Descriptor setup */
+static int ath5k_desc_alloc(struct ath5k_softc *sc);
+static void ath5k_desc_free(struct ath5k_softc *sc);
+/* Buffers setup */
+static int ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
+static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
+static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
+ struct ath5k_buf *bf)
+{
+ if (!bf->iob)
+ return;
+
+ net80211_tx_complete(sc->dev, bf->iob, 0, ECANCELED);
+ bf->iob = NULL;
+}
+
+static inline void ath5k_rxbuf_free(struct ath5k_softc *sc __unused,
+ struct ath5k_buf *bf)
+{
+ free_iob(bf->iob);
+ bf->iob = NULL;
+}
+
+/* Queues setup */
+static int ath5k_txq_setup(struct ath5k_softc *sc,
+ int qtype, int subtype);
+static void ath5k_txq_drainq(struct ath5k_softc *sc,
+ struct ath5k_txq *txq);
+static void ath5k_txq_cleanup(struct ath5k_softc *sc);
+static void ath5k_txq_release(struct ath5k_softc *sc);
+/* Rx handling */
+static int ath5k_rx_start(struct ath5k_softc *sc);
+static void ath5k_rx_stop(struct ath5k_softc *sc);
+/* Tx handling */
+static void ath5k_tx_processq(struct ath5k_softc *sc,
+ struct ath5k_txq *txq);
+
+/* Interrupt handling */
+static int ath5k_init(struct ath5k_softc *sc);
+static int ath5k_stop_hw(struct ath5k_softc *sc);
+
+static void ath5k_calibrate(struct ath5k_softc *sc);
+
+/* Filter */
+static void ath5k_configure_filter(struct ath5k_softc *sc);
+
+/********************\
+* PCI Initialization *
+\********************/
+
+#if DBGLVL_MAX
+static const char *
+ath5k_chip_name(enum ath5k_srev_type type, u16 val)
+{
+ const char *name = "xxxxx";
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
+ if (srev_names[i].sr_type != type)
+ continue;
+
+ if ((val & 0xf0) == srev_names[i].sr_val)
+ name = srev_names[i].sr_name;
+
+ if ((val & 0xff) == srev_names[i].sr_val) {
+ name = srev_names[i].sr_name;
+ break;
+ }
+ }
+
+ return name;
+}
+#endif
+
+static int ath5k_probe(struct pci_device *pdev,
+ const struct pci_device_id *id)
+{
+ void *mem;
+ struct ath5k_softc *sc;
+ struct net80211_device *dev;
+ int ret;
+ u8 csz;
+
+ adjust_pci_device(pdev);
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+ if (csz == 0) {
+ /*
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 16);
+ }
+ /*
+ * The default setting of latency timer yields poor results,
+ * set it to the value used by other systems. It may be worth
+ * tweaking this setting more.
+ */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+ /*
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ mem = ioremap(pdev->membase, 0x10000);
+ if (!mem) {
+ DBG("ath5k: cannot remap PCI memory region\n");
+ ret = -EIO;
+ goto err;
+ }
+
+ /*
+ * Allocate dev (net80211 main struct)
+ * and dev->priv (driver private data)
+ */
+ dev = net80211_alloc(sizeof(*sc));
+ if (!dev) {
+ DBG("ath5k: cannot allocate 802.11 device\n");
+ ret = -ENOMEM;
+ goto err_map;
+ }
+
+ /* Initialize driver private data */
+ sc = dev->priv;
+ sc->dev = dev;
+ sc->pdev = pdev;
+
+ sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
+ if (!sc->hwinfo) {
+ DBG("ath5k: cannot allocate 802.11 hardware info structure\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
+ sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
+ sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
+ sc->hwinfo->channel_change_time = 5000;
+
+ /* Avoid working with the device until setup is complete */
+ sc->status |= ATH_STAT_INVALID;
+
+ sc->iobase = mem;
+ sc->cachelsz = csz * 4; /* convert to bytes */
+
+ DBG("ath5k: register base at %p (%08lx)\n", sc->iobase, pdev->membase);
+ DBG("ath5k: cache line size %d\n", sc->cachelsz);
+
+ /* Set private data */
+ pci_set_drvdata(pdev, dev);
+ dev->netdev->dev = (struct device *)pdev;
+
+ /* Initialize device */
+ ret = ath5k_hw_attach(sc, id->driver_data, &sc->ah);
+ if (ret)
+ goto err_free_hwinfo;
+
+ /* Finish private driver data initialization */
+ ret = ath5k_attach(dev);
+ if (ret)
+ goto err_ah;
+
+#if DBGLVL_MAX
+ DBG("Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+ sc->ah->ah_mac_srev, sc->ah->ah_phy_revision);
+
+ if (!sc->ah->ah_single_chip) {
+ /* Single chip radio (!RF5111) */
+ if (sc->ah->ah_radio_5ghz_revision &&
+ !sc->ah->ah_radio_2ghz_revision) {
+ /* No 5GHz support -> report 2GHz radio */
+ if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A)) {
+ DBG("RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* No 2GHz support (5110 and some
+ * 5Ghz only cards) -> report 5Ghz radio */
+ } else if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B)) {
+ DBG("RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* Multiband radio */
+ } else {
+ DBG("RF%s multiband radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ }
+ }
+ /* Multi chip radio (RF5111 - RF2111) ->
+ * report both 2GHz/5GHz radios */
+ else if (sc->ah->ah_radio_5ghz_revision &&
+ sc->ah->ah_radio_2ghz_revision) {
+ DBG("RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ DBG("RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_2ghz_revision),
+ sc->ah->ah_radio_2ghz_revision);
+ }
+ }
+#endif
+
+ /* Ready to go */
+ sc->status &= ~ATH_STAT_INVALID;
+
+ return 0;
+err_ah:
+ ath5k_hw_detach(sc->ah);
+err_free_hwinfo:
+ free(sc->hwinfo);
+err_free:
+ net80211_free(dev);
+err_map:
+ iounmap(mem);
+err:
+ return ret;
+}
+
+static void ath5k_remove(struct pci_device *pdev)
+{
+ struct net80211_device *dev = pci_get_drvdata(pdev);
+ struct ath5k_softc *sc = dev->priv;
+
+ ath5k_detach(dev);
+ ath5k_hw_detach(sc->ah);
+ iounmap(sc->iobase);
+ free(sc->hwinfo);
+ net80211_free(dev);
+}
+
+
+/***********************\
+* Driver Initialization *
+\***********************/
+
+static int
+ath5k_attach(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ /*
+ * Collect the channel list. The 802.11 layer
+ * is resposible for filtering this list based
+ * on settings like the phy mode and regulatory
+ * domain restrictions.
+ */
+ ret = ath5k_setup_bands(dev);
+ if (ret) {
+ DBG("ath5k: can't get channels\n");
+ goto err;
+ }
+
+ /* NB: setup here so ath5k_rate_update is happy */
+ if (ah->ah_modes & AR5K_MODE_BIT_11A)
+ ath5k_setcurmode(sc, AR5K_MODE_11A);
+ else
+ ath5k_setcurmode(sc, AR5K_MODE_11B);
+
+ /*
+ * Allocate tx+rx descriptors and populate the lists.
+ */
+ ret = ath5k_desc_alloc(sc);
+ if (ret) {
+ DBG("ath5k: can't allocate descriptors\n");
+ goto err;
+ }
+
+ /*
+ * Allocate hardware transmit queues. Note that hw functions
+ * handle reseting these queues at the needed time.
+ */
+ ret = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ if (ret) {
+ DBG("ath5k: can't setup xmit queue\n");
+ goto err_desc;
+ }
+
+ sc->last_calib_ticks = currticks();
+
+ ret = ath5k_eeprom_read_mac(ah, sc->hwinfo->hwaddr);
+ if (ret) {
+ DBG("ath5k: unable to read address from EEPROM: 0x%04x\n",
+ sc->pdev->device);
+ goto err_queues;
+ }
+
+ memset(sc->bssidmask, 0xff, ETH_ALEN);
+ ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+
+ ret = net80211_register(sc->dev, &ath5k_ops, sc->hwinfo);
+ if (ret) {
+ DBG("ath5k: can't register ieee80211 hw\n");
+ goto err_queues;
+ }
+
+ return 0;
+err_queues:
+ ath5k_txq_release(sc);
+err_desc:
+ ath5k_desc_free(sc);
+err:
+ return ret;
+}
+
+static void
+ath5k_detach(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+
+ net80211_unregister(dev);
+ ath5k_desc_free(sc);
+ ath5k_txq_release(sc);
+}
+
+
+
+
+/********************\
+* Channel/mode setup *
+\********************/
+
+/*
+ * Convert IEEE channel number to MHz frequency.
+ */
+static inline short
+ath5k_ieee2mhz(short chan)
+{
+ if (chan < 14)
+ return 2407 + 5 * chan;
+ if (chan == 14)
+ return 2484;
+ if (chan < 27)
+ return 2212 + 20 * chan;
+ return 5000 + 5 * chan;
+}
+
+static unsigned int
+ath5k_copy_channels(struct ath5k_hw *ah,
+ struct net80211_channel *channels,
+ unsigned int mode, unsigned int max)
+{
+ unsigned int i, count, size, chfreq, freq, ch;
+
+ if (!(ah->ah_modes & (1 << mode)))
+ return 0;
+
+ switch (mode) {
+ case AR5K_MODE_11A:
+ case AR5K_MODE_11A_TURBO:
+ /* 1..220, but 2GHz frequencies are filtered by check_channel */
+ size = 220;
+ chfreq = CHANNEL_5GHZ;
+ break;
+ case AR5K_MODE_11B:
+ case AR5K_MODE_11G:
+ case AR5K_MODE_11G_TURBO:
+ size = 26;
+ chfreq = CHANNEL_2GHZ;
+ break;
+ default:
+ return 0;
+ }
+
+ for (i = 0, count = 0; i < size && max > 0; i++) {
+ ch = i + 1 ;
+ freq = ath5k_ieee2mhz(ch);
+
+ /* Check if channel is supported by the chipset */
+ if (!ath5k_channel_ok(ah, freq, chfreq))
+ continue;
+
+ /* Write channel info and increment counter */
+ channels[count].center_freq = freq;
+ channels[count].maxpower = 0; /* use regulatory */
+ channels[count].band = (chfreq == CHANNEL_2GHZ) ?
+ NET80211_BAND_2GHZ : NET80211_BAND_5GHZ;
+ switch (mode) {
+ case AR5K_MODE_11A:
+ case AR5K_MODE_11G:
+ channels[count].hw_value = chfreq | CHANNEL_OFDM;
+ break;
+ case AR5K_MODE_11A_TURBO:
+ case AR5K_MODE_11G_TURBO:
+ channels[count].hw_value = chfreq |
+ CHANNEL_OFDM | CHANNEL_TURBO;
+ break;
+ case AR5K_MODE_11B:
+ channels[count].hw_value = CHANNEL_B;
+ }
+
+ count++;
+ max--;
+ }
+
+ return count;
+}
+
+static int
+ath5k_setup_bands(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int max_c, count_c = 0;
+ int i;
+ int band;
+
+ max_c = sizeof(sc->hwinfo->channels) / sizeof(sc->hwinfo->channels[0]);
+
+ /* 2GHz band */
+ if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11G) {
+ /* G mode */
+ band = NET80211_BAND_2GHZ;
+ sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
+ sc->hwinfo->modes = (NET80211_MODE_G | NET80211_MODE_B);
+
+ for (i = 0; i < 12; i++)
+ sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
+ sc->hwinfo->nr_rates[band] = 12;
+
+ sc->hwinfo->nr_channels =
+ ath5k_copy_channels(ah, sc->hwinfo->channels,
+ AR5K_MODE_11G, max_c);
+ count_c = sc->hwinfo->nr_channels;
+ max_c -= count_c;
+ } else if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B) {
+ /* B mode */
+ band = NET80211_BAND_2GHZ;
+ sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
+ sc->hwinfo->modes = NET80211_MODE_B;
+
+ for (i = 0; i < 4; i++)
+ sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
+ sc->hwinfo->nr_rates[band] = 4;
+
+ sc->hwinfo->nr_channels =
+ ath5k_copy_channels(ah, sc->hwinfo->channels,
+ AR5K_MODE_11B, max_c);
+ count_c = sc->hwinfo->nr_channels;
+ max_c -= count_c;
+ }
+
+ /* 5GHz band, A mode */
+ if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A) {
+ band = NET80211_BAND_5GHZ;
+ sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
+ sc->hwinfo->modes |= NET80211_MODE_A;
+
+ for (i = 0; i < 8; i++)
+ sc->hwinfo->rates[band][i] = ath5k_rates[i+4].bitrate;
+ sc->hwinfo->nr_rates[band] = 8;
+
+ sc->hwinfo->nr_channels =
+ ath5k_copy_channels(ah, sc->hwinfo->channels,
+ AR5K_MODE_11B, max_c);
+ count_c = sc->hwinfo->nr_channels;
+ max_c -= count_c;
+ }
+
+ return 0;
+}
+
+/*
+ * Set/change channels. If the channel is really being changed,
+ * it's done by reseting the chip. To accomplish this we must
+ * first cleanup any pending DMA, then restart stuff after a la
+ * ath5k_init.
+ */
+static int
+ath5k_chan_set(struct ath5k_softc *sc, struct net80211_channel *chan)
+{
+ if (chan->center_freq != sc->curchan->center_freq ||
+ chan->hw_value != sc->curchan->hw_value) {
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ DBG2("ath5k: resetting for channel change (%d -> %d MHz)\n",
+ sc->curchan->center_freq, chan->center_freq);
+ return ath5k_reset(sc, chan);
+ }
+
+ return 0;
+}
+
+static void
+ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+{
+ sc->curmode = mode;
+
+ if (mode == AR5K_MODE_11A) {
+ sc->curband = NET80211_BAND_5GHZ;
+ } else {
+ sc->curband = NET80211_BAND_2GHZ;
+ }
+}
+
+static void
+ath5k_mode_setup(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 rfilt;
+
+ /* configure rx filter */
+ rfilt = sc->filter_flags;
+ ath5k_hw_set_rx_filter(ah, rfilt);
+
+ if (ath5k_hw_hasbssidmask(ah))
+ ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
+
+ /* configure operational mode */
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_set_mcast_filter(ah, 0, 0);
+}
+
+static inline int
+ath5k_hw_rix_to_bitrate(int hw_rix)
+{
+ int i;
+
+ for (i = 0; i < ATH5K_NR_RATES; i++) {
+ if (ath5k_rates[i].hw_code == hw_rix)
+ return ath5k_rates[i].bitrate;
+ }
+
+ DBG("ath5k: invalid rix %02x\n", hw_rix);
+ return 10; /* use lowest rate */
+}
+
+int ath5k_bitrate_to_hw_rix(int bitrate)
+{
+ int i;
+
+ for (i = 0; i < ATH5K_NR_RATES; i++) {
+ if (ath5k_rates[i].bitrate == bitrate)
+ return ath5k_rates[i].hw_code;
+ }
+
+ DBG("ath5k: invalid bitrate %d\n", bitrate);
+ return ATH5K_RATE_CODE_1M; /* use lowest rate */
+}
+
+/***************\
+* Buffers setup *
+\***************/
+
+static struct io_buffer *
+ath5k_rx_iob_alloc(struct ath5k_softc *sc, u32 *iob_addr)
+{
+ struct io_buffer *iob;
+ unsigned int off;
+
+ /*
+ * Allocate buffer with headroom_needed space for the
+ * fake physical layer header at the start.
+ */
+ iob = alloc_iob(sc->rxbufsize + sc->cachelsz - 1);
+
+ if (!iob) {
+ DBG("ath5k: can't alloc iobuf of size %d\n",
+ sc->rxbufsize + sc->cachelsz - 1);
+ return NULL;
+ }
+
+ *iob_addr = virt_to_bus(iob->data);
+
+ /*
+ * Cache-line-align. This is important (for the
+ * 5210 at least) as not doing so causes bogus data
+ * in rx'd frames.
+ */
+ off = *iob_addr % sc->cachelsz;
+ if (off != 0) {
+ iob_reserve(iob, sc->cachelsz - off);
+ *iob_addr += sc->cachelsz - off;
+ }
+
+ return iob;
+}
+
+static int
+ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct io_buffer *iob = bf->iob;
+ struct ath5k_desc *ds;
+
+ if (!iob) {
+ iob = ath5k_rx_iob_alloc(sc, &bf->iobaddr);
+ if (!iob)
+ return -ENOMEM;
+ bf->iob = iob;
+ }
+
+ /*
+ * Setup descriptors. For receive we always terminate
+ * the descriptor list with a self-linked entry so we'll
+ * not get overrun under high load (as can happen with a
+ * 5212 when ANI processing enables PHY error frames).
+ *
+ * To insure the last descriptor is self-linked we create
+ * each descriptor as self-linked and add it to the end. As
+ * each additional descriptor is added the previous self-linked
+ * entry is ``fixed'' naturally. This should be safe even
+ * if DMA is happening. When processing RX interrupts we
+ * never remove/process the last, self-linked, entry on the
+ * descriptor list. This insures the hardware always has
+ * someplace to write a new frame.
+ */
+ ds = bf->desc;
+ ds->ds_link = bf->daddr; /* link to self */
+ ds->ds_data = bf->iobaddr;
+ if (ah->ah_setup_rx_desc(ah, ds,
+ iob_tailroom(iob), /* buffer size */
+ 0) != 0) {
+ DBG("ath5k: error setting up RX descriptor for %d bytes\n", iob_tailroom(iob));
+ return -EINVAL;
+ }
+
+ if (sc->rxlink != NULL)
+ *sc->rxlink = bf->daddr;
+ sc->rxlink = &ds->ds_link;
+ return 0;
+}
+
+static int
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq *txq = &sc->txq;
+ struct ath5k_desc *ds = bf->desc;
+ struct io_buffer *iob = bf->iob;
+ unsigned int pktlen, flags;
+ int ret;
+ u16 duration = 0;
+ u16 cts_rate = 0;
+
+ flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
+ bf->iobaddr = virt_to_bus(iob->data);
+ pktlen = iob_len(iob);
+
+ /* FIXME: If we are in g mode and rate is a CCK rate
+ * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
+ * from tx power (value is in dB units already) */
+ if (sc->dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
+ struct net80211_device *dev = sc->dev;
+
+ flags |= AR5K_TXDESC_CTSENA;
+ cts_rate = sc->hw_rtscts_rate;
+ duration = net80211_cts_duration(dev, pktlen);
+ }
+ ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
+ IEEE80211_TYP_FRAME_HEADER_LEN,
+ AR5K_PKT_TYPE_NORMAL, sc->power_level * 2,
+ sc->hw_rate, ATH5K_RETRIES,
+ AR5K_TXKEYIX_INVALID, 0, flags,
+ cts_rate, duration);
+ if (ret)
+ return ret;
+
+ ds->ds_link = 0;
+ ds->ds_data = bf->iobaddr;
+
+ list_add_tail(&bf->list, &txq->q);
+ if (txq->link == NULL) /* is this first packet? */
+ ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
+ else /* no, so only link it */
+ *txq->link = bf->daddr;
+
+ txq->link = &ds->ds_link;
+ ath5k_hw_start_tx_dma(ah, txq->qnum);
+ mb();
+
+ return 0;
+}
+
+/*******************\
+* Descriptors setup *
+\*******************/
+
+static int
+ath5k_desc_alloc(struct ath5k_softc *sc)
+{
+ struct ath5k_desc *ds;
+ struct ath5k_buf *bf;
+ u32 da;
+ unsigned int i;
+ int ret;
+
+ /* allocate descriptors */
+ sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + 1);
+ sc->desc = malloc_dma(sc->desc_len, ATH5K_DESC_ALIGN);
+ if (sc->desc == NULL) {
+ DBG("ath5k: can't allocate descriptors\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ memset(sc->desc, 0, sc->desc_len);
+ sc->desc_daddr = virt_to_bus(sc->desc);
+
+ ds = sc->desc;
+ da = sc->desc_daddr;
+
+ bf = calloc(ATH_TXBUF + ATH_RXBUF + 1, sizeof(struct ath5k_buf));
+ if (bf == NULL) {
+ DBG("ath5k: can't allocate buffer pointers\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+ sc->bufptr = bf;
+
+ INIT_LIST_HEAD(&sc->rxbuf);
+ for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->rxbuf);
+ }
+
+ INIT_LIST_HEAD(&sc->txbuf);
+ sc->txbuf_len = ATH_TXBUF;
+ for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->txbuf);
+ }
+
+ return 0;
+
+err_free:
+ free_dma(sc->desc, sc->desc_len);
+err:
+ sc->desc = NULL;
+ return ret;
+}
+
+static void
+ath5k_desc_free(struct ath5k_softc *sc)
+{
+ struct ath5k_buf *bf;
+
+ list_for_each_entry(bf, &sc->txbuf, list)
+ ath5k_txbuf_free(sc, bf);
+ list_for_each_entry(bf, &sc->rxbuf, list)
+ ath5k_rxbuf_free(sc, bf);
+
+ /* Free memory associated with all descriptors */
+ free_dma(sc->desc, sc->desc_len);
+
+ free(sc->bufptr);
+ sc->bufptr = NULL;
+}
+
+
+
+
+
+/**************\
+* Queues setup *
+\**************/
+
+static int
+ath5k_txq_setup(struct ath5k_softc *sc, int qtype, int subtype)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq *txq;
+ struct ath5k_txq_info qi = {
+ .tqi_subtype = subtype,
+ .tqi_aifs = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_max = AR5K_TXQ_USEDEFAULT
+ };
+ int qnum;
+
+ /*
+ * Enable interrupts only for EOL and DESC conditions.
+ * We mark tx descriptors to receive a DESC interrupt
+ * when a tx queue gets deep; otherwise waiting for the
+ * EOL to reap descriptors. Note that this is done to
+ * reduce interrupt load and this only defers reaping
+ * descriptors, never transmitting frames. Aside from
+ * reducing interrupts this also permits more concurrency.
+ * The only potential downside is if the tx queue backs
+ * up in which case the top half of the kernel may backup
+ * due to a lack of tx descriptors.
+ */
+ qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
+ AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
+ qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
+ if (qnum < 0) {
+ DBG("ath5k: can't set up a TX queue\n");
+ return -EIO;
+ }
+
+ txq = &sc->txq;
+ if (!txq->setup) {
+ txq->qnum = qnum;
+ txq->link = NULL;
+ INIT_LIST_HEAD(&txq->q);
+ txq->setup = 1;
+ }
+ return 0;
+}
+
+static void
+ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+ struct ath5k_buf *bf, *bf0;
+
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ath5k_txbuf_free(sc, bf);
+
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ }
+ txq->link = NULL;
+}
+
+/*
+ * Drain the transmit queues and reclaim resources.
+ */
+static void
+ath5k_txq_cleanup(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ if (!(sc->status & ATH_STAT_INVALID)) {
+ /* don't touch the hardware if marked invalid */
+ if (sc->txq.setup) {
+ ath5k_hw_stop_tx_dma(ah, sc->txq.qnum);
+ DBG("ath5k: txq [%d] %x, link %p\n",
+ sc->txq.qnum,
+ ath5k_hw_get_txdp(ah, sc->txq.qnum),
+ sc->txq.link);
+ }
+ }
+
+ if (sc->txq.setup)
+ ath5k_txq_drainq(sc, &sc->txq);
+}
+
+static void
+ath5k_txq_release(struct ath5k_softc *sc)
+{
+ if (sc->txq.setup) {
+ ath5k_hw_release_tx_queue(sc->ah);
+ sc->txq.setup = 0;
+ }
+}
+
+
+
+
+/*************\
+* RX Handling *
+\*************/
+
+/*
+ * Enable the receive h/w following a reset.
+ */
+static int
+ath5k_rx_start(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_buf *bf;
+ int ret;
+
+ sc->rxbufsize = IEEE80211_MAX_LEN;
+ if (sc->rxbufsize % sc->cachelsz != 0)
+ sc->rxbufsize += sc->cachelsz - (sc->rxbufsize % sc->cachelsz);
+
+ sc->rxlink = NULL;
+
+ list_for_each_entry(bf, &sc->rxbuf, list) {
+ ret = ath5k_rxbuf_setup(sc, bf);
+ if (ret != 0)
+ return ret;
+ }
+
+ bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
+
+ ath5k_hw_set_rxdp(ah, bf->daddr);
+ ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
+ ath5k_mode_setup(sc); /* set filters, etc. */
+ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
+
+ return 0;
+}
+
+/*
+ * Disable the receive h/w in preparation for a reset.
+ */
+static void
+ath5k_rx_stop(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
+ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
+ ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
+
+ sc->rxlink = NULL; /* just in case */
+}
+
+static void
+ath5k_handle_rx(struct ath5k_softc *sc)
+{
+ struct ath5k_rx_status rs;
+ struct io_buffer *iob, *next_iob;
+ u32 next_iob_addr;
+ struct ath5k_buf *bf, *bf_last;
+ struct ath5k_desc *ds;
+ int ret;
+
+ memset(&rs, 0, sizeof(rs));
+
+ if (list_empty(&sc->rxbuf)) {
+ DBG("ath5k: empty rx buf pool\n");
+ return;
+ }
+
+ bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
+
+ do {
+ bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
+ assert(bf->iob != NULL);
+ iob = bf->iob;
+ ds = bf->desc;
+
+ /*
+ * last buffer must not be freed to ensure proper hardware
+ * function. When the hardware finishes also a packet next to
+ * it, we are sure, it doesn't use it anymore and we can go on.
+ */
+ if (bf_last == bf)
+ bf->flags |= 1;
+ if (bf->flags) {
+ struct ath5k_buf *bf_next = list_entry(bf->list.next,
+ struct ath5k_buf, list);
+ ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
+ &rs);
+ if (ret)
+ break;
+ bf->flags &= ~1;
+ /* skip the overwritten one (even status is martian) */
+ goto next;
+ }
+
+ ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+ if (ret) {
+ if (ret != -EINPROGRESS) {
+ DBG("ath5k: error in processing rx desc: %s\n",
+ strerror(ret));
+ net80211_rx_err(sc->dev, NULL, -ret);
+ } else {
+ /* normal return, reached end of
+ available descriptors */
+ }
+ return;
+ }
+
+ if (rs.rs_more) {
+ DBG("ath5k: unsupported fragmented rx\n");
+ goto next;
+ }
+
+ if (rs.rs_status) {
+ if (rs.rs_status & AR5K_RXERR_PHY) {
+ DBG("ath5k: rx PHY error\n");
+ goto next;
+ }
+ if (rs.rs_status & AR5K_RXERR_CRC) {
+ net80211_rx_err(sc->dev, NULL, EIO);
+ goto next;
+ }
+ if (rs.rs_status & AR5K_RXERR_DECRYPT) {
+ /*
+ * Decrypt error. If the error occurred
+ * because there was no hardware key, then
+ * let the frame through so the upper layers
+ * can process it. This is necessary for 5210
+ * parts which have no way to setup a ``clear''
+ * key cache entry.
+ *
+ * XXX do key cache faulting
+ */
+ if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
+ !(rs.rs_status & AR5K_RXERR_CRC))
+ goto accept;
+ }
+
+ /* any other error, unhandled */
+ DBG("ath5k: packet rx status %x\n", rs.rs_status);
+ goto next;
+ }
+accept:
+ next_iob = ath5k_rx_iob_alloc(sc, &next_iob_addr);
+
+ /*
+ * If we can't replace bf->iob with a new iob under memory
+ * pressure, just skip this packet
+ */
+ if (!next_iob) {
+ DBG("ath5k: dropping packet under memory pressure\n");
+ goto next;
+ }
+
+ iob_put(iob, rs.rs_datalen);
+
+ /* The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. However, gPXE only
+ * supports standard 802.11 packets with 24-byte
+ * header, so no padding correction should be needed.
+ */
+
+ DBG2("ath5k: rx %d bytes, signal %d\n", rs.rs_datalen,
+ rs.rs_rssi);
+
+ net80211_rx(sc->dev, iob, rs.rs_rssi,
+ ath5k_hw_rix_to_bitrate(rs.rs_rate));
+
+ bf->iob = next_iob;
+ bf->iobaddr = next_iob_addr;
+next:
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->rxbuf);
+ } while (ath5k_rxbuf_setup(sc, bf) == 0);
+}
+
+
+
+
+/*************\
+* TX Handling *
+\*************/
+
+static void
+ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+ struct ath5k_tx_status ts;
+ struct ath5k_buf *bf, *bf0;
+ struct ath5k_desc *ds;
+ struct io_buffer *iob;
+ int ret;
+
+ memset(&ts, 0, sizeof(ts));
+
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ds = bf->desc;
+
+ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ if (ret) {
+ if (ret != -EINPROGRESS) {
+ DBG("ath5k: error in processing tx desc: %s\n",
+ strerror(ret));
+ } else {
+ /* normal return, reached end of tx completions */
+ }
+ break;
+ }
+
+ iob = bf->iob;
+ bf->iob = NULL;
+
+ DBG2("ath5k: tx %d bytes complete, %d retries\n",
+ iob_len(iob), ts.ts_retry[0]);
+
+ net80211_tx_complete(sc->dev, iob, ts.ts_retry[0],
+ ts.ts_status ? EIO : 0);
+
+ list_del(&bf->list);
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ }
+
+ if (list_empty(&txq->q))
+ txq->link = NULL;
+}
+
+static void
+ath5k_handle_tx(struct ath5k_softc *sc)
+{
+ ath5k_tx_processq(sc, &sc->txq);
+}
+
+
+/********************\
+* Interrupt handling *
+\********************/
+
+static void
+ath5k_irq(struct net80211_device *dev, int enable)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+
+ sc->irq_ena = enable;
+ ah->ah_ier = enable ? AR5K_IER_ENABLE : AR5K_IER_DISABLE;
+
+ ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
+ ath5k_hw_set_imr(ah, sc->imask);
+}
+
+static int
+ath5k_init(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ int ret, i;
+
+ /*
+ * Stop anything previously setup. This is safe
+ * no matter this is the first time through or not.
+ */
+ ath5k_stop_hw(sc);
+
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ sc->curchan = sc->dev->channels + sc->dev->channel;
+ sc->curband = sc->curchan->band;
+ sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+ AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
+ AR5K_INT_FATAL | AR5K_INT_GLOBAL;
+ ret = ath5k_reset(sc, NULL);
+ if (ret)
+ goto done;
+
+ /*
+ * Reset the key cache since some parts do not reset the
+ * contents on initial power up or resume from suspend.
+ */
+ for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+ ath5k_hw_reset_key(ah, i);
+
+ /* Set ack to be sent at low bit-rates */
+ ath5k_hw_set_ack_bitrate_high(ah, 0);
+
+ ret = 0;
+done:
+ mb();
+ return ret;
+}
+
+static int
+ath5k_stop_hw(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ /*
+ * Shutdown the hardware and driver:
+ * stop output from above
+ * disable interrupts
+ * turn off timers
+ * turn off the radio
+ * clear transmit machinery
+ * clear receive machinery
+ * drain and release tx queues
+ * reclaim beacon resources
+ * power down hardware
+ *
+ * Note that some of this work is not possible if the
+ * hardware is gone (invalid).
+ */
+
+ if (!(sc->status & ATH_STAT_INVALID)) {
+ ath5k_hw_set_imr(ah, 0);
+ }
+ ath5k_txq_cleanup(sc);
+ if (!(sc->status & ATH_STAT_INVALID)) {
+ ath5k_rx_stop(sc);
+ ath5k_hw_phy_disable(ah);
+ } else
+ sc->rxlink = NULL;
+
+ return 0;
+}
+
+static void
+ath5k_poll(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ enum ath5k_int status;
+ unsigned int counter = 1000;
+
+ if (currticks() - sc->last_calib_ticks >
+ ATH5K_CALIB_INTERVAL * ticks_per_sec()) {
+ ath5k_calibrate(sc);
+ sc->last_calib_ticks = currticks();
+ }
+
+ if ((sc->status & ATH_STAT_INVALID) ||
+ (sc->irq_ena && !ath5k_hw_is_intr_pending(ah)))
+ return;
+
+ do {
+ ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
+ DBGP("ath5k: status %#x/%#x\n", status, sc->imask);
+ if (status & AR5K_INT_FATAL) {
+ /*
+ * Fatal errors are unrecoverable.
+ * Typically these are caused by DMA errors.
+ */
+ DBG("ath5k: fatal error, resetting\n");
+ ath5k_reset_wake(sc);
+ } else if (status & AR5K_INT_RXORN) {
+ DBG("ath5k: rx overrun, resetting\n");
+ ath5k_reset_wake(sc);
+ } else {
+ if (status & AR5K_INT_RXEOL) {
+ /*
+ * NB: the hardware should re-read the link when
+ * RXE bit is written, but it doesn't work at
+ * least on older hardware revs.
+ */
+ DBG("ath5k: rx EOL\n");
+ sc->rxlink = NULL;
+ }
+ if (status & AR5K_INT_TXURN) {
+ /* bump tx trigger level */
+ DBG("ath5k: tx underrun\n");
+ ath5k_hw_update_tx_triglevel(ah, 1);
+ }
+ if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
+ ath5k_handle_rx(sc);
+ if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
+ | AR5K_INT_TXERR | AR5K_INT_TXEOL))
+ ath5k_handle_tx(sc);
+ }
+ } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
+
+ if (!counter)
+ DBG("ath5k: too many interrupts, giving up for now\n");
+}
+
+/*
+ * Periodically recalibrate the PHY to account
+ * for temperature/environment changes.
+ */
+static void
+ath5k_calibrate(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
+ /*
+ * Rfgain is out of bounds, reset the chip
+ * to load new gain values.
+ */
+ DBG("ath5k: resetting for calibration\n");
+ ath5k_reset_wake(sc);
+ }
+ if (ath5k_hw_phy_calibrate(ah, sc->curchan))
+ DBG("ath5k: calibration of channel %d failed\n",
+ sc->curchan->channel_nr);
+}
+
+
+/********************\
+* Net80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct net80211_device *dev, struct io_buffer *iob)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_buf *bf;
+ int rc;
+
+ /*
+ * The hardware expects the header padded to 4 byte boundaries.
+ * gPXE only ever sends 24-byte headers, so no action necessary.
+ */
+
+ if (list_empty(&sc->txbuf)) {
+ DBG("ath5k: dropping packet because no tx bufs available\n");
+ return -ENOBUFS;
+ }
+
+ bf = list_entry(sc->txbuf.next, struct ath5k_buf, list);
+ list_del(&bf->list);
+ sc->txbuf_len--;
+
+ bf->iob = iob;
+
+ if ((rc = ath5k_txbuf_setup(sc, bf)) != 0) {
+ bf->iob = NULL;
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ return rc;
+ }
+ return 0;
+}
+
+/*
+ * Reset the hardware. If chan is not NULL, then also pause rx/tx
+ * and change to the given channel.
+ */
+static int
+ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan)
+{
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ if (chan) {
+ ath5k_hw_set_imr(ah, 0);
+ ath5k_txq_cleanup(sc);
+ ath5k_rx_stop(sc);
+
+ sc->curchan = chan;
+ sc->curband = chan->band;
+ }
+
+ ret = ath5k_hw_reset(ah, sc->curchan, 1);
+ if (ret) {
+ DBG("ath5k: can't reset hardware: %s\n", strerror(ret));
+ return ret;
+ }
+
+ ret = ath5k_rx_start(sc);
+ if (ret) {
+ DBG("ath5k: can't start rx logic: %s\n", strerror(ret));
+ return ret;
+ }
+
+ /*
+ * Change channels and update the h/w rate map if we're switching;
+ * e.g. 11a to 11b/g.
+ *
+ * We may be doing a reset in response to an ioctl that changes the
+ * channel so update any state that might change as a result.
+ *
+ * XXX needed?
+ */
+/* ath5k_chan_change(sc, c); */
+
+ /* Reenable interrupts if necessary */
+ ath5k_irq(sc->dev, sc->irq_ena);
+
+ return 0;
+}
+
+static int ath5k_reset_wake(struct ath5k_softc *sc)
+{
+ return ath5k_reset(sc, sc->curchan);
+}
+
+static int ath5k_start(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ int ret;
+
+ if ((ret = ath5k_init(sc)) != 0)
+ return ret;
+
+ sc->assoc = 0;
+ ath5k_configure_filter(sc);
+ ath5k_hw_set_lladdr(sc->ah, dev->netdev->ll_addr);
+
+ return 0;
+}
+
+static void ath5k_stop(struct net80211_device *dev)
+{
+ struct ath5k_softc *sc = dev->priv;
+ u8 mac[ETH_ALEN] = {};
+
+ ath5k_hw_set_lladdr(sc->ah, mac);
+
+ ath5k_stop_hw(sc);
+}
+
+static int
+ath5k_config(struct net80211_device *dev, int changed)
+{
+ struct ath5k_softc *sc = dev->priv;
+ struct ath5k_hw *ah = sc->ah;
+ struct net80211_channel *chan = &dev->channels[dev->channel];
+ int ret;
+
+ if (changed & NET80211_CFG_CHANNEL) {
+ sc->power_level = chan->maxpower;
+ if ((ret = ath5k_chan_set(sc, chan)) != 0)
+ return ret;
+ }
+
+ if ((changed & NET80211_CFG_RATE) ||
+ (changed & NET80211_CFG_PHY_PARAMS)) {
+ int spmbl = ATH5K_SPMBL_NO;
+ u16 rate = dev->rates[dev->rate];
+ u16 slowrate = dev->rates[dev->rtscts_rate];
+ int i;
+
+ if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
+ spmbl = ATH5K_SPMBL_YES;
+
+ for (i = 0; i < ATH5K_NR_RATES; i++) {
+ if (ath5k_rates[i].bitrate == rate &&
+ (ath5k_rates[i].short_pmbl & spmbl))
+ sc->hw_rate = ath5k_rates[i].hw_code;
+
+ if (ath5k_rates[i].bitrate == slowrate &&
+ (ath5k_rates[i].short_pmbl & spmbl))
+ sc->hw_rtscts_rate = ath5k_rates[i].hw_code;
+ }
+ }
+
+ if (changed & NET80211_CFG_ASSOC) {
+ sc->assoc = !!(dev->state & NET80211_ASSOCIATED);
+ if (sc->assoc) {
+ memcpy(ah->ah_bssid, dev->bssid, ETH_ALEN);
+ } else {
+ memset(ah->ah_bssid, 0xff, ETH_ALEN);
+ }
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * o always accept unicast, broadcast, and multicast traffic
+ * o multicast traffic for all BSSIDs will be enabled if mac80211
+ * says it should be
+ * o maintain current state of phy ofdm or phy cck error reception.
+ * If the hardware detects any of these type of errors then
+ * ath5k_hw_get_rx_filter() will pass to us the respective
+ * hardware filters to be able to receive these type of frames.
+ * o probe request frames are accepted only when operating in
+ * hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ * - when operating in adhoc mode so the 802.11 layer creates
+ * node table entries for peers,
+ * - when operating in station mode for collecting rssi data when
+ * the station is otherwise quiet, or
+ * - when scanning
+ */
+static void ath5k_configure_filter(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 mfilt[2], rfilt;
+
+ /* Enable all multicast */
+ mfilt[0] = ~0;
+ mfilt[1] = ~0;
+
+ /* Enable data frames and beacons */
+ rfilt = (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
+ AR5K_RX_FILTER_MCAST | AR5K_RX_FILTER_BEACON);
+
+ /* Set filters */
+ ath5k_hw_set_rx_filter(ah, rfilt);
+
+ /* Set multicast bits */
+ ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
+
+ /* Set the cached hw filter flags, this will alter actually
+ * be set in HW */
+ sc->filter_flags = rfilt;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.h
new file mode 100644
index 0000000..c79fbec
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k.h
@@ -0,0 +1,1275 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ATH5K_H
+#define _ATH5K_H
+
+FILE_LICENCE ( MIT );
+
+#include <stddef.h>
+#include <byteswap.h>
+#include <gpxe/io.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/net80211.h>
+#include <errno.h>
+
+/* Keep all ath5k files under one errfile ID */
+#undef ERRFILE
+#define ERRFILE ERRFILE_ath5k
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+/* RX/TX descriptor hw structs */
+#include "desc.h"
+
+/* EEPROM structs/offsets */
+#include "eeprom.h"
+
+/* PCI IDs */
+#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
+
+/****************************\
+ GENERIC DRIVER DEFINITIONS
+\****************************/
+
+/*
+ * AR5K REGISTER ACCESS
+ */
+
+/* Some macros to read/write fields */
+
+/* First shift, then mask */
+#define AR5K_REG_SM(_val, _flags) \
+ (((_val) << _flags##_S) & (_flags))
+
+/* First mask, then shift */
+#define AR5K_REG_MS(_val, _flags) \
+ (((_val) & (_flags)) >> _flags##_S)
+
+/* Some registers can hold multiple values of interest. For this
+ * reason when we want to write to these registers we must first
+ * retrieve the values which we do not want to clear (lets call this
+ * old_data) and then set the register with this and our new_value:
+ * ( old_data | new_value) */
+#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
+ (((_val) << _flags##_S) & (_flags)), _reg)
+
+#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
+ (_mask)) | (_flags), _reg)
+
+#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
+
+#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
+
+/* Access to PHY registers */
+#define AR5K_PHY_READ(ah, _reg) \
+ ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
+
+#define AR5K_PHY_WRITE(ah, _reg, _val) \
+ ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
+
+/* Access QCU registers per queue */
+#define AR5K_REG_READ_Q(ah, _reg, _queue) \
+ (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
+
+#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
+ ath5k_hw_reg_write(ah, (1 << _queue), _reg)
+
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
+ _reg |= 1 << _queue; \
+} while (0)
+
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
+ _reg &= ~(1 << _queue); \
+} while (0)
+
+/* Used while writing initvals */
+#define AR5K_REG_WAIT(_i) do { \
+ if (_i % 64) \
+ udelay(1); \
+} while (0)
+
+/* Register dumps are done per operation mode */
+#define AR5K_INI_RFGAIN_5GHZ 0
+#define AR5K_INI_RFGAIN_2GHZ 1
+
+/* TODO: Clean this up */
+#define AR5K_INI_VAL_11A 0
+#define AR5K_INI_VAL_11A_TURBO 1
+#define AR5K_INI_VAL_11B 2
+#define AR5K_INI_VAL_11G 3
+#define AR5K_INI_VAL_11G_TURBO 4
+#define AR5K_INI_VAL_XR 0
+#define AR5K_INI_VAL_MAX 5
+
+/* Used for BSSID etc manipulation */
+#define AR5K_LOW_ID(_a)( \
+(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
+)
+
+#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
+
+#define IEEE80211_MAX_LEN 2352
+
+/*
+ * Some tuneable values (these should be changeable by the user)
+ */
+#define AR5K_TUNE_DMA_BEACON_RESP 2
+#define AR5K_TUNE_SW_BEACON_RESP 10
+#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
+#define AR5K_TUNE_RADAR_ALERT 0
+#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
+#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1)
+#define AR5K_TUNE_REGISTER_TIMEOUT 20000
+/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
+ * be the max value. */
+#define AR5K_TUNE_RSSI_THRES 129
+/* This must be set when setting the RSSI threshold otherwise it can
+ * prevent a reset. If AR5K_RSSI_THR is read after writing to it
+ * the BMISS_THRES will be seen as 0, seems harware doesn't keep
+ * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * For AR5211+ this seems to be up to 255. */
+#define AR5K_TUNE_BMISS_THRES 7
+#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
+#define AR5K_TUNE_BEACON_INTERVAL 100
+#define AR5K_TUNE_AIFS 2
+#define AR5K_TUNE_AIFS_11B 2
+#define AR5K_TUNE_AIFS_XR 0
+#define AR5K_TUNE_CWMIN 15
+#define AR5K_TUNE_CWMIN_11B 31
+#define AR5K_TUNE_CWMIN_XR 3
+#define AR5K_TUNE_CWMAX 1023
+#define AR5K_TUNE_CWMAX_11B 1023
+#define AR5K_TUNE_CWMAX_XR 7
+#define AR5K_TUNE_NOISE_FLOOR -72
+#define AR5K_TUNE_MAX_TXPOWER 63
+#define AR5K_TUNE_DEFAULT_TXPOWER 25
+#define AR5K_TUNE_TPC_TXPOWER 0
+#define AR5K_TUNE_ANT_DIVERSITY 1
+#define AR5K_TUNE_HWTXTRIES 4
+
+#define AR5K_INIT_CARR_SENSE_EN 1
+
+/*Swap RX/TX Descriptor for big endian archs*/
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define AR5K_INIT_CFG ( \
+ AR5K_CFG_SWTD | AR5K_CFG_SWRD \
+)
+#else
+#define AR5K_INIT_CFG 0x00000000
+#endif
+
+/* Initial values */
+#define AR5K_INIT_CYCRSSI_THR1 2
+#define AR5K_INIT_TX_LATENCY 502
+#define AR5K_INIT_USEC 39
+#define AR5K_INIT_USEC_TURBO 79
+#define AR5K_INIT_USEC_32 31
+#define AR5K_INIT_SLOT_TIME 396
+#define AR5K_INIT_SLOT_TIME_TURBO 480
+#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
+#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
+#define AR5K_INIT_PROG_IFS 920
+#define AR5K_INIT_PROG_IFS_TURBO 960
+#define AR5K_INIT_EIFS 3440
+#define AR5K_INIT_EIFS_TURBO 6880
+#define AR5K_INIT_SIFS 560
+#define AR5K_INIT_SIFS_TURBO 480
+#define AR5K_INIT_SH_RETRY 10
+#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
+#define AR5K_INIT_SSH_RETRY 32
+#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
+#define AR5K_INIT_TX_RETRY 10
+
+#define AR5K_INIT_TRANSMIT_LATENCY ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC) \
+)
+#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC_TURBO) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
+ (AR5K_INIT_PROG_IFS) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
+ (AR5K_INIT_PROG_IFS_TURBO) \
+)
+
+/* token to use for aifs, cwmin, cwmax in MadWiFi */
+#define AR5K_TXQ_USEDEFAULT ((u32) -1)
+
+/* GENERIC CHIPSET DEFINITIONS */
+
+/* MAC Chips */
+enum ath5k_version {
+ AR5K_AR5210 = 0,
+ AR5K_AR5211 = 1,
+ AR5K_AR5212 = 2,
+};
+
+/* PHY Chips */
+enum ath5k_radio {
+ AR5K_RF5110 = 0,
+ AR5K_RF5111 = 1,
+ AR5K_RF5112 = 2,
+ AR5K_RF2413 = 3,
+ AR5K_RF5413 = 4,
+ AR5K_RF2316 = 5,
+ AR5K_RF2317 = 6,
+ AR5K_RF2425 = 7,
+};
+
+/*
+ * Common silicon revision/version values
+ */
+
+enum ath5k_srev_type {
+ AR5K_VERSION_MAC,
+ AR5K_VERSION_RAD,
+};
+
+struct ath5k_srev_name {
+ const char *sr_name;
+ enum ath5k_srev_type sr_type;
+ unsigned sr_val;
+};
+
+#define AR5K_SREV_UNKNOWN 0xffff
+
+#define AR5K_SREV_AR5210 0x00 /* Crete */
+#define AR5K_SREV_AR5311 0x10 /* Maui 1 */
+#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */
+#define AR5K_SREV_AR5311B 0x30 /* Spirit */
+#define AR5K_SREV_AR5211 0x40 /* Oahu */
+#define AR5K_SREV_AR5212 0x50 /* Venice */
+#define AR5K_SREV_AR5213 0x55 /* ??? */
+#define AR5K_SREV_AR5213A 0x59 /* Hainan */
+#define AR5K_SREV_AR2413 0x78 /* Griffin lite */
+#define AR5K_SREV_AR2414 0x70 /* Griffin */
+#define AR5K_SREV_AR5424 0x90 /* Condor */
+#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
+#define AR5K_SREV_AR5414 0xa0 /* Eagle */
+#define AR5K_SREV_AR2415 0xb0 /* Talon */
+#define AR5K_SREV_AR5416 0xc0 /* PCI-E */
+#define AR5K_SREV_AR5418 0xca /* PCI-E */
+#define AR5K_SREV_AR2425 0xe0 /* Swan */
+#define AR5K_SREV_AR2417 0xf0 /* Nala */
+
+#define AR5K_SREV_RAD_5110 0x00
+#define AR5K_SREV_RAD_5111 0x10
+#define AR5K_SREV_RAD_5111A 0x15
+#define AR5K_SREV_RAD_2111 0x20
+#define AR5K_SREV_RAD_5112 0x30
+#define AR5K_SREV_RAD_5112A 0x35
+#define AR5K_SREV_RAD_5112B 0x36
+#define AR5K_SREV_RAD_2112 0x40
+#define AR5K_SREV_RAD_2112A 0x45
+#define AR5K_SREV_RAD_2112B 0x46
+#define AR5K_SREV_RAD_2413 0x50
+#define AR5K_SREV_RAD_5413 0x60
+#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */
+#define AR5K_SREV_RAD_2317 0x80
+#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */
+#define AR5K_SREV_RAD_2425 0xa2
+#define AR5K_SREV_RAD_5133 0xc0
+
+#define AR5K_SREV_PHY_5211 0x30
+#define AR5K_SREV_PHY_5212 0x41
+#define AR5K_SREV_PHY_5212A 0x42
+#define AR5K_SREV_PHY_5212B 0x43
+#define AR5K_SREV_PHY_2413 0x45
+#define AR5K_SREV_PHY_5413 0x61
+#define AR5K_SREV_PHY_2425 0x70
+
+/*
+ * Some of this information is based on Documentation from:
+ *
+ * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
+ *
+ * Modulation for Atheros' eXtended Range - range enhancing extension that is
+ * supposed to double the distance an Atheros client device can keep a
+ * connection with an Atheros access point. This is achieved by increasing
+ * the receiver sensitivity up to, -105dBm, which is about 20dB above what
+ * the 802.11 specifications demand. In addition, new (proprietary) data rates
+ * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
+ *
+ * Please note that can you either use XR or TURBO but you cannot use both,
+ * they are exclusive.
+ *
+ */
+#define MODULATION_XR 0x00000200
+
+/*
+ * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
+ * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
+ * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
+ * channels. To use this feature your Access Point must also suport it.
+ * There is also a distinction between "static" and "dynamic" turbo modes:
+ *
+ * - Static: is the dumb version: devices set to this mode stick to it until
+ * the mode is turned off.
+ * - Dynamic: is the intelligent version, the network decides itself if it
+ * is ok to use turbo. As soon as traffic is detected on adjacent channels
+ * (which would get used in turbo mode), or when a non-turbo station joins
+ * the network, turbo mode won't be used until the situation changes again.
+ * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
+ * monitors the used radio band in order to decide whether turbo mode may
+ * be used or not.
+ *
+ * This article claims Super G sticks to bonding of channels 5 and 6 for
+ * USA:
+ *
+ * http://www.pcworld.com/article/id,113428-page,1/article.html
+ *
+ * The channel bonding seems to be driver specific though. In addition to
+ * deciding what channels will be used, these "Turbo" modes are accomplished
+ * by also enabling the following features:
+ *
+ * - Bursting: allows multiple frames to be sent at once, rather than pausing
+ * after each frame. Bursting is a standards-compliant feature that can be
+ * used with any Access Point.
+ * - Fast frames: increases the amount of information that can be sent per
+ * frame, also resulting in a reduction of transmission overhead. It is a
+ * proprietary feature that needs to be supported by the Access Point.
+ * - Compression: data frames are compressed in real time using a Lempel Ziv
+ * algorithm. This is done transparently. Once this feature is enabled,
+ * compression and decompression takes place inside the chipset, without
+ * putting additional load on the host CPU.
+ *
+ */
+#define MODULATION_TURBO 0x00000080
+
+enum ath5k_driver_mode {
+ AR5K_MODE_11A = 0,
+ AR5K_MODE_11A_TURBO = 1,
+ AR5K_MODE_11B = 2,
+ AR5K_MODE_11G = 3,
+ AR5K_MODE_11G_TURBO = 4,
+ AR5K_MODE_XR = 5,
+};
+
+enum {
+ AR5K_MODE_BIT_11A = (1 << AR5K_MODE_11A),
+ AR5K_MODE_BIT_11A_TURBO = (1 << AR5K_MODE_11A_TURBO),
+ AR5K_MODE_BIT_11B = (1 << AR5K_MODE_11B),
+ AR5K_MODE_BIT_11G = (1 << AR5K_MODE_11G),
+ AR5K_MODE_BIT_11G_TURBO = (1 << AR5K_MODE_11G_TURBO),
+ AR5K_MODE_BIT_XR = (1 << AR5K_MODE_XR),
+};
+
+/****************\
+ TX DEFINITIONS
+\****************/
+
+/*
+ * TX Status descriptor
+ */
+struct ath5k_tx_status {
+ u16 ts_seqnum;
+ u16 ts_tstamp;
+ u8 ts_status;
+ u8 ts_rate[4];
+ u8 ts_retry[4];
+ u8 ts_final_idx;
+ s8 ts_rssi;
+ u8 ts_shortretry;
+ u8 ts_longretry;
+ u8 ts_virtcol;
+ u8 ts_antenna;
+} __attribute__ ((packed));
+
+#define AR5K_TXSTAT_ALTRATE 0x80
+#define AR5K_TXERR_XRETRY 0x01
+#define AR5K_TXERR_FILT 0x02
+#define AR5K_TXERR_FIFO 0x04
+
+/**
+ * enum ath5k_tx_queue - Queue types used to classify tx queues.
+ * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
+ * @AR5K_TX_QUEUE_DATA: A normal data queue
+ * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
+ * @AR5K_TX_QUEUE_BEACON: The beacon queue
+ * @AR5K_TX_QUEUE_CAB: The after-beacon queue
+ * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
+ */
+enum ath5k_tx_queue {
+ AR5K_TX_QUEUE_INACTIVE = 0,
+ AR5K_TX_QUEUE_DATA,
+ AR5K_TX_QUEUE_XR_DATA,
+ AR5K_TX_QUEUE_BEACON,
+ AR5K_TX_QUEUE_CAB,
+ AR5K_TX_QUEUE_UAPSD,
+};
+
+/*
+ * Queue syb-types to classify normal data queues.
+ * These are the 4 Access Categories as defined in
+ * WME spec. 0 is the lowest priority and 4 is the
+ * highest. Normal data that hasn't been classified
+ * goes to the Best Effort AC.
+ */
+enum ath5k_tx_queue_subtype {
+ AR5K_WME_AC_BK = 0, /*Background traffic*/
+ AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
+ AR5K_WME_AC_VI, /*Video traffic*/
+ AR5K_WME_AC_VO, /*Voice traffic*/
+};
+
+/*
+ * Queue ID numbers as returned by the hw functions, each number
+ * represents a hw queue. If hw does not support hw queues
+ * (eg 5210) all data goes in one queue. These match
+ * d80211 definitions (net80211/MadWiFi don't use them).
+ */
+enum ath5k_tx_queue_id {
+ AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
+ AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1,
+ AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/
+ AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/
+ AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
+ AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
+ AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/
+ AR5K_TX_QUEUE_ID_UAPSD = 8,
+ AR5K_TX_QUEUE_ID_XR_DATA = 9,
+};
+
+/*
+ * Flags to set hw queue's parameters...
+ */
+#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */
+#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */
+#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
+#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */
+#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */
+#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */
+#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
+
+/*
+ * A struct to hold tx queue's parameters
+ */
+struct ath5k_txq_info {
+ enum ath5k_tx_queue tqi_type;
+ enum ath5k_tx_queue_subtype tqi_subtype;
+ u16 tqi_flags; /* Tx queue flags (see above) */
+ u32 tqi_aifs; /* Arbitrated Interframe Space */
+ s32 tqi_cw_min; /* Minimum Contention Window */
+ s32 tqi_cw_max; /* Maximum Contention Window */
+ u32 tqi_cbr_period; /* Constant bit rate period */
+ u32 tqi_cbr_overflow_limit;
+ u32 tqi_burst_time;
+ u32 tqi_ready_time; /* Not used */
+};
+
+/*
+ * Transmit packet types.
+ * used on tx control descriptor
+ * TODO: Use them inside base.c corectly
+ */
+enum ath5k_pkt_type {
+ AR5K_PKT_TYPE_NORMAL = 0,
+ AR5K_PKT_TYPE_ATIM = 1,
+ AR5K_PKT_TYPE_PSPOLL = 2,
+ AR5K_PKT_TYPE_BEACON = 3,
+ AR5K_PKT_TYPE_PROBE_RESP = 4,
+ AR5K_PKT_TYPE_PIFS = 5,
+};
+
+/*
+ * TX power and TPC settings
+ */
+#define AR5K_TXPOWER_OFDM(_r, _v) ( \
+ ((0 & 1) << ((_v) + 6)) | \
+ (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \
+)
+
+#define AR5K_TXPOWER_CCK(_r, _v) ( \
+ (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \
+)
+
+/*
+ * DMA size definitions (2^n+2)
+ */
+enum ath5k_dmasize {
+ AR5K_DMASIZE_4B = 0,
+ AR5K_DMASIZE_8B,
+ AR5K_DMASIZE_16B,
+ AR5K_DMASIZE_32B,
+ AR5K_DMASIZE_64B,
+ AR5K_DMASIZE_128B,
+ AR5K_DMASIZE_256B,
+ AR5K_DMASIZE_512B
+};
+
+
+/****************\
+ RX DEFINITIONS
+\****************/
+
+/*
+ * RX Status descriptor
+ */
+struct ath5k_rx_status {
+ u16 rs_datalen;
+ u16 rs_tstamp;
+ u8 rs_status;
+ u8 rs_phyerr;
+ s8 rs_rssi;
+ u8 rs_keyix;
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+};
+
+#define AR5K_RXERR_CRC 0x01
+#define AR5K_RXERR_PHY 0x02
+#define AR5K_RXERR_FIFO 0x04
+#define AR5K_RXERR_DECRYPT 0x08
+#define AR5K_RXERR_MIC 0x10
+#define AR5K_RXKEYIX_INVALID ((u8) - 1)
+#define AR5K_TXKEYIX_INVALID ((u32) - 1)
+
+
+/*
+ * TSF to TU conversion:
+ *
+ * TSF is a 64bit value in usec (microseconds).
+ * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of
+ * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024).
+ */
+#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+
+
+/*******************************\
+ GAIN OPTIMIZATION DEFINITIONS
+\*******************************/
+
+enum ath5k_rfgain {
+ AR5K_RFGAIN_INACTIVE = 0,
+ AR5K_RFGAIN_ACTIVE,
+ AR5K_RFGAIN_READ_REQUESTED,
+ AR5K_RFGAIN_NEED_CHANGE,
+};
+
+struct ath5k_gain {
+ u8 g_step_idx;
+ u8 g_current;
+ u8 g_target;
+ u8 g_low;
+ u8 g_high;
+ u8 g_f_corr;
+ u8 g_state;
+};
+
+/********************\
+ COMMON DEFINITIONS
+\********************/
+
+#define AR5K_SLOT_TIME_9 396
+#define AR5K_SLOT_TIME_20 880
+#define AR5K_SLOT_TIME_MAX 0xffff
+
+/* channel_flags */
+#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
+#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
+#define CHANNEL_CCK 0x0020 /* CCK channel */
+#define CHANNEL_OFDM 0x0040 /* OFDM channel */
+#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
+#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
+#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
+#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
+#define CHANNEL_XR 0x0800 /* XR channel */
+
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_108A CHANNEL_T
+#define CHANNEL_108G CHANNEL_TG
+#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
+
+#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
+ CHANNEL_TURBO)
+
+#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO)
+#define CHANNEL_MODES CHANNEL_ALL
+
+/*
+ * Used internaly for reset_tx_queue).
+ * Also see struct struct net80211_channel.
+ */
+#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0)
+#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0)
+
+/*
+ * The following structure is used to map 2GHz channels to
+ * 5GHz Atheros channels.
+ * TODO: Clean up
+ */
+struct ath5k_athchan_2ghz {
+ u32 a2_flags;
+ u16 a2_athchan;
+};
+
+
+/******************\
+ RATE DEFINITIONS
+\******************/
+
+/**
+ * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
+ *
+ * The rate code is used to get the RX rate or set the TX rate on the
+ * hardware descriptors. It is also used for internal modulation control
+ * and settings.
+ *
+ * This is the hardware rate map we are aware of:
+ *
+ * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
+ * rate_kbps 3000 1000 ? ? ? 2000 500 48000
+ *
+ * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10
+ * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
+ *
+ * rate_code 17 18 19 20 21 22 23 24
+ * rate_kbps ? ? ? ? ? ? ? 11000
+ *
+ * rate_code 25 26 27 28 29 30 31 32
+ * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ?
+ *
+ * "S" indicates CCK rates with short preamble.
+ *
+ * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
+ * lowest 4 bits, so they are the same as below with a 0xF mask.
+ * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
+ * We handle this in ath5k_setup_bands().
+ */
+#define AR5K_MAX_RATES 32
+
+/* B */
+#define ATH5K_RATE_CODE_1M 0x1B
+#define ATH5K_RATE_CODE_2M 0x1A
+#define ATH5K_RATE_CODE_5_5M 0x19
+#define ATH5K_RATE_CODE_11M 0x18
+/* A and G */
+#define ATH5K_RATE_CODE_6M 0x0B
+#define ATH5K_RATE_CODE_9M 0x0F
+#define ATH5K_RATE_CODE_12M 0x0A
+#define ATH5K_RATE_CODE_18M 0x0E
+#define ATH5K_RATE_CODE_24M 0x09
+#define ATH5K_RATE_CODE_36M 0x0D
+#define ATH5K_RATE_CODE_48M 0x08
+#define ATH5K_RATE_CODE_54M 0x0C
+/* XR */
+#define ATH5K_RATE_CODE_XR_500K 0x07
+#define ATH5K_RATE_CODE_XR_1M 0x02
+#define ATH5K_RATE_CODE_XR_2M 0x06
+#define ATH5K_RATE_CODE_XR_3M 0x01
+
+/* adding this flag to rate_code enables short preamble */
+#define AR5K_SET_SHORT_PREAMBLE 0x04
+
+/*
+ * Crypto definitions
+ */
+
+#define AR5K_KEYCACHE_SIZE 8
+
+/***********************\
+ HW RELATED DEFINITIONS
+\***********************/
+
+/*
+ * Misc definitions
+ */
+#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
+
+#define AR5K_ASSERT_ENTRY(_e, _s) do { \
+ if (_e >= _s) \
+ return 0; \
+} while (0)
+
+/*
+ * Hardware interrupt abstraction
+ */
+
+/**
+ * enum ath5k_int - Hardware interrupt masks helpers
+ *
+ * @AR5K_INT_RX: mask to identify received frame interrupts, of type
+ * AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
+ * @AR5K_INT_RXNOFRM: No frame received (?)
+ * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
+ * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ * LinkPtr is NULL. For more details, refer to:
+ * http://www.freepatentsonline.com/20030225739.html
+ * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
+ * Note that Rx overrun is not always fatal, on some chips we can continue
+ * operation without reseting the card, that's why int_fatal is not
+ * common for all chips.
+ * @AR5K_INT_TX: mask to identify received frame interrupts, of type
+ * AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
+ * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
+ * We currently do increments on interrupt by
+ * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
+ * checked. We should do this with ath5k_hw_update_mib_counters() but
+ * it seems we should also then do some noise immunity work.
+ * @AR5K_INT_RXPHY: RX PHY Error
+ * @AR5K_INT_RXKCM: RX Key cache miss
+ * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
+ * beacon that must be handled in software. The alternative is if you
+ * have VEOL support, in that case you let the hardware deal with things.
+ * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
+ * beacons from the AP have associated with, we should probably try to
+ * reassociate. When in IBSS mode this might mean we have not received
+ * any beacons from any local stations. Note that every station in an
+ * IBSS schedules to send beacons at the Target Beacon Transmission Time
+ * (TBTT) with a random backoff.
+ * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
+ * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
+ * until properly handled
+ * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
+ * errors. These types of errors we can enable seem to be of type
+ * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ * @AR5K_INT_GLOBAL: Used to clear and set the IER
+ * @AR5K_INT_NOCARD: signals the card has been removed
+ * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
+ * bit value
+ *
+ * These are mapped to take advantage of some common bits
+ * between the MACs, to be able to set intr properties
+ * easier. Some of them are not used yet inside hw.c. Most map
+ * to the respective hw interrupt value as they are common amogst different
+ * MACs.
+ */
+enum ath5k_int {
+ AR5K_INT_RXOK = 0x00000001,
+ AR5K_INT_RXDESC = 0x00000002,
+ AR5K_INT_RXERR = 0x00000004,
+ AR5K_INT_RXNOFRM = 0x00000008,
+ AR5K_INT_RXEOL = 0x00000010,
+ AR5K_INT_RXORN = 0x00000020,
+ AR5K_INT_TXOK = 0x00000040,
+ AR5K_INT_TXDESC = 0x00000080,
+ AR5K_INT_TXERR = 0x00000100,
+ AR5K_INT_TXNOFRM = 0x00000200,
+ AR5K_INT_TXEOL = 0x00000400,
+ AR5K_INT_TXURN = 0x00000800,
+ AR5K_INT_MIB = 0x00001000,
+ AR5K_INT_SWI = 0x00002000,
+ AR5K_INT_RXPHY = 0x00004000,
+ AR5K_INT_RXKCM = 0x00008000,
+ AR5K_INT_SWBA = 0x00010000,
+ AR5K_INT_BRSSI = 0x00020000,
+ AR5K_INT_BMISS = 0x00040000,
+ AR5K_INT_FATAL = 0x00080000, /* Non common */
+ AR5K_INT_BNR = 0x00100000, /* Non common */
+ AR5K_INT_TIM = 0x00200000, /* Non common */
+ AR5K_INT_DTIM = 0x00400000, /* Non common */
+ AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */
+ AR5K_INT_GPIO = 0x01000000,
+ AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */
+ AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */
+ AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */
+ AR5K_INT_QCBRORN = 0x10000000, /* Non common */
+ AR5K_INT_QCBRURN = 0x20000000, /* Non common */
+ AR5K_INT_QTRIG = 0x40000000, /* Non common */
+ AR5K_INT_GLOBAL = 0x80000000,
+
+ AR5K_INT_COMMON = AR5K_INT_RXOK
+ | AR5K_INT_RXDESC
+ | AR5K_INT_RXERR
+ | AR5K_INT_RXNOFRM
+ | AR5K_INT_RXEOL
+ | AR5K_INT_RXORN
+ | AR5K_INT_TXOK
+ | AR5K_INT_TXDESC
+ | AR5K_INT_TXERR
+ | AR5K_INT_TXNOFRM
+ | AR5K_INT_TXEOL
+ | AR5K_INT_TXURN
+ | AR5K_INT_MIB
+ | AR5K_INT_SWI
+ | AR5K_INT_RXPHY
+ | AR5K_INT_RXKCM
+ | AR5K_INT_SWBA
+ | AR5K_INT_BRSSI
+ | AR5K_INT_BMISS
+ | AR5K_INT_GPIO
+ | AR5K_INT_GLOBAL,
+
+ AR5K_INT_NOCARD = 0xffffffff
+};
+
+/*
+ * Power management
+ */
+enum ath5k_power_mode {
+ AR5K_PM_UNDEFINED = 0,
+ AR5K_PM_AUTO,
+ AR5K_PM_AWAKE,
+ AR5K_PM_FULL_SLEEP,
+ AR5K_PM_NETWORK_SLEEP,
+};
+
+/* GPIO-controlled software LED */
+#define AR5K_SOFTLED_PIN 0
+#define AR5K_SOFTLED_ON 0
+#define AR5K_SOFTLED_OFF 1
+
+/*
+ * Chipset capabilities -see ath5k_hw_get_capability-
+ * get_capability function is not yet fully implemented
+ * in ath5k so most of these don't work yet...
+ * TODO: Implement these & merge with _TUNE_ stuff above
+ */
+enum ath5k_capability_type {
+ AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
+ AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
+ AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
+ AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
+ AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
+ AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
+ AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
+ AR5K_CAP_COMPRESSION = 8, /* Supports compression */
+ AR5K_CAP_BURST = 9, /* Supports packet bursting */
+ AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
+ AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
+ AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
+ AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
+ AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
+ AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
+ AR5K_CAP_XR = 16, /* Supports XR mode */
+ AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
+ AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
+ AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
+ AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
+};
+
+
+/* XXX: we *may* move cap_range stuff to struct wiphy */
+struct ath5k_capabilities {
+ /*
+ * Supported PHY modes
+ * (ie. CHANNEL_A, CHANNEL_B, ...)
+ */
+ u16 cap_mode;
+
+ /*
+ * Frequency range (without regulation restrictions)
+ */
+ struct {
+ u16 range_2ghz_min;
+ u16 range_2ghz_max;
+ u16 range_5ghz_min;
+ u16 range_5ghz_max;
+ } cap_range;
+
+ /*
+ * Values stored in the EEPROM (some of them...)
+ */
+ struct ath5k_eeprom_info cap_eeprom;
+
+ /*
+ * Queue information
+ */
+ struct {
+ u8 q_tx_num;
+ } cap_queues;
+};
+
+
+/***************************************\
+ HARDWARE ABSTRACTION LAYER STRUCTURE
+\***************************************/
+
+/*
+ * Misc defines
+ */
+
+#define AR5K_MAX_GPIO 10
+#define AR5K_MAX_RF_BANKS 8
+
+/* TODO: Clean up and merge with ath5k_softc */
+struct ath5k_hw {
+ struct ath5k_softc *ah_sc;
+ void *ah_iobase;
+
+ enum ath5k_int ah_imr;
+ int ah_ier;
+
+ struct net80211_channel *ah_current_channel;
+ int ah_turbo;
+ int ah_calibration;
+ int ah_running;
+ int ah_single_chip;
+ int ah_combined_mic;
+
+ u32 ah_mac_srev;
+ u16 ah_mac_version;
+ u16 ah_mac_revision;
+ u16 ah_phy_revision;
+ u16 ah_radio_5ghz_revision;
+ u16 ah_radio_2ghz_revision;
+
+ enum ath5k_version ah_version;
+ enum ath5k_radio ah_radio;
+ u32 ah_phy;
+
+ int ah_5ghz;
+ int ah_2ghz;
+
+#define ah_regdomain ah_capabilities.cap_regdomain.reg_current
+#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw
+#define ah_modes ah_capabilities.cap_mode
+#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
+
+ u32 ah_atim_window;
+ u32 ah_aifs;
+ u32 ah_cw_min;
+ u32 ah_cw_max;
+ int ah_software_retry;
+ u32 ah_limit_tx_retries;
+
+ u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+ int ah_ant_diversity;
+
+ u8 ah_sta_id[ETH_ALEN];
+
+ /* Current BSSID we are trying to assoc to / create.
+ * This is passed by mac80211 on config_interface() and cached here for
+ * use in resets */
+ u8 ah_bssid[ETH_ALEN];
+ u8 ah_bssid_mask[ETH_ALEN];
+
+ u32 ah_gpio[AR5K_MAX_GPIO];
+ int ah_gpio_npins;
+
+ struct ath5k_capabilities ah_capabilities;
+
+ struct ath5k_txq_info ah_txq;
+ u32 ah_txq_status;
+ u32 ah_txq_imr_txok;
+ u32 ah_txq_imr_txerr;
+ u32 ah_txq_imr_txurn;
+ u32 ah_txq_imr_txdesc;
+ u32 ah_txq_imr_txeol;
+ u32 ah_txq_imr_cbrorn;
+ u32 ah_txq_imr_cbrurn;
+ u32 ah_txq_imr_qtrig;
+ u32 ah_txq_imr_nofrm;
+ u32 ah_txq_isr;
+ u32 *ah_rf_banks;
+ size_t ah_rf_banks_size;
+ size_t ah_rf_regs_count;
+ struct ath5k_gain ah_gain;
+ u8 ah_offset[AR5K_MAX_RF_BANKS];
+
+
+ struct {
+ /* Temporary tables used for interpolation */
+ u8 tmpL[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_POWER_TABLE_SIZE];
+ u8 tmpR[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_POWER_TABLE_SIZE];
+ u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2];
+ u16 txp_rates_power_table[AR5K_MAX_RATES];
+ u8 txp_min_idx;
+ int txp_tpc;
+ /* Values in 0.25dB units */
+ s16 txp_min_pwr;
+ s16 txp_max_pwr;
+ s16 txp_offset;
+ s16 txp_ofdm;
+ /* Values in dB units */
+ s16 txp_cck_ofdm_pwr_delta;
+ s16 txp_cck_ofdm_gainf_delta;
+ } ah_txpower;
+
+ /* noise floor from last periodic calibration */
+ s32 ah_noise_floor;
+
+ /*
+ * Function pointers
+ */
+ int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ u32 size, unsigned int flags);
+ int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int);
+ int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_tx_status *);
+ int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_rx_status *);
+};
+
+/*
+ * Prototypes
+ */
+
+extern int ath5k_bitrate_to_hw_rix(int bitrate);
+
+/* Attach/Detach Functions */
+extern int ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version, struct ath5k_hw **ah);
+extern void ath5k_hw_detach(struct ath5k_hw *ah);
+
+/* LED functions */
+extern int ath5k_init_leds(struct ath5k_softc *sc);
+extern void ath5k_led_enable(struct ath5k_softc *sc);
+extern void ath5k_led_off(struct ath5k_softc *sc);
+extern void ath5k_unregister_leds(struct ath5k_softc *sc);
+
+/* Reset Functions */
+extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, int initial);
+extern int ath5k_hw_reset(struct ath5k_hw *ah, struct net80211_channel *channel, int change_channel);
+/* Power management functions */
+extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, int set_chip, u16 sleep_duration);
+
+/* DMA Related Functions */
+extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
+extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
+extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
+extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
+ u32 phys_addr);
+extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, int increase);
+/* Interrupt handling */
+extern int ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
+extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
+extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
+
+/* EEPROM access functions */
+extern int ath5k_eeprom_init(struct ath5k_hw *ah);
+extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
+extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+extern int ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
+
+/* Protocol Control Unit Functions */
+extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
+/* BSSID Functions */
+extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
+extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
+extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
+/* Receive start/stop functions */
+extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
+extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
+/* RX Filter functions */
+extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
+extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
+/* ACK bit rate */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, int high);
+/* ACK/CTS Timeouts */
+extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
+extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
+/* Key table (WEP) functions */
+extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
+
+/* Queue Control Unit, DFS Control Unit Functions */
+extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, const struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
+ enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info);
+extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah);
+extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah);
+extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah);
+extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+
+/* Hardware Descriptor Functions */
+extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
+
+/* GPIO Functions */
+extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
+extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
+extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+
+/* Misc functions */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
+extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
+extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
+
+/* Initial register settings functions */
+extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, int change_channel);
+
+/* Initialize RF */
+extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ unsigned int mode);
+extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
+extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
+extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
+/* PHY/RF channel functions */
+extern int ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
+extern int ath5k_hw_channel(struct ath5k_hw *ah, struct net80211_channel *channel);
+/* PHY calibration */
+extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct net80211_channel *channel);
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+/* Misc PHY functions */
+extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
+extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
+extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+/* TX power setup */
+extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct net80211_channel *channel, u8 ee_mode, u8 txpower);
+extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower);
+
+/*
+ * Functions used internaly
+ */
+
+/*
+ * Translate usec to hw clock units
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, int turbo)
+{
+ return turbo ? (usec * 80) : (usec * 40);
+}
+
+/*
+ * Translate hw clock units to usec
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, int turbo)
+{
+ return turbo ? (clock / 80) : (clock / 40);
+}
+
+/*
+ * Read from a register
+ */
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+ return readl(ah->ah_iobase + reg);
+}
+
+/*
+ * Write to a register
+ */
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+ writel(val, ah->ah_iobase + reg);
+}
+
+#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
+/*
+ * Check if a register write has been completed
+ */
+static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
+ u32 val, int is_set)
+{
+ int i;
+ u32 data;
+
+ for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+ data = ath5k_hw_reg_read(ah, reg);
+ if (is_set && (data & flag))
+ break;
+ else if ((data & flag) == val)
+ break;
+ udelay(15);
+ }
+
+ return (i <= 0) ? -EAGAIN : 0;
+}
+
+/*
+ * Convert channel frequency to channel number
+ */
+static inline int ath5k_freq_to_channel(int freq)
+{
+ if (freq == 2484)
+ return 14;
+
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+
+ return freq/5 - 1000;
+}
+
+#endif
+
+static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
+{
+ u32 retval = 0, bit, i;
+
+ for (i = 0; i < bits; i++) {
+ bit = (val >> i) & 1;
+ retval = (retval << 1) | bit;
+ }
+
+ return retval;
+}
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_attach.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_attach.c
new file mode 100644
index 0000000..36dc243
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_attach.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*************************************\
+* Attach/Detach Functions and helpers *
+\*************************************/
+
+#include <gpxe/pci.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/**
+ * ath5k_hw_post - Power On Self Test helper function
+ *
+ * @ah: The &struct ath5k_hw
+ */
+static int ath5k_hw_post(struct ath5k_hw *ah)
+{
+
+ static const u32 static_pattern[4] = {
+ 0x55555555, 0xaaaaaaaa,
+ 0x66666666, 0x99999999
+ };
+ static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) };
+ int i, c;
+ u16 cur_reg;
+ u32 var_pattern;
+ u32 init_val;
+ u32 cur_val;
+
+ for (c = 0; c < 2; c++) {
+
+ cur_reg = regs[c];
+
+ /* Save previous value */
+ init_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ for (i = 0; i < 256; i++) {
+ var_pattern = i << 16 | i;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ if (cur_val != var_pattern) {
+ DBG("ath5k: POST failed!\n");
+ return -EAGAIN;
+ }
+
+ /* Found on ndiswrapper dumps */
+ var_pattern = 0x0039080f;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ }
+
+ for (i = 0; i < 4; i++) {
+ var_pattern = static_pattern[i];
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+ if (cur_val != var_pattern) {
+ DBG("ath5k: POST failed!\n");
+ return -EAGAIN;
+ }
+
+ /* Found on ndiswrapper dumps */
+ var_pattern = 0x003b080f;
+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+ }
+
+ /* Restore previous value */
+ ath5k_hw_reg_write(ah, init_val, cur_reg);
+
+ }
+
+ return 0;
+
+}
+
+/**
+ * ath5k_hw_attach - Check if hw is supported and init the needed structs
+ *
+ * @sc: The &struct ath5k_softc we got from the driver's attach function
+ * @mac_version: The mac version id (check out ath5k.h) based on pci id
+ * @hw: Returned newly allocated hardware structure, on success
+ *
+ * Check if the device is supported, perform a POST and initialize the needed
+ * structs. Returns -ENOMEM if we don't have memory for the needed structs,
+ * -ENODEV if the device is not supported or prints an error msg if something
+ * else went wrong.
+ */
+int ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version,
+ struct ath5k_hw **hw)
+{
+ struct ath5k_hw *ah;
+ struct pci_device *pdev = sc->pdev;
+ int ret;
+ u32 srev;
+
+ ah = zalloc(sizeof(struct ath5k_hw));
+ if (ah == NULL) {
+ ret = -ENOMEM;
+ DBG("ath5k: out of memory\n");
+ goto err;
+ }
+
+ ah->ah_sc = sc;
+ ah->ah_iobase = sc->iobase;
+
+ /*
+ * HW information
+ */
+ ah->ah_turbo = 0;
+ ah->ah_txpower.txp_tpc = 0;
+ ah->ah_imr = 0;
+ ah->ah_atim_window = 0;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
+ ah->ah_software_retry = 0;
+ ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
+
+ /*
+ * Set the mac version based on the pci id
+ */
+ ah->ah_version = mac_version;
+
+ /*Fill the ath5k_hw struct with the needed functions*/
+ ret = ath5k_hw_init_desc_functions(ah);
+ if (ret)
+ goto err_free;
+
+ /* Bring device out of sleep and reset it's units */
+ ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, 1);
+ if (ret)
+ goto err_free;
+
+ /* Get MAC, PHY and RADIO revisions */
+ srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+ ah->ah_mac_srev = srev;
+ ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+ ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID);
+ ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, CHANNEL_5GHZ);
+ ah->ah_phy = AR5K_PHY(0);
+
+ /* Try to identify radio chip based on it's srev */
+ switch (ah->ah_radio_5ghz_revision & 0xf0) {
+ case AR5K_SREV_RAD_5111:
+ ah->ah_radio = AR5K_RF5111;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ break;
+ case AR5K_SREV_RAD_5112:
+ case AR5K_SREV_RAD_2112:
+ ah->ah_radio = AR5K_RF5112;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ break;
+ case AR5K_SREV_RAD_2413:
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_5413:
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_2316:
+ ah->ah_radio = AR5K_RF2316;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_2317:
+ ah->ah_radio = AR5K_RF2317;
+ ah->ah_single_chip = 1;
+ break;
+ case AR5K_SREV_RAD_5424:
+ if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
+ ah->ah_mac_version == AR5K_SREV_AR2417) {
+ ah->ah_radio = AR5K_RF2425;
+ } else {
+ ah->ah_radio = AR5K_RF5413;
+ }
+ ah->ah_single_chip = 1;
+ break;
+ default:
+ /* Identify radio based on mac/phy srev */
+ if (ah->ah_version == AR5K_AR5210) {
+ ah->ah_radio = AR5K_RF5110;
+ ah->ah_single_chip = 0;
+ } else if (ah->ah_version == AR5K_AR5211) {
+ ah->ah_radio = AR5K_RF5111;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
+ ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
+ ah->ah_radio = AR5K_RF2425;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
+ } else if (srev == AR5K_SREV_AR5213A &&
+ ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
+ ah->ah_radio = AR5K_RF5112;
+ ah->ah_single_chip = 0;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
+ ah->ah_radio = AR5K_RF2316;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+ ah->ah_radio = AR5K_RF5413;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
+ } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
+ ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_single_chip = 1;
+ ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
+ } else {
+ DBG("ath5k: Couldn't identify radio revision.\n");
+ ret = -ENOTSUP;
+ goto err_free;
+ }
+ }
+
+ /* Return on unsuported chips (unsupported eeprom etc) */
+ if ((srev >= AR5K_SREV_AR5416) &&
+ (srev < AR5K_SREV_AR2425)) {
+ DBG("ath5k: Device not yet supported.\n");
+ ret = -ENOTSUP;
+ goto err_free;
+ }
+
+ /*
+ * Write PCI-E power save settings
+ */
+ if ((ah->ah_version == AR5K_AR5212) &&
+ pci_find_capability(pdev, PCI_CAP_ID_EXP)) {
+ ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
+ /* Shut off RX when elecidle is asserted */
+ ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
+ /* TODO: EEPROM work */
+ ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
+ /* Shut off PLL and CLKREQ active in L1 */
+ ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
+ /* Preserce other settings */
+ ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
+ ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
+ /* Reset SERDES to load new settings */
+ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
+ mdelay(1);
+ }
+
+ /*
+ * POST
+ */
+ ret = ath5k_hw_post(ah);
+ if (ret)
+ goto err_free;
+
+ /* Enable pci core retry fix on Hainan (5213A) and later chips */
+ if (srev >= AR5K_SREV_AR5213A)
+ ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
+
+ /*
+ * Get card capabilities, calibration values etc
+ * TODO: EEPROM work
+ */
+ ret = ath5k_eeprom_init(ah);
+ if (ret) {
+ DBG("ath5k: unable to init EEPROM\n");
+ goto err_free;
+ }
+
+ /* Get misc capabilities */
+ ret = ath5k_hw_set_capabilities(ah);
+ if (ret) {
+ DBG("ath5k: unable to get device capabilities: 0x%04x\n",
+ sc->pdev->device);
+ goto err_free;
+ }
+
+ if (srev >= AR5K_SREV_AR2414) {
+ ah->ah_combined_mic = 1;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
+ AR5K_MISC_MODE_COMBINED_MIC);
+ }
+
+ /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
+ memset(ah->ah_bssid, 0xff, ETH_ALEN);
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_rfgain_opt_init(ah);
+
+ *hw = ah;
+ return 0;
+err_free:
+ free(ah);
+err:
+ return ret;
+}
+
+/**
+ * ath5k_hw_detach - Free the ath5k_hw struct
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_detach(struct ath5k_hw *ah)
+{
+ free(ah->ah_rf_banks);
+ ath5k_eeprom_detach(ah);
+ free(ah);
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_caps.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_caps.c
new file mode 100644
index 0000000..1d60d74
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_caps.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/**************\
+* Capabilities *
+\**************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Fill the capabilities struct
+ * TODO: Merge this with EEPROM code when we are done with it
+ */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
+{
+ u16 ee_header;
+
+ /* Capabilities stored in the EEPROM */
+ ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /*
+ * Set radio capabilities
+ * (The AR5110 only supports the middle 5GHz band)
+ */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
+ ah->ah_capabilities.cap_range.range_2ghz_min = 0;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+
+ /* Set supported modes */
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A;
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A_TURBO;
+ } else {
+ /*
+ * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+ * XXX and from 2312 to 2732GHz. There are problems with the
+ * XXX current ieee80211 implementation because the IEEE
+ * XXX channel mapping does not support negative channel
+ * XXX numbers (2312MHz is channel -19). Of course, this
+ * XXX doesn't matter because these channels are out of range
+ * XXX but some regulation domains like MKK (Japan) will
+ * XXX support frequencies somewhere around 4.8GHz.
+ */
+
+ /*
+ * Set radio capabilities
+ */
+
+ if (AR5K_EEPROM_HDR_11A(ee_header)) {
+ /* 4920 */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+
+ /* Set supported modes */
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A;
+ ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A_TURBO;
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_capabilities.cap_mode |=
+ AR5K_MODE_BIT_11G_TURBO;
+ }
+
+ /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
+ * connected */
+ if (AR5K_EEPROM_HDR_11B(ee_header) ||
+ (AR5K_EEPROM_HDR_11G(ee_header) &&
+ ah->ah_version != AR5K_AR5211)) {
+ /* 2312 */
+ ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+
+ if (AR5K_EEPROM_HDR_11B(ee_header))
+ ah->ah_capabilities.cap_mode |=
+ AR5K_MODE_BIT_11B;
+
+ if (AR5K_EEPROM_HDR_11G(ee_header) &&
+ ah->ah_version != AR5K_AR5211)
+ ah->ah_capabilities.cap_mode |=
+ AR5K_MODE_BIT_11G;
+ }
+ }
+
+ /* GPIO */
+ ah->ah_gpio_npins = AR5K_NUM_GPIO;
+
+ /* Set number of supported TX queues */
+ ah->ah_capabilities.cap_queues.q_tx_num = 1;
+
+ return 0;
+}
+
+/* Main function used by the driver part to check caps */
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
+ enum ath5k_capability_type cap_type,
+ u32 capability __unused, u32 *result)
+{
+ switch (cap_type) {
+ case AR5K_CAP_NUM_TXQUEUES:
+ if (result) {
+ *result = 1;
+ goto yes;
+ }
+ case AR5K_CAP_VEOL:
+ goto yes;
+ case AR5K_CAP_COMPRESSION:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_BURST:
+ goto yes;
+ case AR5K_CAP_TPC:
+ goto yes;
+ case AR5K_CAP_BSSIDMASK:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_XR:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ default:
+ goto no;
+ }
+
+no:
+ return -EINVAL;
+yes:
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_desc.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_desc.c
new file mode 100644
index 0000000..76d0c1e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_desc.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/******************************\
+ Hardware Descriptor Functions
+\******************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * TX Descriptors
+ */
+
+#define FCS_LEN 4
+
+/*
+ * Initialize the 2-word tx control descriptor on 5210/5211
+ */
+static int
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
+ unsigned int tx_power __unused, unsigned int tx_rate0, unsigned int tx_tries0,
+ unsigned int key_index __unused, unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate __unused, unsigned int rtscts_duration)
+{
+ u32 frame_type;
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (tx_tries0 == 0) {
+ DBG("ath5k: zero retries\n");
+ return -EINVAL;
+ }
+ if (tx_rate0 == 0) {
+ DBG("ath5k: zero rate\n");
+ return -EINVAL;
+ }
+
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+
+ frame_len = pkt_len + FCS_LEN;
+
+ if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+ if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+
+ /*
+ * Verify and set header length
+ * XXX: I only found that on 5210 code, does it work on 5211 ?
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+ return -EINVAL;
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+ }
+
+ /*Diferences between 5210-5211*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (type) {
+ case AR5K_PKT_TYPE_BEACON:
+ case AR5K_PKT_TYPE_PROBE_RESP:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
+ case AR5K_PKT_TYPE_PIFS:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
+ default:
+ frame_type = type /*<< 2 ?*/;
+ }
+
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+
+ } else {
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+ AR5K_REG_SM(antenna_mode,
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_ctl->tx_control_1 |=
+ AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+ }
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) { \
+ tx_ctl->tx_control_##_c |= \
+ AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
+ }
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * RTS/CTS Duration [5210 ?]
+ */
+ if ((ah->ah_version == AR5K_AR5210) &&
+ (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+ tx_ctl->tx_control_1 |= rtscts_duration &
+ AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+
+ return 0;
+}
+
+/*
+ * Initialize the 4-word tx control descriptor on 5212
+ */
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len __unused,
+ enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
+ unsigned int tx_tries0, unsigned int key_index __unused,
+ unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate,
+ unsigned int rtscts_duration)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (tx_tries0 == 0) {
+ DBG("ath5k: zero retries\n");
+ return -EINVAL;
+ }
+ if (tx_rate0 == 0) {
+ DBG("ath5k: zero rate\n");
+ return -EINVAL;
+ }
+
+ tx_power += ah->ah_txpower.txp_offset;
+ if (tx_power > AR5K_TUNE_MAX_TXPOWER)
+ tx_power = AR5K_TUNE_MAX_TXPOWER;
+
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+
+ frame_len = pkt_len + FCS_LEN;
+
+ if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+ if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+
+ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+ AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
+ AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+ tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+ tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) { \
+ tx_ctl->tx_control_##_c |= \
+ AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
+ }
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(0, CTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * RTS/CTS
+ */
+ if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
+ if ((flags & AR5K_TXDESC_RTSENA) &&
+ (flags & AR5K_TXDESC_CTSENA))
+ return -EINVAL;
+ tx_ctl->tx_control_2 |= rtscts_duration &
+ AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+ tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess the tx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+ tx_status = &desc->ud.ds_tx5210.tx_stat;
+
+ /* No frame has been send or error */
+ if ((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ /*TODO: ts->ts_virtcol + test*/
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ ts->ts_antenna = 1;
+ ts->ts_status = 0;
+ ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
+ AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ ts->ts_retry[0] = ts->ts_longretry;
+ ts->ts_final_idx = 0;
+
+ if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess a tx status descriptor on 5212
+ */
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+ tx_status = &desc->ud.ds_tx5212.tx_stat;
+
+ /* No frame has been send or error */
+ if (!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ ts->ts_antenna = (tx_status->tx_status_1 &
+ AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+ ts->ts_status = 0;
+
+ ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
+
+ ts->ts_retry[0] = ts->ts_longretry;
+ ts->ts_rate[0] = tx_ctl->tx_control_3 &
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+ /* TX error */
+ if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * RX Descriptors
+ */
+
+/*
+ * Initialize an rx control descriptor
+ */
+static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc,
+ u32 size, unsigned int flags)
+{
+ struct ath5k_hw_rx_ctl *rx_ctl;
+
+ rx_ctl = &desc->ud.ds_rx.rx_ctl;
+
+ /*
+ * Clear the descriptor
+ * If we don't clean the status descriptor,
+ * while scanning we get too many results,
+ * most of them virtual, after some secs
+ * of scanning system hangs. M.F.
+ */
+ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
+
+ /* Setup descriptor */
+ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+ if (rx_ctl->rx_control_1 != size)
+ return -EINVAL;
+
+ if (flags & AR5K_RXDESC_INTREQ)
+ rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+ struct ath5k_hw_rx_status *rx_status;
+
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* No frame received / not ready */
+ if (!(rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+ rs->rs_more = !!(rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_MORE);
+ /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
+ rs->rs_phyerr = 0;
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if (!(rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
+ rs->rs_status |= AR5K_RXERR_FIFO;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5212
+ */
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah __unused,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+ struct ath5k_hw_rx_status *rx_status;
+ struct ath5k_hw_rx_error *rx_err;
+
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* Overlay on error */
+ rx_err = &desc->ud.ds_rx.u.rx_err;
+
+ /* No frame received / not ready */
+ if (!(rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+ rs->rs_more = !!(rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_MORE);
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
+ rs->rs_phyerr = 0;
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if (!(rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
+ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
+
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+ rs->rs_status |= AR5K_RXERR_MIC;
+ }
+
+ return 0;
+}
+
+/*
+ * Init function pointers inside ath5k_hw struct
+ */
+int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
+{
+
+ if (ah->ah_version != AR5K_AR5210 &&
+ ah->ah_version != AR5K_AR5211 &&
+ ah->ah_version != AR5K_AR5212)
+ return -ENOTSUP;
+
+ if (ah->ah_version == AR5K_AR5212) {
+ ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+ ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
+ } else {
+ ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+ ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
+ }
+
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
+ else if (ah->ah_version <= AR5K_AR5211)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
+
+ return 0;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_dma.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_dma.c
new file mode 100644
index 0000000..23c4cf9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_dma.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*************************************\
+* DMA and interrupt masking functions *
+\*************************************/
+
+/*
+ * dma.c - DMA and interrupt masking functions
+ *
+ * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
+ * handle queue setup for 5210 chipset (rest are handled on qcu.c).
+ * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * status registers (ISR).
+ *
+ * TODO: Handle SISR on 5211+ and introduce a function to return the queue
+ * number that resulted the interrupt.
+ */
+
+#include <unistd.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*********\
+* Receive *
+\*********/
+
+/**
+ * ath5k_hw_start_rx_dma - Start DMA receive
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
+{
+ ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+}
+
+/**
+ * ath5k_hw_stop_rx_dma - Stop DMA receive
+ *
+ * @ah: The &struct ath5k_hw
+ */
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+{
+ unsigned int i;
+
+ ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
+
+ /*
+ * It may take some time to disable the DMA receive unit
+ */
+ for (i = 1000; i > 0 &&
+ (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
+ i--)
+ udelay(10);
+
+ return i ? 0 : -EBUSY;
+}
+
+/**
+ * ath5k_hw_get_rxdp - Get RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * XXX: Is RXDP read and clear ?
+ */
+u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
+{
+ return ath5k_hw_reg_read(ah, AR5K_RXDP);
+}
+
+/**
+ * ath5k_hw_set_rxdp - Set RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ * @phys_addr: RX descriptor address
+ *
+ * XXX: Should we check if rx is enabled before setting rxdp ?
+ */
+void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
+{
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+}
+
+
+/**********\
+* Transmit *
+\**********/
+
+/**
+ * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Start DMA transmit for a specific queue and since 5210 doesn't have
+ * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
+ * queue for normal data and one queue for beacons). For queue setup
+ * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
+ * of range or if queue is already disabled.
+ *
+ * NOTE: Must be called after setting up tx control descriptor for that
+ * queue (see below).
+ */
+int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ u32 tx_queue;
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /* Assume always a data queue */
+ tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
+
+ /* Start queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+ } else {
+ /* Return if queue is disabled */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
+ return -EIO;
+
+ /* Start queue */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
+ }
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Stop DMA transmit on a specific hw queue and drain queue so we don't
+ * have any pending frames. Returns -EBUSY if we still have pending frames,
+ * -EINVAL if queue number is out of range.
+ *
+ */
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ unsigned int i = 40;
+ u32 tx_queue, pending;
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /* Assume a data queue */
+ tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
+
+ /* Stop queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ ath5k_hw_reg_read(ah, AR5K_CR);
+ } else {
+ /*
+ * Schedule TX disable and wait until queue is empty
+ */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
+
+ /*Check for pending frames*/
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ /* For 2413+ order PCU to drop packets using
+ * QUIET mechanism */
+ if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && pending) {
+ /* Set periodicity and duration */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
+ AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
+ AR5K_QUIET_CTL2);
+
+ /* Enable quiet period for current TSF */
+ ath5k_hw_reg_write(ah,
+ AR5K_QUIET_CTL1_QT_EN |
+ AR5K_REG_SM(ath5k_hw_reg_read(ah,
+ AR5K_TSF_L32_5211) >> 10,
+ AR5K_QUIET_CTL1_NEXT_QT_TSF),
+ AR5K_QUIET_CTL1);
+
+ /* Force channel idle high */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+
+ /* Wait a while and disable mechanism */
+ udelay(200);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
+ AR5K_QUIET_CTL1_QT_EN);
+
+ /* Re-check for pending frames */
+ i = 40;
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+ }
+
+ /* Clear register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
+ if (pending)
+ return -EBUSY;
+ }
+
+ /* TODO: Check for success on 5210 else return error */
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Get TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and use tx queue type since we only have 2 queues.
+ * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just read the corresponding TXDP register.
+ *
+ * XXX: Is TXDP read and clear ?
+ */
+u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
+{
+ u16 tx_reg;
+
+ /*
+ * Get the transmit queue descriptor pointer from the selected queue
+ */
+ /*5210 doesn't have QCU*/
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Assume a data queue */
+ tx_reg = AR5K_NOQCU_TXDP0;
+ } else {
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ return ath5k_hw_reg_read(ah, tx_reg);
+}
+
+/**
+ * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Set TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and we use tx queue type since we only have 2 queues
+ * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just set the corresponding TXDP register.
+ * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
+ * active.
+ */
+int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
+{
+ u16 tx_reg;
+
+ /*
+ * Set the transmit queue descriptor pointer register by type
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Assume a data queue */
+ tx_reg = AR5K_NOQCU_TXDP0;
+ } else {
+ /*
+ * Set the transmit queue descriptor pointer for
+ * the selected queue on QCU for 5211+
+ * (this won't work if the queue is still active)
+ */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+ return -EIO;
+
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ /* Set descriptor pointer */
+ ath5k_hw_reg_write(ah, phys_addr, tx_reg);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_update_tx_triglevel - Update tx trigger level
+ *
+ * @ah: The &struct ath5k_hw
+ * @increase: Flag to force increase of trigger level
+ *
+ * This function increases/decreases the tx trigger level for the tx fifo
+ * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
+ * the buffer and transmits it's data. Lowering this results sending small
+ * frames more quickly but can lead to tx underruns, raising it a lot can
+ * result other problems (i think bmiss is related). Right now we start with
+ * the lowest possible (64Bytes) and if we get tx underrun we increase it using
+ * the increase flag. Returns -EIO if we have have reached maximum/minimum.
+ *
+ * XXX: Link this with tx DMA size ?
+ * XXX: Use it to save interrupts ?
+ * TODO: Needs testing, i think it's related to bmiss...
+ */
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, int increase)
+{
+ u32 trigger_level, imr;
+ int ret = -EIO;
+
+ /*
+ * Disable interrupts by setting the mask
+ */
+ imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
+
+ trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+ AR5K_TXCFG_TXFULL);
+
+ if (!increase) {
+ if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+ goto done;
+ } else
+ trigger_level +=
+ ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
+
+ /*
+ * Update trigger level on success
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_TXFULL, trigger_level);
+
+ ret = 0;
+
+done:
+ /*
+ * Restore interrupt mask
+ */
+ ath5k_hw_set_imr(ah, imr);
+
+ return ret;
+}
+
+/*******************\
+* Interrupt masking *
+\*******************/
+
+/**
+ * ath5k_hw_is_intr_pending - Check if we have pending interrupts
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Check if we have pending interrupts to process. Returns 1 if we
+ * have pending interrupts and 0 if we haven't.
+ */
+int ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
+{
+ return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
+}
+
+/**
+ * ath5k_hw_get_isr - Get interrupt status
+ *
+ * @ah: The @struct ath5k_hw
+ * @interrupt_mask: Driver's interrupt mask used to filter out
+ * interrupts in sw.
+ *
+ * This function is used inside our interrupt handler to determine the reason
+ * for the interrupt by reading Primary Interrupt Status Register. Returns an
+ * abstract interrupt status mask which is mostly ISR with some uncommon bits
+ * being mapped on some standard non hw-specific positions
+ * (check out &ath5k_int).
+ *
+ * NOTE: We use read-and-clear register, so after this function is called ISR
+ * is zeroed.
+ */
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
+{
+ u32 data;
+
+ /*
+ * Read interrupt status from the Interrupt Status register
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_ISR);
+ if (data == AR5K_INT_NOCARD) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
+ } else {
+ /*
+ * Read interrupt status from Interrupt
+ * Status Register shadow copy (Read And Clear)
+ *
+ * Note: PISR/SISR Not available on 5210
+ */
+ data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+ if (data == AR5K_INT_NOCARD) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Get abstract interrupt mask (driver-compatible)
+ */
+ *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
+
+ /*HIU = Host Interface Unit (PCI etc)*/
+ if (data & (AR5K_ISR_HIUERR))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*Beacon Not Ready*/
+ if (data & (AR5K_ISR_BNR))
+ *interrupt_mask |= AR5K_INT_BNR;
+
+ if (sisr2 & (AR5K_SISR2_SSERR | AR5K_SISR2_DPERR |
+ AR5K_SISR2_MCABT))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ if (data & AR5K_ISR_TIM)
+ *interrupt_mask |= AR5K_INT_TIM;
+
+ if (data & AR5K_ISR_BCNMISC) {
+ if (sisr2 & AR5K_SISR2_TIM)
+ *interrupt_mask |= AR5K_INT_TIM;
+ if (sisr2 & AR5K_SISR2_DTIM)
+ *interrupt_mask |= AR5K_INT_DTIM;
+ if (sisr2 & AR5K_SISR2_DTIM_SYNC)
+ *interrupt_mask |= AR5K_INT_DTIM_SYNC;
+ if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
+ *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
+ if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
+ *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
+ }
+
+ if (data & AR5K_ISR_RXDOPPLER)
+ *interrupt_mask |= AR5K_INT_RX_DOPPLER;
+ if (data & AR5K_ISR_QCBRORN) {
+ *interrupt_mask |= AR5K_INT_QCBRORN;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+ AR5K_SISR3_QCBRORN);
+ }
+ if (data & AR5K_ISR_QCBRURN) {
+ *interrupt_mask |= AR5K_INT_QCBRURN;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+ AR5K_SISR3_QCBRURN);
+ }
+ if (data & AR5K_ISR_QTRIG) {
+ *interrupt_mask |= AR5K_INT_QTRIG;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
+ AR5K_SISR4_QTRIG);
+ }
+
+ if (data & AR5K_ISR_TXOK)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+ AR5K_SISR0_QCU_TXOK);
+
+ if (data & AR5K_ISR_TXDESC)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+ AR5K_SISR0_QCU_TXDESC);
+
+ if (data & AR5K_ISR_TXERR)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+ AR5K_SISR1_QCU_TXERR);
+
+ if (data & AR5K_ISR_TXEOL)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+ AR5K_SISR1_QCU_TXEOL);
+
+ if (data & AR5K_ISR_TXURN)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
+ AR5K_SISR2_QCU_TXURN);
+ } else {
+ if (data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT |
+ AR5K_ISR_HIUERR | AR5K_ISR_DPERR))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*
+ * XXX: BMISS interrupts may occur after association.
+ * I found this on 5210 code but it needs testing. If this is
+ * true we should disable them before assoc and re-enable them
+ * after a successful assoc + some jiffies.
+ interrupt_mask &= ~AR5K_INT_BMISS;
+ */
+ }
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_imr - Set interrupt mask
+ *
+ * @ah: The &struct ath5k_hw
+ * @new_mask: The new interrupt mask to be set
+ *
+ * Set the interrupt mask in hw to save interrupts. We do that by mapping
+ * ath5k_int bits to hw-specific bits to remove abstraction and writing
+ * Interrupt Mask Register.
+ */
+enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
+{
+ enum ath5k_int old_mask, int_mask;
+
+ old_mask = ah->ah_imr;
+
+ /*
+ * Disable card interrupts to prevent any race conditions
+ * (they will be re-enabled afterwards if AR5K_INT GLOBAL
+ * is set again on the new mask).
+ */
+ if (old_mask & AR5K_INT_GLOBAL) {
+ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+ }
+
+ /*
+ * Add additional, chipset-dependent interrupt mask flags
+ * and write them to the IMR (interrupt mask register).
+ */
+ int_mask = new_mask & AR5K_INT_COMMON;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /* Preserve per queue TXURN interrupt mask */
+ u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
+ & AR5K_SIMR2_QCU_TXURN;
+
+ if (new_mask & AR5K_INT_FATAL) {
+ int_mask |= AR5K_IMR_HIUERR;
+ simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
+ | AR5K_SIMR2_DPERR);
+ }
+
+ /*Beacon Not Ready*/
+ if (new_mask & AR5K_INT_BNR)
+ int_mask |= AR5K_INT_BNR;
+
+ if (new_mask & AR5K_INT_TIM)
+ int_mask |= AR5K_IMR_TIM;
+
+ if (new_mask & AR5K_INT_TIM)
+ simr2 |= AR5K_SISR2_TIM;
+ if (new_mask & AR5K_INT_DTIM)
+ simr2 |= AR5K_SISR2_DTIM;
+ if (new_mask & AR5K_INT_DTIM_SYNC)
+ simr2 |= AR5K_SISR2_DTIM_SYNC;
+ if (new_mask & AR5K_INT_BCN_TIMEOUT)
+ simr2 |= AR5K_SISR2_BCN_TIMEOUT;
+ if (new_mask & AR5K_INT_CAB_TIMEOUT)
+ simr2 |= AR5K_SISR2_CAB_TIMEOUT;
+
+ if (new_mask & AR5K_INT_RX_DOPPLER)
+ int_mask |= AR5K_IMR_RXDOPPLER;
+
+ /* Note: Per queue interrupt masks
+ * are set via reset_tx_queue (qcu.c) */
+ ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+ ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
+
+ } else {
+ if (new_mask & AR5K_INT_FATAL)
+ int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
+ | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
+
+ ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
+ }
+
+ /* If RXNOFRM interrupt is masked disable it
+ * by setting AR5K_RXNOFRM to zero */
+ if (!(new_mask & AR5K_INT_RXNOFRM))
+ ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
+
+ /* Store new interrupt mask */
+ ah->ah_imr = new_mask;
+
+ /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
+ if (new_mask & AR5K_INT_GLOBAL) {
+ ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+ }
+
+ return old_mask;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_eeprom.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_eeprom.c
new file mode 100644
index 0000000..592714d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_eeprom.c
@@ -0,0 +1,1749 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*************************************\
+* EEPROM access functions and helpers *
+\*************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Read from eeprom
+ */
+static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+{
+ u32 status, timeout;
+
+ /*
+ * Initialize EEPROM access
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_READ);
+ }
+
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_RDDONE) {
+ if (status & AR5K_EEPROM_STAT_RDERR)
+ return -EIO;
+ *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+ 0xffff);
+ return 0;
+ }
+ udelay(15);
+ }
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Translate binary channel representation in EEPROM to frequency
+ */
+static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
+ unsigned int mode)
+{
+ u16 val;
+
+ if (bin == AR5K_EEPROM_CHANNEL_DIS)
+ return bin;
+
+ if (mode == AR5K_EEPROM_MODE_11A) {
+ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = (5 * bin) + 4800;
+ else
+ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
+ (bin * 10) + 5100;
+ } else {
+ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = bin + 2300;
+ else
+ val = bin + 2400;
+ }
+
+ return val;
+}
+
+/*
+ * Initialize eeprom & capabilities structs
+ */
+static int
+ath5k_eeprom_init_header(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int ret;
+ u16 val;
+
+ /*
+ * Read values from EEPROM and store them in the capability structure
+ */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+ /* Return if we have an old EEPROM */
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+ return 0;
+
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
+ ee_ant_gain);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+
+ /* XXX: Don't know which versions include these two */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
+ }
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Read antenna infos from eeprom
+ */
+static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret, i = 0;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
+ ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
+ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ /* Get antenna modes */
+ ah->ah_antenna[mode][0] =
+ (ee->ee_ant_control[mode][0] << 4);
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
+ (ee->ee_ant_control[mode][3] << 12) |
+ (ee->ee_ant_control[mode][4] << 18) |
+ (ee->ee_ant_control[mode][5] << 24);
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
+ (ee->ee_ant_control[mode][8] << 12) |
+ (ee->ee_ant_control[mode][9] << 18) |
+ (ee->ee_ant_control[mode][10] << 24);
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Read supported modes and some mode-specific calibration data
+ * from eeprom
+ */
+static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret;
+
+ ee->ee_n_piers[mode] = 0;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
+ ee->ee_db[mode][0] = val & 0x7;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ case AR5K_EEPROM_MODE_11B:
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+ break;
+ }
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
+ ee->ee_thr_62[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
+ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
+
+ if ((val & 0xff) & 0x80)
+ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
+ else
+ ee->ee_noise_floor_thr[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_noise_floor_thr[mode] =
+ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
+ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
+ ee->ee_xpd[mode] = val & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
+
+ if (mode == AR5K_EEPROM_MODE_11A)
+ ee->ee_xr_power[mode] = val & 0x3f;
+ else {
+ ee->ee_ob[mode][0] = val & 0x7;
+ ee->ee_db[mode][0] = (val >> 3) & 0x7;
+ }
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
+ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
+ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
+ } else {
+ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
+
+ if (mode == AR5K_EEPROM_MODE_11G) {
+ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+ }
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
+ mode == AR5K_EEPROM_MODE_11A) {
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
+ goto done;
+
+ /* Note: >= v5 have bg freq piers on another location
+ * so these freq piers are ignored for >= v5 (should be 0xff
+ * anyway) */
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
+ break;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ AR5K_EEPROM_READ(o++, val);
+
+ ee->ee_pwr_cal_b[0].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ ee->ee_pwr_cal_b[1].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+ if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pwr_cal_b[2].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ AR5K_EEPROM_READ(o++, val);
+
+ ee->ee_pwr_cal_g[0].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ ee->ee_pwr_cal_g[1].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+ if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pwr_cal_g[2].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ break;
+ }
+
+done:
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Read turbo mode information on newer EEPROM versions
+ */
+static int
+ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
+ u32 *offset, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret;
+
+ if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
+ return 0;
+
+ switch (mode){
+ case AR5K_EEPROM_MODE_11A:
+ ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
+
+ ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
+ ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
+
+ ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
+ ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
+
+ if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+ ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
+
+ ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
+ ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
+
+ ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
+ ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
+ break;
+ }
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/* Read mode-specific data (except power calibration data) */
+static int
+ath5k_eeprom_init_modes(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 mode_offset[3];
+ unsigned int mode;
+ u32 offset;
+ int ret;
+
+ /*
+ * Get values for all modes
+ */
+ mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+ mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+ mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+
+ ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
+ offset = mode_offset[mode];
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+ }
+
+ /* override for older eeprom versions for better performance */
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
+ }
+
+ return 0;
+}
+
+/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
+ * frequency mask) */
+static inline int
+ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
+ struct ath5k_chan_pcal_info *pc, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int o = *offset;
+ int i = 0;
+ u8 freq1, freq2;
+ int ret;
+ u16 val;
+
+ ee->ee_n_piers[mode] = 0;
+ while(i < max) {
+ AR5K_EEPROM_READ(o++, val);
+
+ freq1 = val & 0xff;
+ if (!freq1)
+ break;
+
+ pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+ freq1, mode);
+ ee->ee_n_piers[mode]++;
+
+ freq2 = (val >> 8) & 0xff;
+ if (!freq2)
+ break;
+
+ pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+ freq2, mode);
+ ee->ee_n_piers[mode]++;
+ }
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/* Read frequency piers for 802.11a */
+static int
+ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
+ int i, ret;
+ u16 val;
+ u8 mask;
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ ath5k_eeprom_read_freq_list(ah, &offset,
+ AR5K_EEPROM_N_5GHZ_CHAN, pcal,
+ AR5K_EEPROM_MODE_11A);
+ } else {
+ mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[0].freq = (val >> 9) & mask;
+ pcal[1].freq = (val >> 2) & mask;
+ pcal[2].freq = (val << 5) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[2].freq |= (val >> 11) & 0x1f;
+ pcal[3].freq = (val >> 4) & mask;
+ pcal[4].freq = (val << 3) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[4].freq |= (val >> 13) & 0x7;
+ pcal[5].freq = (val >> 6) & mask;
+ pcal[6].freq = (val << 1) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[6].freq |= (val >> 15) & 0x1;
+ pcal[7].freq = (val >> 8) & mask;
+ pcal[8].freq = (val >> 1) & mask;
+ pcal[9].freq = (val << 6) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[9].freq |= (val >> 10) & 0x3f;
+
+ /* Fixed number of piers */
+ ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
+
+ for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
+ pcal[i].freq = ath5k_eeprom_bin2freq(ee,
+ pcal[i].freq, AR5K_EEPROM_MODE_11A);
+ }
+ }
+
+ return 0;
+}
+
+/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
+static inline int
+ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal;
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11B:
+ pcal = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ pcal = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ath5k_eeprom_read_freq_list(ah, &offset,
+ AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
+ mode);
+
+ return 0;
+}
+
+/*
+ * Read power calibration for RF5111 chips
+ *
+ * For RF5111 we have an XPD -eXternal Power Detector- curve
+ * for each calibrated channel. Each curve has 0,5dB Power steps
+ * on x axis and PCDAC steps (offsets) on y axis and looks like an
+ * exponential function. To recreate the curve we read 11 points
+ * here and interpolate later.
+ */
+
+/* Used to match PCDAC steps with power values on RF5111 chips
+ * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
+ * steps that match with the power values we read from eeprom. On
+ * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * 10% of the pcdac curve -until the curve reaches it's maximum-
+ * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
+ * these 11 steps are spaced in a different way. This function returns
+ * the pcdac steps based on eeprom version and curve min/max so that we
+ * can have pcdac/pwr points.
+ */
+static inline void
+ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
+{
+ static const u16 intercepts3[] =
+ { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
+ static const u16 intercepts3_2[] =
+ { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+ const u16 *ip;
+ unsigned i;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
+ ip = intercepts3_2;
+ else
+ ip = intercepts3;
+
+ for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
+ vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
+}
+
+/* Convert RF5111 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
+ struct ath5k_chan_pcal_info *chinfo)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5111 *pcinfo;
+ struct ath5k_pdgain_info *pd;
+ u8 pier, point, idx;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+
+ /* Fill raw data for each calibration pier */
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+ pcinfo = &chinfo[pier].rf5111_info;
+
+ /* Allocate pd_curves for this cal pier */
+ chinfo[pier].pd_curves =
+ calloc(AR5K_EEPROM_N_PD_CURVES,
+ sizeof(struct ath5k_pdgain_info));
+
+ if (!chinfo[pier].pd_curves)
+ return -ENOMEM;
+
+ /* Only one curve for RF5111
+ * find out which one and place
+ * in in pd_curves.
+ * Note: ee_x_gain is reversed here */
+ for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
+
+ if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
+ pdgain_idx[0] = idx;
+ break;
+ }
+ }
+
+ ee->ee_pd_gains[mode] = 1;
+
+ pd = &chinfo[pier].pd_curves[idx];
+
+ pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(u8));
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(s16));
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+ /* Fill raw dataset
+ * (convert power to 0.25dB units
+ * for RF5112 combatibility) */
+ for (point = 0; point < pd->pd_points; point++) {
+
+ /* Absolute values */
+ pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
+
+ /* Already sorted */
+ pd->pd_step[point] = pcinfo->pcdac[point];
+ }
+
+ /* Set min/max pwr */
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+ chinfo[pier].max_pwr = pd->pd_pwr[10];
+
+ }
+
+ return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal;
+ int offset, ret;
+ int i;
+ u16 val;
+
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+
+ ret = ath5k_eeprom_init_11a_pcal_freq(ah,
+ offset + AR5K_EEPROM_GROUP1_OFFSET);
+ if (ret < 0)
+ return ret;
+
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+ pcal = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
+ !AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ pcal = ee->ee_pwr_cal_b;
+ offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+ /* fixed piers */
+ pcal[0].freq = 2412;
+ pcal[1].freq = 2447;
+ pcal[2].freq = 2484;
+ ee->ee_n_piers[mode] = 3;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ pcal = ee->ee_pwr_cal_g;
+ offset += AR5K_EEPROM_GROUP4_OFFSET;
+
+ /* fixed piers */
+ pcal[0].freq = 2312;
+ pcal[1].freq = 2412;
+ pcal[2].freq = 2484;
+ ee->ee_n_piers[mode] = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ struct ath5k_chan_pcal_info_rf5111 *cdata =
+ &pcal[i].rf5111_info;
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
+ cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
+ cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[0] |= ((val >> 14) & 0x3);
+ cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[3] |= ((val >> 12) & 0xf);
+ cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
+
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[8] |= ((val >> 14) & 0x3);
+ cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+
+ ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
+ cdata->pcdac_max, cdata->pcdac);
+ }
+
+ return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
+}
+
+
+/*
+ * Read power calibration for RF5112 chips
+ *
+ * For RF5112 we have 4 XPD -eXternal Power Detector- curves
+ * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
+ * power steps on x axis and PCDAC steps on y axis and looks like a
+ * linear function. To recreate the curve and pass the power values
+ * on hw, we read 4 points for xpd 0 (lower gain -> max power)
+ * and 3 points for xpd 3 (higher gain -> lower power) here and
+ * interpolate later.
+ *
+ * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
+ */
+
+/* Convert RF5112 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
+ struct ath5k_chan_pcal_info *chinfo)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5112 *pcinfo;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ unsigned int pier, pdg, point;
+
+ /* Fill raw data for each calibration pier */
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+ pcinfo = &chinfo[pier].rf5112_info;
+
+ /* Allocate pd_curves for this cal pier */
+ chinfo[pier].pd_curves =
+ calloc(AR5K_EEPROM_N_PD_CURVES,
+ sizeof(struct ath5k_pdgain_info));
+
+ if (!chinfo[pier].pd_curves)
+ return -ENOMEM;
+
+ /* Fill pd_curves */
+ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+
+ u8 idx = pdgain_idx[pdg];
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[idx];
+
+ /* Lowest gain curve (max power) */
+ if (pdg == 0) {
+ /* One more point for better accuracy */
+ pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(pd->pd_points, sizeof(u8));
+
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
+
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+
+ /* Fill raw dataset
+ * (all power levels are in 0.25dB units) */
+ pd->pd_step[0] = pcinfo->pcdac_x0[0];
+ pd->pd_pwr[0] = pcinfo->pwr_x0[0];
+
+ for (point = 1; point < pd->pd_points;
+ point++) {
+ /* Absolute values */
+ pd->pd_pwr[point] =
+ pcinfo->pwr_x0[point];
+
+ /* Deltas */
+ pd->pd_step[point] =
+ pd->pd_step[point - 1] +
+ pcinfo->pcdac_x0[point];
+ }
+
+ /* Set min power for this frequency */
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+
+ /* Highest gain curve (min power) */
+ } else if (pdg == 1) {
+
+ pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(pd->pd_points, sizeof(u8));
+
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
+
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+ /* Fill raw dataset
+ * (all power levels are in 0.25dB units) */
+ for (point = 0; point < pd->pd_points;
+ point++) {
+ /* Absolute values */
+ pd->pd_pwr[point] =
+ pcinfo->pwr_x3[point];
+
+ /* Fixed points */
+ pd->pd_step[point] =
+ pcinfo->pcdac_x3[point];
+ }
+
+ /* Since we have a higher gain curve
+ * override min power */
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ u32 offset;
+ u8 i, c;
+ u16 val;
+ int ret;
+ u8 pd_gains = 0;
+
+ /* Count how many curves we have and
+ * identify them (which one of the 4
+ * available curves we have on each count).
+ * Curves are stored from lower (x0) to
+ * higher (x3) gain */
+ for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
+ /* ee_x_gain[mode] is x gain mask */
+ if ((ee->ee_x_gain[mode] >> i) & 0x1)
+ pdgain_idx[pd_gains++] = i;
+ }
+ ee->ee_pd_gains[mode] = pd_gains;
+
+ if (pd_gains == 0 || pd_gains > 2)
+ return -EINVAL;
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ /*
+ * Read 5GHz EEPROM channels
+ */
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+ gen_chan_info = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+ /* NB: frequency piers parsed during mode init */
+ gen_chan_info = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP4_OFFSET;
+ else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+
+ /* NB: frequency piers parsed during mode init */
+ gen_chan_info = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ chan_pcal_info = &gen_chan_info[i].rf5112_info;
+
+ /* Power values in quarter dB
+ * for the lower xpd gain curve
+ * (0 dBm -> higher output power) */
+ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
+ chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
+ }
+
+ /* PCDAC steps
+ * corresponding to the above power
+ * measurements */
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
+ chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
+ chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
+
+ /* Power values in quarter dB
+ * for the higher xpd gain curve
+ * (18 dBm -> lower output power) */
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
+ chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
+
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x3[2] = (val & 0xff);
+
+ /* PCDAC steps
+ * corresponding to the above power
+ * measurements (fixed) */
+ chan_pcal_info->pcdac_x3[0] = 20;
+ chan_pcal_info->pcdac_x3[1] = 35;
+ chan_pcal_info->pcdac_x3[2] = 63;
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
+ chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
+
+ /* Last xpd0 power level is also channel maximum */
+ gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
+ } else {
+ chan_pcal_info->pcdac_x0[0] = 1;
+ gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
+ }
+
+ }
+
+ return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
+}
+
+
+/*
+ * Read power calibration for RF2413 chips
+ *
+ * For RF2413 we have a Power to PDDAC table (Power Detector)
+ * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
+ * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
+ * axis and looks like an exponential function like the RF5111 curve.
+ *
+ * To recreate the curves we read here the points and interpolate
+ * later. Note that in most cases only 2 (higher and lower) curves are
+ * used (like RF5112) but vendors have the oportunity to include all
+ * 4 curves on eeprom. The final curve (higher power) has an extra
+ * point for better accuracy like RF5112.
+ */
+
+/* For RF2413 power calibration data doesn't start on a fixed location and
+ * if a mode is not supported, it's section is missing -not zeroed-.
+ * So we need to calculate the starting offset for each section by using
+ * these two functions */
+
+/* Return the size of each section based on the mode and the number of pd
+ * gains available (maximum 4). */
+static inline unsigned int
+ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
+{
+ static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
+ unsigned int sz;
+
+ sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
+ sz *= ee->ee_n_piers[mode];
+
+ return sz;
+}
+
+/* Return the starting offset for a section based on the modes supported
+ * and each section's size. */
+static unsigned int
+ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
+{
+ u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11G:
+ if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ offset += ath5k_pdgains_size_2413(ee,
+ AR5K_EEPROM_MODE_11B) +
+ AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ /* fall through */
+ case AR5K_EEPROM_MODE_11B:
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += ath5k_pdgains_size_2413(ee,
+ AR5K_EEPROM_MODE_11A) +
+ AR5K_EEPROM_N_5GHZ_CHAN / 2;
+ /* fall through */
+ case AR5K_EEPROM_MODE_11A:
+ break;
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+/* Convert RF2413 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
+ struct ath5k_chan_pcal_info *chinfo)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ unsigned int pier, point;
+ int pdg;
+
+ /* Fill raw data for each calibration pier */
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+ pcinfo = &chinfo[pier].rf2413_info;
+
+ /* Allocate pd_curves for this cal pier */
+ chinfo[pier].pd_curves =
+ calloc(AR5K_EEPROM_N_PD_CURVES,
+ sizeof(struct ath5k_pdgain_info));
+
+ if (!chinfo[pier].pd_curves)
+ return -ENOMEM;
+
+ /* Fill pd_curves */
+ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+
+ u8 idx = pdgain_idx[pdg];
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[idx];
+
+ /* One more point for the highest power
+ * curve (lowest gain) */
+ if (pdg == ee->ee_pd_gains[mode] - 1)
+ pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
+ else
+ pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
+
+ /* Allocate pd points for this curve */
+ pd->pd_step = calloc(pd->pd_points, sizeof(u8));
+
+ if (!pd->pd_step)
+ return -ENOMEM;
+
+ pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
+
+ if (!pd->pd_pwr)
+ return -ENOMEM;
+
+ /* Fill raw dataset
+ * convert all pwr levels to
+ * quarter dB for RF5112 combatibility */
+ pd->pd_step[0] = pcinfo->pddac_i[pdg];
+ pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
+
+ for (point = 1; point < pd->pd_points; point++) {
+
+ pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
+ 2 * pcinfo->pwr[pdg][point - 1];
+
+ pd->pd_step[point] = pd->pd_step[point - 1] +
+ pcinfo->pddac[pdg][point - 1];
+
+ }
+
+ /* Highest gain curve -> min power */
+ if (pdg == 0)
+ chinfo[pier].min_pwr = pd->pd_pwr[0];
+
+ /* Lowest gain curve -> max power */
+ if (pdg == ee->ee_pd_gains[mode] - 1)
+ chinfo[pier].max_pwr =
+ pd->pd_pwr[pd->pd_points - 1];
+ }
+ }
+
+ return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+ struct ath5k_chan_pcal_info *chinfo;
+ u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+ u32 offset;
+ int idx, i, ret;
+ u16 val;
+ u8 pd_gains = 0;
+
+ /* Count how many curves we have and
+ * identify them (which one of the 4
+ * available curves we have on each count).
+ * Curves are stored from higher to
+ * lower gain so we go backwards */
+ for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
+ /* ee_x_gain[mode] is x gain mask */
+ if ((ee->ee_x_gain[mode] >> idx) & 0x1)
+ pdgain_idx[pd_gains++] = idx;
+
+ }
+ ee->ee_pd_gains[mode] = pd_gains;
+
+ if (pd_gains == 0)
+ return -EINVAL;
+
+ offset = ath5k_cal_data_offset_2413(ee, mode);
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+ offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
+ chinfo = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+ offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ chinfo = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+ offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ chinfo = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ pcinfo = &chinfo[i].rf2413_info;
+
+ /*
+ * Read pwr_i, pddac_i and the first
+ * 2 pd points (pwr, pddac)
+ */
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr_i[0] = val & 0x1f;
+ pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
+ pcinfo->pwr[0][0] = (val >> 12) & 0xf;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[0][0] = val & 0x3f;
+ pcinfo->pwr[0][1] = (val >> 6) & 0xf;
+ pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[0][2] = val & 0xf;
+ pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
+
+ pcinfo->pwr[0][3] = 0;
+ pcinfo->pddac[0][3] = 0;
+
+ if (pd_gains > 1) {
+ /*
+ * Pd gain 0 is not the last pd gain
+ * so it only has 2 pd points.
+ * Continue wih pd gain 1.
+ */
+ pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
+
+ pcinfo->pddac_i[1] = (val >> 15) & 0x1;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
+
+ pcinfo->pwr[1][0] = (val >> 6) & 0xf;
+ pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[1][1] = val & 0xf;
+ pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
+ pcinfo->pwr[1][2] = (val >> 10) & 0xf;
+
+ pcinfo->pddac[1][2] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[1][2] |= (val & 0xF) << 2;
+
+ pcinfo->pwr[1][3] = 0;
+ pcinfo->pddac[1][3] = 0;
+ } else if (pd_gains == 1) {
+ /*
+ * Pd gain 0 is the last one so
+ * read the extra point.
+ */
+ pcinfo->pwr[0][3] = (val >> 10) & 0xf;
+
+ pcinfo->pddac[0][3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[0][3] |= (val & 0xF) << 2;
+ }
+
+ /*
+ * Proceed with the other pd_gains
+ * as above.
+ */
+ if (pd_gains > 2) {
+ pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
+ pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[2][0] = (val >> 0) & 0xf;
+ pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
+ pcinfo->pwr[2][1] = (val >> 10) & 0xf;
+
+ pcinfo->pddac[2][1] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[2][1] |= (val & 0xF) << 2;
+
+ pcinfo->pwr[2][2] = (val >> 4) & 0xf;
+ pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
+
+ pcinfo->pwr[2][3] = 0;
+ pcinfo->pddac[2][3] = 0;
+ } else if (pd_gains == 2) {
+ pcinfo->pwr[1][3] = (val >> 4) & 0xf;
+ pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
+ }
+
+ if (pd_gains > 3) {
+ pcinfo->pwr_i[3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
+
+ pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
+ pcinfo->pwr[3][0] = (val >> 10) & 0xf;
+ pcinfo->pddac[3][0] = (val >> 14) & 0x3;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[3][0] |= (val & 0xF) << 2;
+ pcinfo->pwr[3][1] = (val >> 4) & 0xf;
+ pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
+
+ pcinfo->pwr[3][2] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
+
+ pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
+ pcinfo->pwr[3][3] = (val >> 8) & 0xf;
+
+ pcinfo->pddac[3][3] = (val >> 12) & 0xF;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
+ } else if (pd_gains == 3) {
+ pcinfo->pwr[2][3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
+
+ pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
+ }
+ }
+
+ return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
+}
+
+
+/*
+ * Read per rate target power (this is the maximum tx power
+ * supported by the card). This info is used when setting
+ * tx power, no matter the channel.
+ *
+ * This also works for v5 EEPROMs.
+ */
+static int
+ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_rate_pcal_info *rate_pcal_info;
+ u8 *rate_target_pwr_num;
+ u32 offset;
+ u16 val;
+ int ret, i;
+
+ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
+ rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_a;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_b;
+ ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_g;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Different freq mask for older eeproms (<= v3.2) */
+ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
+ for (i = 0; i < (*rate_target_pwr_num); i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ rate_pcal_info[i].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
+
+ rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
+ rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+
+ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+ val == 0) {
+ (*rate_target_pwr_num) = i;
+ break;
+ }
+
+ rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
+ rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
+ rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
+ }
+ } else {
+ for (i = 0; i < (*rate_target_pwr_num); i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ rate_pcal_info[i].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+
+ rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
+ rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+
+ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+ val == 0) {
+ (*rate_target_pwr_num) = i;
+ break;
+ }
+
+ rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
+ rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
+ rate_pcal_info[i].target_power_54 = (val & 0x3f);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Read per channel calibration info from EEPROM
+ *
+ * This info is used to calibrate the baseband power table. Imagine
+ * that for each channel there is a power curve that's hw specific
+ * (depends on amplifier etc) and we try to "correct" this curve using
+ * offests we pass on to phy chip (baseband -> before amplifier) so that
+ * it can use accurate power values when setting tx power (takes amplifier's
+ * performance on each channel into account).
+ *
+ * EEPROM provides us with the offsets for some pre-calibrated channels
+ * and we have to interpolate to create the full table for these channels and
+ * also the table for any channel.
+ */
+static int
+ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int (*read_pcal)(struct ath5k_hw *hw, int mode);
+ int mode;
+ int err;
+
+ if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
+ (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
+ read_pcal = ath5k_eeprom_read_pcal_info_5112;
+ else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
+ (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
+ read_pcal = ath5k_eeprom_read_pcal_info_2413;
+ else
+ read_pcal = ath5k_eeprom_read_pcal_info_5111;
+
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
+ mode++) {
+ err = read_pcal(ah, mode);
+ if (err)
+ return err;
+
+ err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *chinfo;
+ u8 pier, pdg;
+
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+ chinfo = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+ return 0;
+ chinfo = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+ chinfo = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+ if (!chinfo[pier].pd_curves)
+ continue;
+
+ for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[pdg];
+
+ if (pd != NULL) {
+ free(pd->pd_step);
+ free(pd->pd_pwr);
+ }
+ }
+
+ free(chinfo[pier].pd_curves);
+ }
+
+ return 0;
+}
+
+void
+ath5k_eeprom_detach(struct ath5k_hw *ah)
+{
+ u8 mode;
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
+ ath5k_eeprom_free_pcal_info(ah, mode);
+}
+
+/* Read conformance test limits used for regulatory control */
+static int
+ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_edge_power *rep;
+ unsigned int fmask, pmask;
+ unsigned int ctl_mode;
+ int ret, i, j;
+ u32 offset;
+ u16 val;
+
+ pmask = AR5K_EEPROM_POWER_M;
+ fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
+ offset = AR5K_EEPROM_CTL(ee->ee_version);
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
+ for (i = 0; i < ee->ee_ctls; i += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
+ ee->ee_ctl[i + 1] = val & 0xff;
+ }
+
+ offset = AR5K_EEPROM_GROUP8_OFFSET;
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
+ offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
+ AR5K_EEPROM_GROUP5_OFFSET;
+ else
+ offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
+
+ rep = ee->ee_ctl_pwr;
+ for(i = 0; i < ee->ee_ctls; i++) {
+ switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+ case AR5K_CTL_11A:
+ case AR5K_CTL_TURBO:
+ ctl_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ ctl_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ }
+ if (ee->ee_ctl[i] == 0) {
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
+ offset += 8;
+ else
+ offset += 7;
+ rep += AR5K_EEPROM_N_EDGES;
+ continue;
+ }
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[j].freq = (val >> 8) & fmask;
+ rep[j + 1].freq = val & fmask;
+ }
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[j].edge = (val >> 8) & pmask;
+ rep[j].flag = (val >> 14) & 1;
+ rep[j + 1].edge = val & pmask;
+ rep[j + 1].flag = (val >> 6) & 1;
+ }
+ } else {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[0].freq = (val >> 9) & fmask;
+ rep[1].freq = (val >> 2) & fmask;
+ rep[2].freq = (val << 5) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[2].freq |= (val >> 11) & 0x1f;
+ rep[3].freq = (val >> 4) & fmask;
+ rep[4].freq = (val << 3) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[4].freq |= (val >> 13) & 0x7;
+ rep[5].freq = (val >> 6) & fmask;
+ rep[6].freq = (val << 1) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[6].freq |= (val >> 15) & 0x1;
+ rep[7].freq = (val >> 8) & fmask;
+
+ rep[0].edge = (val >> 2) & pmask;
+ rep[1].edge = (val << 4) & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[1].edge |= (val >> 12) & 0xf;
+ rep[2].edge = (val >> 6) & pmask;
+ rep[3].edge = val & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[4].edge = (val >> 10) & pmask;
+ rep[5].edge = (val >> 4) & pmask;
+ rep[6].edge = (val << 2) & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[6].edge |= (val >> 14) & 0x3;
+ rep[7].edge = (val >> 8) & pmask;
+ }
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
+ rep[j].freq = ath5k_eeprom_bin2freq(ee,
+ rep[j].freq, ctl_mode);
+ }
+ rep += AR5K_EEPROM_N_EDGES;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Initialize eeprom power tables
+ */
+int
+ath5k_eeprom_init(struct ath5k_hw *ah)
+{
+ int err;
+
+ err = ath5k_eeprom_init_header(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_init_modes(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_read_pcal_info(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_read_ctl_info(ah);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+/*
+ * Read the MAC address from eeprom
+ */
+int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ u8 mac_d[ETH_ALEN] = {};
+ u32 total, offset;
+ u16 data;
+ int octet, ret;
+
+ ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
+ if (ret)
+ return ret;
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+ ret = ath5k_hw_eeprom_read(ah, offset, &data);
+ if (ret)
+ return ret;
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ if (!total || total == 3 * 0xffff)
+ return -EINVAL;
+
+ memcpy(mac, mac_d, ETH_ALEN);
+
+ return 0;
+}
+
+int ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
+{
+ u16 data;
+
+ ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)
+ return 1;
+ else
+ return 0;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_gpio.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_gpio.c
new file mode 100644
index 0000000..0e8a3e6
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_gpio.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/****************\
+ GPIO Functions
+\****************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Set GPIO inputs
+ */
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
+{
+ if (gpio >= AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah,
+ (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+ | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Set GPIO outputs
+ */
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
+{
+ if (gpio >= AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah,
+ (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+ | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Get GPIO state
+ */
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
+{
+ if (gpio >= AR5K_NUM_GPIO)
+ return 0xffffffff;
+
+ /* GPIO input magic */
+ return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
+ 0x1;
+}
+
+/*
+ * Set GPIO state
+ */
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
+{
+ u32 data;
+
+ if (gpio >= AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ /* GPIO output magic */
+ data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ data &= ~(1 << gpio);
+ data |= (val & 1) << gpio;
+
+ ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
+
+ return 0;
+}
+
+/*
+ * Initialize the GPIO interrupt (RFKill switch)
+ */
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+ u32 interrupt_level)
+{
+ u32 data;
+
+ if (gpio >= AR5K_NUM_GPIO)
+ return;
+
+ /*
+ * Set the GPIO interrupt
+ */
+ data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
+ ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
+ AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
+ (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
+
+ ath5k_hw_reg_write(ah, interrupt_level ? data :
+ (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
+
+ ah->ah_imr |= AR5K_IMR_GPIO;
+
+ /* Enable GPIO interrupts */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_initvals.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_initvals.c
new file mode 100644
index 0000000..5911be8
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_initvals.c
@@ -0,0 +1,1560 @@
+/*
+ * Initial register settings functions
+ *
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+#include <unistd.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Mode-independent initial register writes
+ */
+
+struct ath5k_ini {
+ u16 ini_register;
+ u32 ini_value;
+
+ enum {
+ AR5K_INI_WRITE = 0, /* Default */
+ AR5K_INI_READ = 1, /* Cleared on read */
+ } ini_mode;
+};
+
+/*
+ * Mode specific initial register values
+ */
+
+struct ath5k_ini_mode {
+ u16 mode_register;
+ u32 mode_value[5];
+};
+
+/* Initial register settings for AR5210 */
+static const struct ath5k_ini ar5210_ini[] = {
+ /* PCU and MAC registers */
+ { AR5K_NOQCU_TXDP0, 0, AR5K_INI_WRITE },
+ { AR5K_NOQCU_TXDP1, 0, AR5K_INI_WRITE },
+ { AR5K_RXDP, 0, AR5K_INI_WRITE },
+ { AR5K_CR, 0, AR5K_INI_WRITE },
+ { AR5K_ISR, 0, AR5K_INI_READ },
+ { AR5K_IMR, 0, AR5K_INI_WRITE },
+ { AR5K_IER, AR5K_IER_DISABLE, AR5K_INI_WRITE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
+ { AR5K_TXCFG, AR5K_DMASIZE_128B, AR5K_INI_WRITE },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B, AR5K_INI_WRITE },
+ { AR5K_CFG, AR5K_INIT_CFG, AR5K_INI_WRITE },
+ { AR5K_TOPS, 8, AR5K_INI_WRITE },
+ { AR5K_RXNOFRM, 8, AR5K_INI_WRITE },
+ { AR5K_RPGTO, 0, AR5K_INI_WRITE },
+ { AR5K_TXNOFRM, 0, AR5K_INI_WRITE },
+ { AR5K_SFR, 0, AR5K_INI_WRITE },
+ { AR5K_MIBC, 0, AR5K_INI_WRITE },
+ { AR5K_MISC, 0, AR5K_INI_WRITE },
+ { AR5K_RX_FILTER_5210, 0, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER0_5210, 0, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER1_5210, 0, AR5K_INI_WRITE },
+ { AR5K_TX_MASK0, 0, AR5K_INI_WRITE },
+ { AR5K_TX_MASK1, 0, AR5K_INI_WRITE },
+ { AR5K_CLR_TMASK, 0, AR5K_INI_WRITE },
+ { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES, AR5K_INI_WRITE },
+ { AR5K_DIAG_SW_5210, 0, AR5K_INI_WRITE },
+ { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES, AR5K_INI_WRITE },
+ { AR5K_TSF_L32_5210, 0, AR5K_INI_WRITE },
+ { AR5K_TIMER0_5210, 0, AR5K_INI_WRITE },
+ { AR5K_TIMER1_5210, 0xffffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER2_5210, 0xffffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER3_5210, 1, AR5K_INI_WRITE },
+ { AR5K_CFP_DUR_5210, 0, AR5K_INI_WRITE },
+ { AR5K_CFP_PERIOD_5210, 0, AR5K_INI_WRITE },
+ /* PHY registers */
+ { AR5K_PHY(0), 0x00000047, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(3), 0x09848ea6, AR5K_INI_WRITE },
+ { AR5K_PHY(4), 0x3d32e000, AR5K_INI_WRITE },
+ { AR5K_PHY(5), 0x0000076b, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE, AR5K_INI_WRITE },
+ { AR5K_PHY(8), 0x02020200, AR5K_INI_WRITE },
+ { AR5K_PHY(9), 0x00000e0e, AR5K_INI_WRITE },
+ { AR5K_PHY(10), 0x0a020201, AR5K_INI_WRITE },
+ { AR5K_PHY(11), 0x00036ffc, AR5K_INI_WRITE },
+ { AR5K_PHY(12), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(13), 0x00000e0e, AR5K_INI_WRITE },
+ { AR5K_PHY(14), 0x00000007, AR5K_INI_WRITE },
+ { AR5K_PHY(15), 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY(16), 0x89630000, AR5K_INI_WRITE },
+ { AR5K_PHY(17), 0x1372169c, AR5K_INI_WRITE },
+ { AR5K_PHY(18), 0x0018b633, AR5K_INI_WRITE },
+ { AR5K_PHY(19), 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY(20), 0x0de8b8e0, AR5K_INI_WRITE },
+ { AR5K_PHY(21), 0x00074859, AR5K_INI_WRITE },
+ { AR5K_PHY(22), 0x7e80beba, AR5K_INI_WRITE },
+ { AR5K_PHY(23), 0x313a665e, AR5K_INI_WRITE },
+ { AR5K_PHY_AGCCTL, 0x00001d08, AR5K_INI_WRITE },
+ { AR5K_PHY(25), 0x0001ce00, AR5K_INI_WRITE },
+ { AR5K_PHY(26), 0x409a4190, AR5K_INI_WRITE },
+ { AR5K_PHY(28), 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_PHY(29), 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY(30), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY(31), 0x00000018, AR5K_INI_WRITE }, /* 0x987c */
+ { AR5K_PHY(64), 0x00000000, AR5K_INI_WRITE }, /* 0x9900 */
+ { AR5K_PHY(65), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(66), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(67), 0x00800000, AR5K_INI_WRITE },
+ { AR5K_PHY(68), 0x00000003, AR5K_INI_WRITE },
+ /* BB gain table (64bytes) */
+ { AR5K_BB_GAIN(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(1), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(2), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(3), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(4), 0x00000008, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(5), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(6), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(7), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(8), 0x00000024, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(9), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(10), 0x00000034, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(11), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(12), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(13), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(14), 0x00000022, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(15), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(16), 0x00000032, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(17), 0x0000000a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(18), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(19), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(20), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(21), 0x00000011, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(22), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(23), 0x00000009, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(24), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(25), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(26), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(27), 0x00000015, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(28), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(29), 0x0000000d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(30), 0x0000002d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(31), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(32), 0x00000023, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(33), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(34), 0x00000033, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(35), 0x0000000b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(36), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(37), 0x00000007, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(38), 0x00000027, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(39), 0x00000017, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(40), 0x00000037, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(41), 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(42), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(43), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(44), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(45), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(46), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(47), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(48), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(49), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(50), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(51), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(52), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(53), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(54), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(55), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(56), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(57), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(58), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(59), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(60), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(61), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(62), 0x0000002f, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(63), 0x0000002f, AR5K_INI_WRITE },
+ /* 5110 RF gain table (64btes) */
+ { AR5K_RF_GAIN(0), 0x0000001d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(1), 0x0000005d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(2), 0x0000009d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(3), 0x000000dd, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(4), 0x0000011d, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(5), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(6), 0x00000061, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(7), 0x000000a1, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(8), 0x000000e1, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(9), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(10), 0x00000071, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(11), 0x000000b1, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(12), 0x0000001c, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(13), 0x0000005c, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(14), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(15), 0x00000069, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(16), 0x000000a9, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(17), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(18), 0x00000019, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(19), 0x00000059, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(20), 0x00000099, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(21), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(22), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(23), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(24), 0x00000065, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(25), 0x000000a5, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(26), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(27), 0x00000068, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(28), 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(29), 0x0000001e, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(30), 0x00000018, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(31), 0x00000058, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(32), 0x00000098, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(33), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(34), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(35), 0x00000044, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(36), 0x00000084, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(37), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(38), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(39), 0x00000052, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(40), 0x00000092, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(41), 0x000000d2, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(42), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(43), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(44), 0x0000006a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(45), 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(46), 0x0000001b, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(47), 0x0000001a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(48), 0x0000005a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(49), 0x0000009a, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(50), 0x000000da, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(51), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(52), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(53), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(54), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(55), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(56), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(57), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(58), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(59), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(60), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(61), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(62), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_RF_GAIN(63), 0x00000006, AR5K_INI_WRITE },
+ /* PHY activation */
+ { AR5K_PHY(53), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_PHY(51), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY(50), 0x00060106, AR5K_INI_WRITE },
+ { AR5K_PHY(39), 0x0000006d, AR5K_INI_WRITE },
+ { AR5K_PHY(48), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(52), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE, AR5K_INI_WRITE },
+};
+
+/* Initial register settings for AR5211 */
+static const struct ath5k_ini ar5211_ini[] = {
+ { AR5K_RXDP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RTSD0, 0x84849c9c, AR5K_INI_WRITE },
+ { AR5K_RTSD1, 0x7c7c7c7c, AR5K_INI_WRITE },
+ { AR5K_RXCFG, 0x00000005, AR5K_INI_WRITE },
+ { AR5K_MIBC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TOPS, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_RXNOFRM, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_TXNOFRM, 0x00000010, AR5K_INI_WRITE },
+ { AR5K_RPGTO, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RFCNT, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(8), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_STA_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RSSI_THR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CFP_PERIOD_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TIMER0_5211, 0x00000030, AR5K_INI_WRITE },
+ { AR5K_TIMER1_5211, 0x0007ffff, AR5K_INI_WRITE },
+ { AR5K_TIMER2_5211, 0x01ffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER3_5211, 0x00000031, AR5K_INI_WRITE },
+ { AR5K_CFP_DUR_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RX_FILTER_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER0_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MCAST_FILTER1_5211, 0x00000002, AR5K_INI_WRITE },
+ { AR5K_DIAG_SW_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_ADDAC_TEST, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DEFAULT_ANTENNA, 0x00000000, AR5K_INI_WRITE },
+ /* PHY registers */
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(3), 0x2d849093, AR5K_INI_WRITE },
+ { AR5K_PHY(4), 0x7d32e000, AR5K_INI_WRITE },
+ { AR5K_PHY(5), 0x00000f6b, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(11), 0x00026ffe, AR5K_INI_WRITE },
+ { AR5K_PHY(12), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(15), 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY(16), 0x206a017a, AR5K_INI_WRITE },
+ { AR5K_PHY(19), 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY(21), 0x00000859, AR5K_INI_WRITE },
+ { AR5K_PHY(26), 0x409a4190, AR5K_INI_WRITE }, /* 0x9868 */
+ { AR5K_PHY(27), 0x050cb081, AR5K_INI_WRITE },
+ { AR5K_PHY(28), 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_PHY(29), 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY(30), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY(64), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(65), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(66), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(67), 0x00800000, AR5K_INI_WRITE },
+ { AR5K_PHY(68), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY(71), 0x0000092a, AR5K_INI_WRITE },
+ { AR5K_PHY_IQ, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(73), 0x00058a05, AR5K_INI_WRITE },
+ { AR5K_PHY(74), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY(75), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_PAPD_PROBE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(77), 0x00000000, AR5K_INI_WRITE }, /* 0x9934 */
+ { AR5K_PHY(78), 0x00000000, AR5K_INI_WRITE }, /* 0x9938 */
+ { AR5K_PHY(79), 0x0000003f, AR5K_INI_WRITE }, /* 0x993c */
+ { AR5K_PHY(80), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY(82), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(83), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(84), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_RADAR, 0x5d50f14c, AR5K_INI_WRITE },
+ { AR5K_PHY(86), 0x00000018, AR5K_INI_WRITE },
+ { AR5K_PHY(87), 0x004b6a8e, AR5K_INI_WRITE },
+ /* Initial Power table (32bytes)
+ * common on all cards/modes.
+ * Note: Table is rewritten during
+ * txpower setup later using calibration
+ * data etc. so next write is non-common */
+ { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff, AR5K_INI_WRITE },
+ { AR5K_PHY_CCKTXCTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(642), 0x503e4646, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_2GHZ, 0x6480416c, AR5K_INI_WRITE },
+ { AR5K_PHY(644), 0x0199a003, AR5K_INI_WRITE },
+ { AR5K_PHY(645), 0x044cd610, AR5K_INI_WRITE },
+ { AR5K_PHY(646), 0x13800040, AR5K_INI_WRITE },
+ { AR5K_PHY(647), 0x1be00060, AR5K_INI_WRITE },
+ { AR5K_PHY(648), 0x0c53800a, AR5K_INI_WRITE },
+ { AR5K_PHY(649), 0x0014df3b, AR5K_INI_WRITE },
+ { AR5K_PHY(650), 0x000001b5, AR5K_INI_WRITE },
+ { AR5K_PHY(651), 0x00000020, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for AR5211
+ * 5211 supports OFDM-only g (draft g) but we
+ * need to test it !
+ */
+static const struct ath5k_ini_mode ar5211_ini_mode[] = {
+ { AR5K_TXCFG,
+ /* a aTurbo b g (OFDM) */
+ { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { AR5K_DCU_GBL_IFS_SLOT,
+ { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
+ { AR5K_DCU_GBL_IFS_SIFS,
+ { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
+ { AR5K_DCU_GBL_IFS_EIFS,
+ { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
+ { AR5K_DCU_GBL_IFS_MISC,
+ { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
+ { AR5K_TIME_OUT,
+ { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
+ { AR5K_USEC_5211,
+ { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(8),
+ { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
+ { AR5K_PHY(9),
+ { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
+ { AR5K_PHY(10),
+ { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
+ { AR5K_PHY(13),
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(14),
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY(17),
+ { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
+ { AR5K_PHY(18),
+ { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
+ { AR5K_PHY(20),
+ { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
+ { AR5K_PHY_AGCCTL,
+ { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
+ { AR5K_PHY_NF,
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
+ { AR5K_PHY(70),
+ { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
+ { AR5K_PHY_PCDAC_TXPOWER_BASE,
+ { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
+ { AR5K_RF_BUFFER_CONTROL_4,
+ { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
+};
+
+/* Initial register settings for AR5212 */
+static const struct ath5k_ini ar5212_ini_common_start[] = {
+ { AR5K_RXDP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RXCFG, 0x00000005, AR5K_INI_WRITE },
+ { AR5K_MIBC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TOPS, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_RXNOFRM, 0x00000008, AR5K_INI_WRITE },
+ { AR5K_TXNOFRM, 0x00000010, AR5K_INI_WRITE },
+ { AR5K_RPGTO, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RFCNT, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(8), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUEUE_TXDP(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TXP, 0x00000000, AR5K_INI_WRITE },
+ /* Tx filter table 0 (32 entries) */
+ { AR5K_DCU_TX_FILTER_0(0), 0x00000000, AR5K_INI_WRITE }, /* DCU 0 */
+ { AR5K_DCU_TX_FILTER_0(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(4), 0x00000000, AR5K_INI_WRITE }, /* DCU 1 */
+ { AR5K_DCU_TX_FILTER_0(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(8), 0x00000000, AR5K_INI_WRITE }, /* DCU 2 */
+ { AR5K_DCU_TX_FILTER_0(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(10), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(11), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(12), 0x00000000, AR5K_INI_WRITE }, /* DCU 3 */
+ { AR5K_DCU_TX_FILTER_0(13), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(14), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(15), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(16), 0x00000000, AR5K_INI_WRITE }, /* DCU 4 */
+ { AR5K_DCU_TX_FILTER_0(17), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(18), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(19), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(20), 0x00000000, AR5K_INI_WRITE }, /* DCU 5 */
+ { AR5K_DCU_TX_FILTER_0(21), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(22), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(23), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(24), 0x00000000, AR5K_INI_WRITE }, /* DCU 6 */
+ { AR5K_DCU_TX_FILTER_0(25), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(26), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(27), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(28), 0x00000000, AR5K_INI_WRITE }, /* DCU 7 */
+ { AR5K_DCU_TX_FILTER_0(29), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(30), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_0(31), 0x00000000, AR5K_INI_WRITE },
+ /* Tx filter table 1 (16 entries) */
+ { AR5K_DCU_TX_FILTER_1(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(1), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(2), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(3), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(6), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(7), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(8), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(9), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(10), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(11), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(12), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(13), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(14), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_1(15), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_CLR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_SET, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_CLR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DCU_TX_FILTER_SET, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_STA_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_ID1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BEACON_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CFP_PERIOD_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TIMER0_5211, 0x00000030, AR5K_INI_WRITE },
+ { AR5K_TIMER1_5211, 0x0007ffff, AR5K_INI_WRITE },
+ { AR5K_TIMER2_5211, 0x01ffffff, AR5K_INI_WRITE },
+ { AR5K_TIMER3_5211, 0x00000031, AR5K_INI_WRITE },
+ { AR5K_CFP_DUR_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RX_FILTER_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DIAG_SW_5211, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_ADDAC_TEST, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_DEFAULT_ANTENNA, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_FRAME_CTL_QOSM, 0x000fc78f, AR5K_INI_WRITE },
+ { AR5K_XRMODE, 0x2a82301a, AR5K_INI_WRITE },
+ { AR5K_XRDELAY, 0x05dc01e0, AR5K_INI_WRITE },
+ { AR5K_XRTIMEOUT, 0x1f402710, AR5K_INI_WRITE },
+ { AR5K_XRCHIRP, 0x01f40000, AR5K_INI_WRITE },
+ { AR5K_XRSTOMP, 0x00001e1c, AR5K_INI_WRITE },
+ { AR5K_SLEEP0, 0x0002aaaa, AR5K_INI_WRITE },
+ { AR5K_SLEEP1, 0x02005555, AR5K_INI_WRITE },
+ { AR5K_SLEEP2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BSS_IDM0, 0xffffffff, AR5K_INI_WRITE },
+ { AR5K_BSS_IDM1, 0x0000ffff, AR5K_INI_WRITE },
+ { AR5K_TXPC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_TX, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_RX, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_RXCLR, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PROFCNT_CYCLE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUIET_CTL1, 0x00000088, AR5K_INI_WRITE },
+ /* Initial rate duration table (32 entries )*/
+ { AR5K_RATE_DUR(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(1), 0x0000008c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(2), 0x000000e4, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(3), 0x000002d5, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(4), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(5), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(6), 0x000000a0, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(7), 0x000001c9, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(8), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(9), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(10), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(11), 0x0000003c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(12), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(13), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(14), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(15), 0x0000003c, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(16), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(17), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(18), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(19), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(20), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(21), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(22), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(23), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(24), 0x000000d5, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(25), 0x000000df, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(26), 0x00000102, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(27), 0x0000013a, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(28), 0x00000075, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(29), 0x0000007f, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(30), 0x000000a2, AR5K_INI_WRITE },
+ { AR5K_RATE_DUR(31), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_QUIET_CTL2, 0x00010002, AR5K_INI_WRITE },
+ { AR5K_TSF_PARM, 0x00000001, AR5K_INI_WRITE },
+ { AR5K_QOS_NOACK, 0x000000c0, AR5K_INI_WRITE },
+ { AR5K_PHY_ERR_FIL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_XRLAT_TX, 0x00000168, AR5K_INI_WRITE },
+ { AR5K_ACKSIFS, 0x00000000, AR5K_INI_WRITE },
+ /* Rate -> db table
+ * notice ...03<-02<-01<-00 ! */
+ { AR5K_RATE2DB(0), 0x03020100, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(1), 0x07060504, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(2), 0x0b0a0908, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(3), 0x0f0e0d0c, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(4), 0x13121110, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(5), 0x17161514, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(6), 0x1b1a1918, AR5K_INI_WRITE },
+ { AR5K_RATE2DB(7), 0x1f1e1d1c, AR5K_INI_WRITE },
+ /* Db -> Rate table */
+ { AR5K_DB2RATE(0), 0x03020100, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(1), 0x07060504, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(2), 0x0b0a0908, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(3), 0x0f0e0d0c, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(4), 0x13121110, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(5), 0x17161514, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(6), 0x1b1a1918, AR5K_INI_WRITE },
+ { AR5K_DB2RATE(7), 0x1f1e1d1c, AR5K_INI_WRITE },
+ /* PHY registers (Common settings
+ * for all chips/modes) */
+ { AR5K_PHY(3), 0xad848e19, AR5K_INI_WRITE },
+ { AR5K_PHY(4), 0x7d28e000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_3, 0x9c0a9f6b, AR5K_INI_WRITE },
+ { AR5K_PHY_ACT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY(16), 0x206a017a, AR5K_INI_WRITE },
+ { AR5K_PHY(21), 0x00000859, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_3, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_BIN_MASK_CTL, 0x00800000, AR5K_INI_WRITE },
+ { AR5K_PHY_ANT_CTL, 0x00000001, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(71), 0x0000092a, AR5K_INI_WRITE },*/ /* Old value */
+ { AR5K_PHY_MAX_RX_LEN, 0x00000c80, AR5K_INI_WRITE },
+ { AR5K_PHY_IQ, 0x05100000, AR5K_INI_WRITE },
+ { AR5K_PHY_WARM_RESET, 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY_CTL, 0x00000004, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f, AR5K_INI_WRITE },
+ { AR5K_PHY(82), 0x9280b212, AR5K_INI_WRITE },
+ { AR5K_PHY_RADAR, 0x5d50e188, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(86), 0x000000ff, AR5K_INI_WRITE },*/
+ { AR5K_PHY(87), 0x004b6a8e, AR5K_INI_WRITE },
+ { AR5K_PHY_NFTHRES, 0x000003ce, AR5K_INI_WRITE },
+ { AR5K_PHY_RESTART, 0x192fb515, AR5K_INI_WRITE },
+ { AR5K_PHY(94), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_PHY_RFBUS_REQ, 0x00000000, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(644), 0x0080a333, AR5K_INI_WRITE },*/ /* Old value */
+ /*{ AR5K_PHY(645), 0x00206c10, AR5K_INI_WRITE },*/ /* Old value */
+ { AR5K_PHY(644), 0x00806333, AR5K_INI_WRITE },
+ { AR5K_PHY(645), 0x00106c10, AR5K_INI_WRITE },
+ { AR5K_PHY(646), 0x009c4060, AR5K_INI_WRITE },
+ /* { AR5K_PHY(647), 0x1483800a, AR5K_INI_WRITE }, */
+ /* { AR5K_PHY(648), 0x01831061, AR5K_INI_WRITE }, */ /* Old value */
+ { AR5K_PHY(648), 0x018830c6, AR5K_INI_WRITE },
+ { AR5K_PHY(649), 0x00000400, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(650), 0x000001b5, AR5K_INI_WRITE },*/
+ { AR5K_PHY(651), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE3, 0x20202020, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE2, 0x20202020, AR5K_INI_WRITE },
+ /*{ AR5K_PHY(655), 0x13c889af, AR5K_INI_WRITE },*/
+ { AR5K_PHY(656), 0x38490a20, AR5K_INI_WRITE },
+ { AR5K_PHY(657), 0x00007bb6, AR5K_INI_WRITE },
+ { AR5K_PHY(658), 0x0fff3ffc, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
+static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_DCU_GBL_IFS_SIFS,
+ { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
+ { AR5K_DCU_GBL_IFS_SLOT,
+ { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
+ { AR5K_DCU_GBL_IFS_EIFS,
+ { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
+ { AR5K_DCU_GBL_IFS_MISC,
+ { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
+ { AR5K_TIME_OUT,
+ { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
+ { AR5K_PHY(8),
+ { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
+ { AR5K_PHY_RF_CTL2,
+ { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_SETTLING,
+ { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
+ { AR5K_PHY_AGCCTL,
+ { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
+ { AR5K_PHY_NF,
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { AR5K_PHY_WEAK_OFDM_HIGH_THR,
+ { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
+ { AR5K_PHY(70),
+ { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
+ { AR5K_PHY_OFDM_SELFCORR,
+ { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
+ { 0xa230,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ { AR5K_USEC_5211,
+ { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_GAIN,
+ { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf5111_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x00022ffe, AR5K_INI_WRITE },
+ { 0x983c, 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY_PAPD_PROBE, 0x00004883, AR5K_INI_WRITE },
+ { 0x9940, 0x00000004, AR5K_INI_WRITE },
+ { 0x9958, 0x000000ff, AR5K_INI_WRITE },
+ { 0x9974, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000018, AR5K_INI_WRITE },
+ { AR5K_PHY_CCKTXCTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_CCK_CROSSCORR, 0xd03e6788, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000001b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x13c889af, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_GAIN,
+ { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf5112_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x00022ffe, AR5K_INI_WRITE },
+ { 0x983c, 0x00020100, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284613c, AR5K_INI_WRITE },
+ { AR5K_PHY_PAPD_PROBE, 0x00004882, AR5K_INI_WRITE },
+ { 0x9940, 0x00000004, AR5K_INI_WRITE },
+ { 0x9958, 0x000000ff, AR5K_INI_WRITE },
+ { 0x9974, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000001b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x13c889af, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_GAIN,
+ { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0xa300,
+ { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
+ { 0xa304,
+ { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
+ { 0xa308,
+ { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
+ { 0xa30c,
+ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
+ { 0xa310,
+ { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
+ { 0xa314,
+ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
+ { 0xa318,
+ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
+ { 0xa31c,
+ { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
+ { 0xa320,
+ { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
+ { 0xa324,
+ { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
+ { 0xa328,
+ { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
+ { 0xa32c,
+ { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
+ { 0xa330,
+ { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
+ { 0xa334,
+ { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
+};
+
+static const struct ath5k_ini rf5413_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x000003e0, AR5K_INI_WRITE },
+ { AR5K_5414_CBCFG, 0x00000010, AR5K_INI_WRITE },
+ { AR5K_SEQ_MASK, 0x0000000f, AR5K_INI_WRITE },
+ { 0x809c, 0x00000000, AR5K_INI_WRITE },
+ { 0x80a0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_CTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_SEL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MISC_MODE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_OFDM_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CCK_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TSF_THRES, 0x00000000, AR5K_INI_WRITE },
+ { 0x8140, 0x800003f9, AR5K_INI_WRITE },
+ { 0x8144, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x0000a000, AR5K_INI_WRITE },
+ { 0x983c, 0x00200400, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284233c, AR5K_INI_WRITE },
+ { AR5K_PHY_SCR, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_PHY_SLMT, 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY_SCAL, 0x0000000e, AR5K_INI_WRITE },
+ { 0x9958, 0x00081fff, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_7, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_8, 0x02800000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_11, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000, AR5K_INI_WRITE },
+ { 0x99e4, 0xaaaaaaaa, AR5K_INI_WRITE },
+ { 0x99e8, 0x3c466478, AR5K_INI_WRITE },
+ { 0x99ec, 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_PHY_SCLOCK, 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY_SDELAY, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000009b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x93c889af, AR5K_INI_WRITE },
+ { AR5K_PHY_FAST_ADC, 0x00000001, AR5K_INI_WRITE },
+ { 0xa250, 0x0000a000, AR5K_INI_WRITE },
+ { AR5K_PHY_BLUETOOTH, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG1, 0x0cc75380, AR5K_INI_WRITE },
+ { 0xa25c, 0x0f0f0f01, AR5K_INI_WRITE },
+ { 0xa260, 0x5f690f01, AR5K_INI_WRITE },
+ { 0xa264, 0x00418a11, AR5K_INI_WRITE },
+ { 0xa268, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG5, 0x0c30c16a, AR5K_INI_WRITE },
+ { 0xa270, 0x00820820, AR5K_INI_WRITE },
+ { 0xa274, 0x081b7caa, AR5K_INI_WRITE },
+ { 0xa278, 0x1ce739ce, AR5K_INI_WRITE },
+ { 0xa27c, 0x051701ce, AR5K_INI_WRITE },
+ { 0xa338, 0x00000000, AR5K_INI_WRITE },
+ { 0xa33c, 0x00000000, AR5K_INI_WRITE },
+ { 0xa340, 0x00000000, AR5K_INI_WRITE },
+ { 0xa344, 0x00000000, AR5K_INI_WRITE },
+ { 0xa348, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa34c, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa350, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa354, 0x0003ffff, AR5K_INI_WRITE },
+ { 0xa358, 0x79a8aa1f, AR5K_INI_WRITE },
+ { 0xa35c, 0x066c420f, AR5K_INI_WRITE },
+ { 0xa360, 0x0f282207, AR5K_INI_WRITE },
+ { 0xa364, 0x17601685, AR5K_INI_WRITE },
+ { 0xa368, 0x1f801104, AR5K_INI_WRITE },
+ { 0xa36c, 0x37a00c03, AR5K_INI_WRITE },
+ { 0xa370, 0x3fc40883, AR5K_INI_WRITE },
+ { 0xa374, 0x57c00803, AR5K_INI_WRITE },
+ { 0xa378, 0x5fd80682, AR5K_INI_WRITE },
+ { 0xa37c, 0x7fe00482, AR5K_INI_WRITE },
+ { 0xa380, 0x7f3c7bba, AR5K_INI_WRITE },
+ { 0xa384, 0xf3307ff0, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
+/* XXX: a mode ? */
+static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
+ { AR5K_PHY_GAIN,
+ { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf2413_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x000003e0, AR5K_INI_WRITE },
+ { AR5K_SEQ_MASK, 0x0000000f, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_CTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_SEL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MISC_MODE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_OFDM_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CCK_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TSF_THRES, 0x00000000, AR5K_INI_WRITE },
+ { 0x8140, 0x800000a8, AR5K_INI_WRITE },
+ { 0x8144, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x0000a000, AR5K_INI_WRITE },
+ { 0x983c, 0x00200400, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284233c, AR5K_INI_WRITE },
+ { AR5K_PHY_SCR, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_PHY_SLMT, 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY_SCAL, 0x0000000e, AR5K_INI_WRITE },
+ { 0x9958, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_7, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_8, 0x02800000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_11, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000, AR5K_INI_WRITE },
+ { 0x99e4, 0xaaaaaaaa, AR5K_INI_WRITE },
+ { 0x99e8, 0x3c466478, AR5K_INI_WRITE },
+ { 0x99ec, 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_PHY_SCLOCK, 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY_SDELAY, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000009b5, AR5K_INI_WRITE },
+ { 0xa23c, 0x93c889af, AR5K_INI_WRITE },
+ { AR5K_PHY_FAST_ADC, 0x00000001, AR5K_INI_WRITE },
+ { 0xa250, 0x0000a000, AR5K_INI_WRITE },
+ { AR5K_PHY_BLUETOOTH, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG1, 0x0cc75380, AR5K_INI_WRITE },
+ { 0xa25c, 0x0f0f0f01, AR5K_INI_WRITE },
+ { 0xa260, 0x5f690f01, AR5K_INI_WRITE },
+ { 0xa264, 0x00418a11, AR5K_INI_WRITE },
+ { 0xa268, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG5, 0x0c30c16a, AR5K_INI_WRITE },
+ { 0xa270, 0x00820820, AR5K_INI_WRITE },
+ { 0xa274, 0x001b7caa, AR5K_INI_WRITE },
+ { 0xa278, 0x1ce739ce, AR5K_INI_WRITE },
+ { 0xa27c, 0x051701ce, AR5K_INI_WRITE },
+ { 0xa300, 0x18010000, AR5K_INI_WRITE },
+ { 0xa304, 0x30032602, AR5K_INI_WRITE },
+ { 0xa308, 0x48073e06, AR5K_INI_WRITE },
+ { 0xa30c, 0x560b4c0a, AR5K_INI_WRITE },
+ { 0xa310, 0x641a600f, AR5K_INI_WRITE },
+ { 0xa314, 0x784f6e1b, AR5K_INI_WRITE },
+ { 0xa318, 0x868f7c5a, AR5K_INI_WRITE },
+ { 0xa31c, 0x8ecf865b, AR5K_INI_WRITE },
+ { 0xa320, 0x9d4f970f, AR5K_INI_WRITE },
+ { 0xa324, 0xa5cfa18f, AR5K_INI_WRITE },
+ { 0xa328, 0xb55faf1f, AR5K_INI_WRITE },
+ { 0xa32c, 0xbddfb99f, AR5K_INI_WRITE },
+ { 0xa330, 0xcd7fc73f, AR5K_INI_WRITE },
+ { 0xa334, 0xd5ffd1bf, AR5K_INI_WRITE },
+ { 0xa338, 0x00000000, AR5K_INI_WRITE },
+ { 0xa33c, 0x00000000, AR5K_INI_WRITE },
+ { 0xa340, 0x00000000, AR5K_INI_WRITE },
+ { 0xa344, 0x00000000, AR5K_INI_WRITE },
+ { 0xa348, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa34c, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa350, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa354, 0x0003ffff, AR5K_INI_WRITE },
+ { 0xa358, 0x79a8aa1f, AR5K_INI_WRITE },
+ { 0xa35c, 0x066c420f, AR5K_INI_WRITE },
+ { 0xa360, 0x0f282207, AR5K_INI_WRITE },
+ { 0xa364, 0x17601685, AR5K_INI_WRITE },
+ { 0xa368, 0x1f801104, AR5K_INI_WRITE },
+ { 0xa36c, 0x37a00c03, AR5K_INI_WRITE },
+ { 0xa370, 0x3fc40883, AR5K_INI_WRITE },
+ { 0xa374, 0x57c00803, AR5K_INI_WRITE },
+ { 0xa378, 0x5fd80682, AR5K_INI_WRITE },
+ { 0xa37c, 0x7fe00482, AR5K_INI_WRITE },
+ { 0xa380, 0x7f3c7bba, AR5K_INI_WRITE },
+ { 0xa384, 0xf3307ff0, AR5K_INI_WRITE },
+};
+
+/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
+/* XXX: a mode ? */
+static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_SETTLING,
+ { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
+ { AR5K_PHY_GAIN,
+ { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { AR5K_PHY_WEAK_OFDM_LOW_THR,
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_CCK_CROSSCORR,
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
+ { AR5K_PHY_CCK_RX_CTL_4,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0xa324,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa328,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa32c,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa330,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa334,
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+};
+
+static const struct ath5k_ini rf2425_ini_common_end[] = {
+ { AR5K_DCU_FP, 0x000003e0, AR5K_INI_WRITE },
+ { AR5K_SEQ_MASK, 0x0000000f, AR5K_INI_WRITE },
+ { 0x809c, 0x00000000, AR5K_INI_WRITE },
+ { 0x80a0, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_CTL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MIC_QOS_SEL, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_MISC_MODE, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_OFDM_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_CCK_FIL_CNT, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT1_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHYERR_CNT2_MASK, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_TSF_THRES, 0x00000000, AR5K_INI_WRITE },
+ { 0x8140, 0x800003f9, AR5K_INI_WRITE },
+ { 0x8144, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_AGC, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_ADC_CTL, 0x0000a000, AR5K_INI_WRITE },
+ { 0x983c, 0x00200400, AR5K_INI_WRITE },
+ { AR5K_PHY_GAIN_OFFSET, 0x1284233c, AR5K_INI_WRITE },
+ { AR5K_PHY_SCR, 0x0000001f, AR5K_INI_WRITE },
+ { AR5K_PHY_SLMT, 0x00000080, AR5K_INI_WRITE },
+ { AR5K_PHY_SCAL, 0x0000000e, AR5K_INI_WRITE },
+ { 0x9958, 0x00081fff, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_7, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_8, 0x02800000, AR5K_INI_WRITE },
+ { AR5K_PHY_TIMING_11, 0x00000000, AR5K_INI_WRITE },
+ { 0x99dc, 0xfebadbe8, AR5K_INI_WRITE },
+ { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000, AR5K_INI_WRITE },
+ { 0x99e4, 0xaaaaaaaa, AR5K_INI_WRITE },
+ { 0x99e8, 0x3c466478, AR5K_INI_WRITE },
+ { 0x99ec, 0x000000aa, AR5K_INI_WRITE },
+ { AR5K_PHY_SCLOCK, 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_PHY_SDELAY, 0x000000ff, AR5K_INI_WRITE },
+ { AR5K_PHY_SPENDING, 0x00000014, AR5K_INI_WRITE },
+ { AR5K_PHY_DAG_CCK_CTL, 0x000009b5, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE3, 0x20202020, AR5K_INI_WRITE },
+ { AR5K_PHY_TXPOWER_RATE4, 0x20202020, AR5K_INI_WRITE },
+ { 0xa23c, 0x93c889af, AR5K_INI_WRITE },
+ { AR5K_PHY_FAST_ADC, 0x00000001, AR5K_INI_WRITE },
+ { 0xa250, 0x0000a000, AR5K_INI_WRITE },
+ { AR5K_PHY_BLUETOOTH, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG1, 0x0cc75380, AR5K_INI_WRITE },
+ { 0xa25c, 0x0f0f0f01, AR5K_INI_WRITE },
+ { 0xa260, 0x5f690f01, AR5K_INI_WRITE },
+ { 0xa264, 0x00418a11, AR5K_INI_WRITE },
+ { 0xa268, 0x00000000, AR5K_INI_WRITE },
+ { AR5K_PHY_TPC_RG5, 0x0c30c166, AR5K_INI_WRITE },
+ { 0xa270, 0x00820820, AR5K_INI_WRITE },
+ { 0xa274, 0x081a3caa, AR5K_INI_WRITE },
+ { 0xa278, 0x1ce739ce, AR5K_INI_WRITE },
+ { 0xa27c, 0x051701ce, AR5K_INI_WRITE },
+ { 0xa300, 0x16010000, AR5K_INI_WRITE },
+ { 0xa304, 0x2c032402, AR5K_INI_WRITE },
+ { 0xa308, 0x48433e42, AR5K_INI_WRITE },
+ { 0xa30c, 0x5a0f500b, AR5K_INI_WRITE },
+ { 0xa310, 0x6c4b624a, AR5K_INI_WRITE },
+ { 0xa314, 0x7e8b748a, AR5K_INI_WRITE },
+ { 0xa318, 0x96cf8ccb, AR5K_INI_WRITE },
+ { 0xa31c, 0xa34f9d0f, AR5K_INI_WRITE },
+ { 0xa320, 0xa7cfa58f, AR5K_INI_WRITE },
+ { 0xa348, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa34c, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa350, 0x3fffffff, AR5K_INI_WRITE },
+ { 0xa354, 0x0003ffff, AR5K_INI_WRITE },
+ { 0xa358, 0x79a8aa1f, AR5K_INI_WRITE },
+ { 0xa35c, 0x066c420f, AR5K_INI_WRITE },
+ { 0xa360, 0x0f282207, AR5K_INI_WRITE },
+ { 0xa364, 0x17601685, AR5K_INI_WRITE },
+ { 0xa368, 0x1f801104, AR5K_INI_WRITE },
+ { 0xa36c, 0x37a00c03, AR5K_INI_WRITE },
+ { 0xa370, 0x3fc40883, AR5K_INI_WRITE },
+ { 0xa374, 0x57c00803, AR5K_INI_WRITE },
+ { 0xa378, 0x5fd80682, AR5K_INI_WRITE },
+ { 0xa37c, 0x7fe00482, AR5K_INI_WRITE },
+ { 0xa380, 0x7f3c7bba, AR5K_INI_WRITE },
+ { 0xa384, 0xf3307ff0, AR5K_INI_WRITE },
+};
+
+/*
+ * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
+ * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
+ */
+
+/* RF5111 Initial BaseBand Gain settings */
+static const struct ath5k_ini rf5111_ini_bbgain[] = {
+ { AR5K_BB_GAIN(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(1), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(2), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(3), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(4), 0x00000008, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(5), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(6), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(7), 0x00000024, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(8), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(9), 0x00000034, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(10), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(11), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(12), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(13), 0x00000022, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(14), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(15), 0x00000032, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(16), 0x0000000a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(17), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(18), 0x00000006, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(19), 0x00000026, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(20), 0x00000016, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(21), 0x00000036, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(22), 0x0000000e, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(23), 0x0000002e, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(24), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(25), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(26), 0x00000011, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(27), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(28), 0x00000009, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(29), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(30), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(31), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(32), 0x00000015, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(33), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(34), 0x0000000d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(35), 0x0000002d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(36), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(37), 0x00000023, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(38), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(39), 0x00000033, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(40), 0x0000000b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(41), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(42), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(43), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(44), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(45), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(46), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(47), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(48), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(49), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(50), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(51), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(52), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(53), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(54), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(55), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(56), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(57), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(58), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(59), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(60), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(61), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(62), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(63), 0x00000016, AR5K_INI_WRITE },
+};
+
+/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */
+static const struct ath5k_ini rf5112_ini_bbgain[] = {
+ { AR5K_BB_GAIN(0), 0x00000000, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(1), 0x00000001, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(2), 0x00000002, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(3), 0x00000003, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(4), 0x00000004, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(5), 0x00000005, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(6), 0x00000008, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(7), 0x00000009, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(8), 0x0000000a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(9), 0x0000000b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(10), 0x0000000c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(11), 0x0000000d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(12), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(13), 0x00000011, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(14), 0x00000012, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(15), 0x00000013, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(16), 0x00000014, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(17), 0x00000015, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(18), 0x00000018, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(19), 0x00000019, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(20), 0x0000001a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(21), 0x0000001b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(22), 0x0000001c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(23), 0x0000001d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(24), 0x00000020, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(25), 0x00000021, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(26), 0x00000022, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(27), 0x00000023, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(28), 0x00000024, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(29), 0x00000025, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(30), 0x00000028, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(31), 0x00000029, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(32), 0x0000002a, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(33), 0x0000002b, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(34), 0x0000002c, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(35), 0x0000002d, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(36), 0x00000030, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(37), 0x00000031, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(38), 0x00000032, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(39), 0x00000033, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(40), 0x00000034, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(41), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(42), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(43), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(44), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(45), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(46), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(47), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(48), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(49), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(50), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(51), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(52), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(53), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(54), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(55), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(56), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(57), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(58), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(59), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(60), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(61), 0x00000035, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(62), 0x00000010, AR5K_INI_WRITE },
+ { AR5K_BB_GAIN(63), 0x0000001a, AR5K_INI_WRITE },
+};
+
+
+/*
+ * Write initial register dump
+ */
+static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
+ const struct ath5k_ini *ini_regs, int change_channel)
+{
+ unsigned int i;
+
+ /* Write initial registers */
+ for (i = 0; i < size; i++) {
+ /* On channel change there is
+ * no need to mess with PCU */
+ if (change_channel &&
+ ini_regs[i].ini_register >= AR5K_PCU_MIN &&
+ ini_regs[i].ini_register <= AR5K_PCU_MAX)
+ continue;
+
+ switch (ini_regs[i].ini_mode) {
+ case AR5K_INI_READ:
+ /* Cleared on read */
+ ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
+ break;
+ case AR5K_INI_WRITE:
+ default:
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
+ ini_regs[i].ini_register);
+ }
+ }
+}
+
+static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
+ unsigned int size, const struct ath5k_ini_mode *ini_mode,
+ u8 mode)
+{
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
+ (u32)ini_mode[i].mode_register);
+ }
+}
+
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, int change_channel)
+{
+ /*
+ * Write initial register settings
+ */
+
+ /* For AR5212 and combatible */
+ if (ah->ah_version == AR5K_AR5212) {
+
+ /* First set of mode-specific settings */
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_ini_mode_start),
+ ar5212_ini_mode_start, mode);
+
+ /*
+ * Write initial settings common for all modes
+ */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
+ ar5212_ini_common_start, change_channel);
+
+ /* Second set of mode-specific settings */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5111_ini_mode_end),
+ rf5111_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5111_ini_common_end),
+ rf5111_ini_common_end, change_channel);
+
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
+
+ break;
+ case AR5K_RF5112:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5112_ini_mode_end),
+ rf5112_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_common_end),
+ rf5112_ini_common_end, change_channel);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+
+ break;
+ case AR5K_RF5413:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5413_ini_mode_end),
+ rf5413_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5413_ini_common_end),
+ rf5413_ini_common_end, change_channel);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+
+ break;
+ case AR5K_RF2316:
+ case AR5K_RF2413:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf2413_ini_mode_end),
+ rf2413_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf2413_ini_common_end),
+ rf2413_ini_common_end, change_channel);
+
+ /* Override settings from rf2413_ini_common_end */
+ if (ah->ah_radio == AR5K_RF2316) {
+ ath5k_hw_reg_write(ah, 0x00004000,
+ AR5K_PHY_AGC);
+ ath5k_hw_reg_write(ah, 0x081b7caa,
+ 0xa274);
+ }
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+ break;
+ case AR5K_RF2317:
+ case AR5K_RF2425:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf2425_ini_mode_end),
+ rf2425_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf2425_ini_common_end),
+ rf2425_ini_common_end, change_channel);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+ break;
+ default:
+ return -EINVAL;
+
+ }
+
+ /* For AR5211 */
+ } else if (ah->ah_version == AR5K_AR5211) {
+
+ /* AR5K_MODE_11B */
+ if (mode > 2) {
+ DBG("ath5k: unsupported channel mode %d\n", mode);
+ return -EINVAL;
+ }
+
+ /* Mode-specific settings */
+ ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
+ ar5211_ini_mode, mode);
+
+ /*
+ * Write initial settings common for all modes
+ */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
+ ar5211_ini, change_channel);
+
+ /* AR5211 only comes with 5111 */
+
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
+ /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
+ } else if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
+ ar5210_ini, change_channel);
+ }
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_pcu.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_pcu.c
new file mode 100644
index 0000000..1e90a94
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_pcu.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/*********************************\
+* Protocol Control Unit Functions *
+\*********************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*******************\
+* Generic functions *
+\*******************/
+
+/**
+ * ath5k_hw_set_opmode - Set PCU operating mode
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Initialize PCU for the various operating modes (AP/STA etc)
+ *
+ * For gPXE we always assume STA mode.
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
+{
+ u32 pcu_reg, beacon_reg, low_id, high_id;
+
+
+ /* Preserve rest settings */
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+ pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+ | AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
+ beacon_reg = 0;
+
+ pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_PWR_SV : 0);
+
+ /*
+ * Set PCU registers
+ */
+ low_id = AR5K_LOW_ID(ah->ah_sta_id);
+ high_id = AR5K_HIGH_ID(ah->ah_sta_id);
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ /*
+ * Set Beacon Control Register on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ *
+ * @ah: The &struct ath5k_hw
+ * @high: Flag to determine if we want to use high transmition rate
+ * for ACKs or not
+ *
+ * If high flag is set, we tell hw to use a set of control rates based on
+ * the current transmition rate (check out control_rates array inside reset.c).
+ * If not hw just uses the lowest rate available for the current modulation
+ * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
+ */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, int high)
+{
+ if (ah->ah_version != AR5K_AR5212)
+ return;
+ else {
+ u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+ if (high)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+ }
+}
+
+
+/******************\
+* ACK/CTS Timeouts *
+\******************/
+
+/**
+ * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
+{
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
+{
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+
+/****************\
+* BSSID handling *
+\****************/
+
+/**
+ * ath5k_hw_get_lladdr - Get station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Initialize ah->ah_sta_id using the mac address provided
+ * (just a memcpy).
+ *
+ * TODO: Remove it once we merge ath5k_softc and ath5k_hw
+ */
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
+{
+ memcpy(mac, ah->ah_sta_id, ETH_ALEN);
+}
+
+/**
+ * ath5k_hw_set_lladdr - Set station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Set station id on hw using the provided mac address
+ */
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
+{
+ u32 low_id, high_id;
+ u32 pcu_reg;
+
+ /* Set new station ID */
+ memcpy(ah->ah_sta_id, mac, ETH_ALEN);
+
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+
+ low_id = AR5K_LOW_ID(mac);
+ high_id = AR5K_HIGH_ID(mac);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_set_associd - Set BSSID for association
+ *
+ * @ah: The &struct ath5k_hw
+ * @bssid: BSSID
+ * @assoc_id: Assoc id
+ *
+ * Sets the BSSID which trigers the "SME Join" operation
+ */
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+{
+ u32 low_id, high_id;
+
+ /*
+ * Set simple BSSID mask on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
+ AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
+ AR5K_BSS_IDM1);
+ }
+
+ /*
+ * Set BSSID which triggers the "SME Join" operation
+ */
+ low_id = AR5K_LOW_ID(bssid);
+ high_id = AR5K_HIGH_ID(bssid);
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
+ ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
+ AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
+}
+
+/**
+ * ath5k_hw_set_bssid_mask - filter out bssids we listen
+ *
+ * @ah: the &struct ath5k_hw
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
+ *
+ * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
+ * which bits of the interface's MAC address should be looked at when trying
+ * to decide which packets to ACK. In station mode and AP mode with a single
+ * BSS every bit matters since we lock to only one BSS. In AP mode with
+ * multiple BSSes (virtual interfaces) not every bit matters because hw must
+ * accept frames for all BSSes and so we tweak some bits of our mac address
+ * in order to have multiple BSSes.
+ *
+ * NOTE: This is a simple filter and does *not* filter out all
+ * relevant frames. Some frames that are not for us might get ACKed from us
+ * by PCU because they just match the mask.
+ *
+ * When handling multiple BSSes you can get the BSSID mask by computing the
+ * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
+ *
+ * When you do this you are essentially computing the common bits of all your
+ * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
+ * the MAC address to obtain the relevant bits and compare the result with
+ * (frame's BSSID & mask) to see if they match.
+ */
+/*
+ * Simple example: on your card you have have two BSSes you have created with
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
+ *
+ * \
+ * MAC: 0001 |
+ * BSSID-01: 0100 | --> Belongs to us
+ * BSSID-02: 1001 |
+ * /
+ * -------------------
+ * BSSID-03: 0110 | --> External
+ * -------------------
+ *
+ * Our bssid_mask would then be:
+ *
+ * On loop iteration for BSSID-01:
+ * ~(0001 ^ 0100) -> ~(0101)
+ * -> 1010
+ * bssid_mask = 1010
+ *
+ * On loop iteration for BSSID-02:
+ * bssid_mask &= ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(1001)
+ * bssid_mask = (1010) & (0110)
+ * bssid_mask = 0010
+ *
+ * A bssid_mask of 0010 means "only pay attention to the second least
+ * significant bit". This is because its the only bit common
+ * amongst the MAC and all BSSIDs we support. To findout what the real
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
+ * or our MAC address (we assume the hardware uses the MAC address).
+ *
+ * Now, suppose there's an incoming frame for BSSID-03:
+ *
+ * IFRAME-01: 0110
+ *
+ * An easy eye-inspeciton of this already should tell you that this frame
+ * will not pass our check. This is beacuse the bssid_mask tells the
+ * hardware to only look at the second least significant bit and the
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
+ * as 1, which does not match 0.
+ *
+ * So with IFRAME-01 we *assume* the hardware will do:
+ *
+ * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
+ * --> allow = (0010) == 0000 ? 1 : 0;
+ * --> allow = 0
+ *
+ * Lets now test a frame that should work:
+ *
+ * IFRAME-02: 0001 (we should allow)
+ *
+ * allow = (0001 & 1010) == 1010
+ *
+ * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
+ * --> allow = (0010) == (0010)
+ * --> allow = 1
+ *
+ * Other examples:
+ *
+ * IFRAME-03: 0100 --> allowed
+ * IFRAME-04: 1001 --> allowed
+ * IFRAME-05: 1101 --> allowed but its not for us!!!
+ *
+ */
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
+{
+ u32 low_id, high_id;
+
+ /* Cache bssid mask so that we can restore it
+ * on reset */
+ memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
+ if (ah->ah_version == AR5K_AR5212) {
+ low_id = AR5K_LOW_ID(mask);
+ high_id = AR5K_HIGH_ID(mask);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
+
+ return 0;
+ }
+
+ return -EIO;
+}
+
+
+/************\
+* RX Control *
+\************/
+
+/**
+ * ath5k_hw_start_rx_pcu - Start RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Starts RX engine on PCU so that hw can process RXed frames
+ * (ACK etc).
+ *
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
+ * TODO: Init ANI here
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * at5k_hw_stop_rx_pcu - Stop RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stops RX engine on PCU
+ *
+ * TODO: Detach ANI here
+ */
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
+{
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Set multicast filter
+ */
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
+{
+ /* Set the multicat filter */
+ ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
+ ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
+}
+
+/**
+ * ath5k_hw_get_rx_filter - Get current rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns the RX filter by reading rx filter and
+ * phy error filter registers. RX filter is used
+ * to set the allowed frame types that PCU will accept
+ * and pass to the driver. For a list of frame types
+ * check out reg.h.
+ */
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
+{
+ u32 data, filter = 0;
+
+ filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
+
+ /*Radar detection for 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
+
+ if (data & AR5K_PHY_ERR_FIL_RADAR)
+ filter |= AR5K_RX_FILTER_RADARERR;
+ if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
+ filter |= AR5K_RX_FILTER_PHYERR;
+ }
+
+ return filter;
+}
+
+/**
+ * ath5k_hw_set_rx_filter - Set rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ * @filter: RX filter mask (see reg.h)
+ *
+ * Sets RX filter register and also handles PHY error filter
+ * register on 5212 and newer chips so that we have proper PHY
+ * error reporting.
+ */
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
+{
+ u32 data = 0;
+
+ /* Set PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ if (filter & AR5K_RX_FILTER_RADARERR)
+ data |= AR5K_PHY_ERR_FIL_RADAR;
+ if (filter & AR5K_RX_FILTER_PHYERR)
+ data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
+ }
+
+ /*
+ * The AR5210 uses promiscous mode to detect radar activity
+ */
+ if (ah->ah_version == AR5K_AR5210 &&
+ (filter & AR5K_RX_FILTER_RADARERR)) {
+ filter &= ~AR5K_RX_FILTER_RADARERR;
+ filter |= AR5K_RX_FILTER_PROM;
+ }
+
+ /*Zero length DMA (phy error reporting) */
+ if (data)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+
+ /*Write RX Filter register*/
+ ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
+
+ /*Write PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
+
+}
+
+/*********************\
+* Key table functions *
+\*********************/
+
+/*
+ * Reset a key entry on the table
+ */
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+{
+ unsigned int i, type;
+ u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
+
+ type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
+
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+
+ /* Reset associated MIC entry if TKIP
+ * is enabled located at offset (entry + 64) */
+ if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+ for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
+ ath5k_hw_reg_write(ah, 0,
+ AR5K_KEYTABLE_OFF(micentry, i));
+ }
+
+ /*
+ * Set NULL encryption on AR5212+
+ *
+ * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
+ * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
+ *
+ * Note2: Windows driver (ndiswrapper) sets this to
+ * 0x00000714 instead of 0x00000007
+ */
+ if (ah->ah_version > AR5K_AR5211) {
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(entry));
+
+ if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(micentry));
+ }
+ }
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_phy.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_phy.c
new file mode 100644
index 0000000..8856fa3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_phy.c
@@ -0,0 +1,2586 @@
+/*
+ * PHY functions
+ *
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+#define _ATH5K_PHY
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+#include "rfbuffer.h"
+#include "rfgain.h"
+
+static inline int min(int x, int y)
+{
+ return (x < y) ? x : y;
+}
+
+static inline int max(int x, int y)
+{
+ return (x > y) ? x : y;
+}
+
+/*
+ * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
+ */
+static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
+ const struct ath5k_rf_reg *rf_regs,
+ u32 val, u8 reg_id, int set)
+{
+ const struct ath5k_rf_reg *rfreg = NULL;
+ u8 offset, bank, num_bits, col, position;
+ u16 entry;
+ u32 mask, data, last_bit, bits_shifted, first_bit;
+ u32 *rfb;
+ s32 bits_left;
+ unsigned i;
+
+ data = 0;
+ rfb = ah->ah_rf_banks;
+
+ for (i = 0; i < ah->ah_rf_regs_count; i++) {
+ if (rf_regs[i].index == reg_id) {
+ rfreg = &rf_regs[i];
+ break;
+ }
+ }
+
+ if (rfb == NULL || rfreg == NULL) {
+ DBG("ath5k: RF register not found!\n");
+ /* should not happen */
+ return 0;
+ }
+
+ bank = rfreg->bank;
+ num_bits = rfreg->field.len;
+ first_bit = rfreg->field.pos;
+ col = rfreg->field.col;
+
+ /* first_bit is an offset from bank's
+ * start. Since we have all banks on
+ * the same array, we use this offset
+ * to mark each bank's start */
+ offset = ah->ah_offset[bank];
+
+ /* Boundary check */
+ if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
+ DBG("ath5k: RF invalid values at offset %d\n", offset);
+ return 0;
+ }
+
+ entry = ((first_bit - 1) / 8) + offset;
+ position = (first_bit - 1) % 8;
+
+ if (set)
+ data = ath5k_hw_bitswap(val, num_bits);
+
+ for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
+ position = 0, entry++) {
+
+ last_bit = (position + bits_left > 8) ? 8 :
+ position + bits_left;
+
+ mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
+ (col * 8);
+
+ if (set) {
+ rfb[entry] &= ~mask;
+ rfb[entry] |= ((data << position) << (col * 8)) & mask;
+ data >>= (8 - position);
+ } else {
+ data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
+ << bits_shifted;
+ bits_shifted += last_bit - position;
+ }
+
+ bits_left -= 8 - position;
+ }
+
+ data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
+
+ return data;
+}
+
+/**********************\
+* RF Gain optimization *
+\**********************/
+
+/*
+ * This code is used to optimize rf gain on different environments
+ * (temprature mostly) based on feedback from a power detector.
+ *
+ * It's only used on RF5111 and RF5112, later RF chips seem to have
+ * auto adjustment on hw -notice they have a much smaller BANK 7 and
+ * no gain optimization ladder-.
+ *
+ * For more infos check out this patent doc
+ * http://www.freepatentsonline.com/7400691.html
+ *
+ * This paper describes power drops as seen on the receiver due to
+ * probe packets
+ * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues
+ * %20of%20Power%20Control.pdf
+ *
+ * And this is the MadWiFi bug entry related to the above
+ * http://madwifi-project.org/ticket/1659
+ * with various measurements and diagrams
+ *
+ * TODO: Deal with power drops due to probes by setting an apropriate
+ * tx power on the probe packets ! Make this part of the calibration process.
+ */
+
+/* Initialize ah_gain durring attach */
+int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
+{
+ /* Initialize the gain optimization values */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
+ ah->ah_gain.g_low = 20;
+ ah->ah_gain.g_high = 35;
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ break;
+ case AR5K_RF5112:
+ ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
+ ah->ah_gain.g_low = 20;
+ ah->ah_gain.g_high = 85;
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Schedule a gain probe check on the next transmited packet.
+ * That means our next packet is going to be sent with lower
+ * tx power and a Peak to Average Power Detector (PAPD) will try
+ * to measure the gain.
+ *
+ * TODO: Use propper tx power setting for the probe packet so
+ * that we don't observe a serious power drop on the receiver
+ *
+ * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc)
+ * just after we enable the probe so that we don't mess with
+ * standard traffic ? Maybe it's time to use sw interrupts and
+ * a probe tasklet !!!
+ */
+static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
+{
+
+ /* Skip if gain calibration is inactive or
+ * we already handle a probe request */
+ if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
+ return;
+
+ /* Send the packet with 2dB below max power as
+ * patent doc suggest */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4,
+ AR5K_PHY_PAPD_PROBE_TXPOWER) |
+ AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
+
+ ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
+
+}
+
+/* Calculate gain_F measurement correction
+ * based on the current step for RF5112 rev. 2 */
+static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
+{
+ u32 mix, step;
+ u32 *rf;
+ const struct ath5k_gain_opt *go;
+ const struct ath5k_gain_opt_step *g_step;
+ const struct ath5k_rf_reg *rf_regs;
+
+ /* Only RF5112 Rev. 2 supports it */
+ if ((ah->ah_radio != AR5K_RF5112) ||
+ (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
+ return 0;
+
+ go = &rfgain_opt_5112;
+ rf_regs = rf_regs_5112a;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
+
+ g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ if (ah->ah_rf_banks == NULL)
+ return 0;
+
+ rf = ah->ah_rf_banks;
+ ah->ah_gain.g_f_corr = 0;
+
+ /* No VGA (Variable Gain Amplifier) override, skip */
+ if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, 0) != 1)
+ return 0;
+
+ /* Mix gain stepping */
+ step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, 0);
+
+ /* Mix gain override */
+ mix = g_step->gos_param[0];
+
+ switch (mix) {
+ case 3:
+ ah->ah_gain.g_f_corr = step * 2;
+ break;
+ case 2:
+ ah->ah_gain.g_f_corr = (step - 5) * 2;
+ break;
+ case 1:
+ ah->ah_gain.g_f_corr = step;
+ break;
+ default:
+ ah->ah_gain.g_f_corr = 0;
+ break;
+ }
+
+ return ah->ah_gain.g_f_corr;
+}
+
+/* Check if current gain_F measurement is in the range of our
+ * power detector windows. If we get a measurement outside range
+ * we know it's not accurate (detectors can't measure anything outside
+ * their detection window) so we must ignore it */
+static int ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
+{
+ const struct ath5k_rf_reg *rf_regs;
+ u32 step, mix_ovr, level[4];
+ u32 *rf;
+
+ if (ah->ah_rf_banks == NULL)
+ return 0;
+
+ rf = ah->ah_rf_banks;
+
+ if (ah->ah_radio == AR5K_RF5111) {
+
+ rf_regs = rf_regs_5111;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
+
+ step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP,
+ 0);
+
+ level[0] = 0;
+ level[1] = (step == 63) ? 50 : step + 4;
+ level[2] = (step != 63) ? 64 : level[0];
+ level[3] = level[2] + 50 ;
+
+ ah->ah_gain.g_high = level[3] -
+ (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
+ ah->ah_gain.g_low = level[0] +
+ (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
+ } else {
+
+ rf_regs = rf_regs_5112;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
+
+ mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
+ 0);
+
+ level[0] = level[2] = 0;
+
+ if (mix_ovr == 1) {
+ level[1] = level[3] = 83;
+ } else {
+ level[1] = level[3] = 107;
+ ah->ah_gain.g_high = 55;
+ }
+ }
+
+ return (ah->ah_gain.g_current >= level[0] &&
+ ah->ah_gain.g_current <= level[1]) ||
+ (ah->ah_gain.g_current >= level[2] &&
+ ah->ah_gain.g_current <= level[3]);
+}
+
+/* Perform gain_F adjustment by choosing the right set
+ * of parameters from rf gain optimization ladder */
+static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
+{
+ const struct ath5k_gain_opt *go;
+ const struct ath5k_gain_opt_step *g_step;
+ int ret = 0;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ go = &rfgain_opt_5111;
+ break;
+ case AR5K_RF5112:
+ go = &rfgain_opt_5112;
+ break;
+ default:
+ return 0;
+ }
+
+ g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
+
+ /* Reached maximum */
+ if (ah->ah_gain.g_step_idx == 0)
+ return -1;
+
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+ ah->ah_gain.g_target >= ah->ah_gain.g_high &&
+ ah->ah_gain.g_step_idx > 0;
+ g_step = &go->go_step[ah->ah_gain.g_step_idx])
+ ah->ah_gain.g_target -= 2 *
+ (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
+ g_step->gos_gain);
+
+ ret = 1;
+ goto done;
+ }
+
+ if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
+
+ /* Reached minimum */
+ if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
+ return -2;
+
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+ ah->ah_gain.g_target <= ah->ah_gain.g_low &&
+ ah->ah_gain.g_step_idx < go->go_steps_count-1;
+ g_step = &go->go_step[ah->ah_gain.g_step_idx])
+ ah->ah_gain.g_target -= 2 *
+ (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
+ g_step->gos_gain);
+
+ ret = 2;
+ goto done;
+ }
+
+done:
+ DBG2("ath5k RF adjust: ret %d, gain step %d, current gain %d, "
+ "target gain %d\n", ret, ah->ah_gain.g_step_idx,
+ ah->ah_gain.g_current, ah->ah_gain.g_target);
+
+ return ret;
+}
+
+/* Main callback for thermal rf gain calibration engine
+ * Check for a new gain reading and schedule an adjustment
+ * if needed.
+ *
+ * TODO: Use sw interrupt to schedule reset if gain_F needs
+ * adjustment */
+enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
+{
+ u32 data, type;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+
+ if (ah->ah_rf_banks == NULL ||
+ ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
+ return AR5K_RFGAIN_INACTIVE;
+
+ /* No check requested, either engine is inactive
+ * or an adjustment is already requested */
+ if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
+ goto done;
+
+ /* Read the PAPD (Peak to Average Power Detector)
+ * register */
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
+
+ /* No probe is scheduled, read gain_F measurement */
+ if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
+ ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
+ type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
+
+ /* If tx packet is CCK correct the gain_F measurement
+ * by cck ofdm gain delta */
+ if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) {
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
+ ah->ah_gain.g_current +=
+ ee->ee_cck_ofdm_gain_delta;
+ else
+ ah->ah_gain.g_current +=
+ AR5K_GAIN_CCK_PROBE_CORR;
+ }
+
+ /* Further correct gain_F measurement for
+ * RF5112A radios */
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+ ath5k_hw_rf_gainf_corr(ah);
+ ah->ah_gain.g_current =
+ ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
+ (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+ 0;
+ }
+
+ /* Check if measurement is ok and if we need
+ * to adjust gain, schedule a gain adjustment,
+ * else switch back to the acive state */
+ if (ath5k_hw_rf_check_gainf_readback(ah) &&
+ AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
+ ath5k_hw_rf_gainf_adjust(ah)) {
+ ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
+ } else {
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ }
+ }
+
+done:
+ return ah->ah_gain.g_state;
+}
+
+/* Write initial rf gain table to set the RF sensitivity
+ * this one works on all RF chips and has nothing to do
+ * with gain_F calibration */
+int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
+{
+ const struct ath5k_ini_rfgain *ath5k_rfg;
+ unsigned int i, size;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ath5k_rfg = rfgain_5111;
+ size = ARRAY_SIZE(rfgain_5111);
+ break;
+ case AR5K_RF5112:
+ ath5k_rfg = rfgain_5112;
+ size = ARRAY_SIZE(rfgain_5112);
+ break;
+ case AR5K_RF2413:
+ ath5k_rfg = rfgain_2413;
+ size = ARRAY_SIZE(rfgain_2413);
+ break;
+ case AR5K_RF2316:
+ ath5k_rfg = rfgain_2316;
+ size = ARRAY_SIZE(rfgain_2316);
+ break;
+ case AR5K_RF5413:
+ ath5k_rfg = rfgain_5413;
+ size = ARRAY_SIZE(rfgain_5413);
+ break;
+ case AR5K_RF2317:
+ case AR5K_RF2425:
+ ath5k_rfg = rfgain_2425;
+ size = ARRAY_SIZE(rfgain_2425);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case AR5K_INI_RFGAIN_2GHZ:
+ case AR5K_INI_RFGAIN_5GHZ:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
+ (u32)ath5k_rfg[i].rfg_register);
+ }
+
+ return 0;
+}
+
+
+
+/********************\
+* RF Registers setup *
+\********************/
+
+
+/*
+ * Setup RF registers by writing rf buffer on hw
+ */
+int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct net80211_channel *channel,
+ unsigned int mode)
+{
+ const struct ath5k_rf_reg *rf_regs;
+ const struct ath5k_ini_rfbuffer *ini_rfb;
+ const struct ath5k_gain_opt *go = NULL;
+ const struct ath5k_gain_opt_step *g_step;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u8 ee_mode = 0;
+ u32 *rfb;
+ int obdb = -1, bank = -1;
+ unsigned i;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ rf_regs = rf_regs_5111;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
+ ini_rfb = rfb_5111;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
+ go = &rfgain_opt_5111;
+ break;
+ case AR5K_RF5112:
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+ rf_regs = rf_regs_5112a;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
+ ini_rfb = rfb_5112a;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
+ } else {
+ rf_regs = rf_regs_5112;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
+ ini_rfb = rfb_5112;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
+ }
+ go = &rfgain_opt_5112;
+ break;
+ case AR5K_RF2413:
+ rf_regs = rf_regs_2413;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
+ ini_rfb = rfb_2413;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
+ break;
+ case AR5K_RF2316:
+ rf_regs = rf_regs_2316;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
+ ini_rfb = rfb_2316;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
+ break;
+ case AR5K_RF5413:
+ rf_regs = rf_regs_5413;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
+ ini_rfb = rfb_5413;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
+ break;
+ case AR5K_RF2317:
+ rf_regs = rf_regs_2425;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
+ ini_rfb = rfb_2317;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
+ break;
+ case AR5K_RF2425:
+ rf_regs = rf_regs_2425;
+ ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
+ if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
+ ini_rfb = rfb_2425;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
+ } else {
+ ini_rfb = rfb_2417;
+ ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* If it's the first time we set rf buffer, allocate
+ * ah->ah_rf_banks based on ah->ah_rf_banks_size
+ * we set above */
+ if (ah->ah_rf_banks == NULL) {
+ ah->ah_rf_banks = malloc(sizeof(u32) * ah->ah_rf_banks_size);
+ if (ah->ah_rf_banks == NULL) {
+ return -ENOMEM;
+ }
+ }
+
+ /* Copy values to modify them */
+ rfb = ah->ah_rf_banks;
+
+ for (i = 0; i < ah->ah_rf_banks_size; i++) {
+ if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
+ DBG("ath5k: invalid RF register bank\n");
+ return -EINVAL;
+ }
+
+ /* Bank changed, write down the offset */
+ if (bank != ini_rfb[i].rfb_bank) {
+ bank = ini_rfb[i].rfb_bank;
+ ah->ah_offset[bank] = i;
+ }
+
+ rfb[i] = ini_rfb[i].rfb_mode_data[mode];
+ }
+
+ /* Set Output and Driver bias current (OB/DB) */
+ if (channel->hw_value & CHANNEL_2GHZ) {
+
+ if (channel->hw_value & CHANNEL_CCK)
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ else
+ ee_mode = AR5K_EEPROM_MODE_11G;
+
+ /* For RF511X/RF211X combination we
+ * use b_OB and b_DB parameters stored
+ * in eeprom on ee->ee_ob[ee_mode][0]
+ *
+ * For all other chips we use OB/DB for 2Ghz
+ * stored in the b/g modal section just like
+ * 802.11a on ee->ee_ob[ee_mode][1] */
+ if ((ah->ah_radio == AR5K_RF5111) ||
+ (ah->ah_radio == AR5K_RF5112))
+ obdb = 0;
+ else
+ obdb = 1;
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
+ AR5K_RF_OB_2GHZ, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
+ AR5K_RF_DB_2GHZ, 1);
+
+ /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
+ } else if ((channel->hw_value & CHANNEL_5GHZ) ||
+ (ah->ah_radio == AR5K_RF5111)) {
+
+ /* For 11a, Turbo and XR we need to choose
+ * OB/DB based on frequency range */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ obdb = channel->center_freq >= 5725 ? 3 :
+ (channel->center_freq >= 5500 ? 2 :
+ (channel->center_freq >= 5260 ? 1 :
+ (channel->center_freq > 4000 ? 0 : -1)));
+
+ if (obdb < 0)
+ return -EINVAL;
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
+ AR5K_RF_OB_5GHZ, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
+ AR5K_RF_DB_5GHZ, 1);
+ }
+
+ g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ /* Bank Modifications (chip-specific) */
+ if (ah->ah_radio == AR5K_RF5111) {
+
+ /* Set gain_F settings according to current step */
+ if (channel->hw_value & CHANNEL_OFDM) {
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
+ AR5K_PHY_FRAME_CTL_TX_CLIP,
+ g_step->gos_param[0]);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
+ AR5K_RF_PWD_90, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
+ AR5K_RF_PWD_84, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
+ AR5K_RF_RFGAIN_SEL, 1);
+
+ /* We programmed gain_F parameters, switch back
+ * to active state */
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+
+ }
+
+ /* Bank 6/7 setup */
+
+ ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
+ AR5K_RF_PWD_XPD, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
+ AR5K_RF_XPD_GAIN, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
+ AR5K_RF_GAIN_I, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
+ AR5K_RF_PLO_SEL, 1);
+
+ /* TODO: Half/quarter channel support */
+ }
+
+ if (ah->ah_radio == AR5K_RF5112) {
+
+ /* Set gain_F settings according to current step */
+ if (channel->hw_value & CHANNEL_OFDM) {
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
+ AR5K_RF_MIXGAIN_OVR, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
+ AR5K_RF_PWD_138, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
+ AR5K_RF_PWD_137, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
+ AR5K_RF_PWD_136, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
+ AR5K_RF_PWD_132, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
+ AR5K_RF_PWD_131, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
+ AR5K_RF_PWD_130, 1);
+
+ /* We programmed gain_F parameters, switch back
+ * to active state */
+ ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+ }
+
+ /* Bank 6/7 setup */
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
+ AR5K_RF_XPD_SEL, 1);
+
+ if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
+ /* Rev. 1 supports only one xpd */
+ ath5k_hw_rfb_op(ah, rf_regs,
+ ee->ee_x_gain[ee_mode],
+ AR5K_RF_XPD_GAIN, 1);
+
+ } else {
+ /* TODO: Set high and low gain bits */
+ ath5k_hw_rfb_op(ah, rf_regs,
+ ee->ee_x_gain[ee_mode],
+ AR5K_RF_PD_GAIN_LO, 1);
+ ath5k_hw_rfb_op(ah, rf_regs,
+ ee->ee_x_gain[ee_mode],
+ AR5K_RF_PD_GAIN_HI, 1);
+
+ /* Lower synth voltage on Rev 2 */
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_HIGH_VC_CP, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_MID_VC_CP, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_LOW_VC_CP, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 2,
+ AR5K_RF_PUSH_UP, 1);
+
+ /* Decrease power consumption on 5213+ BaseBand */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_PAD2GND, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_XB2_LVL, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_XB5_LVL, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_PWD_167, 1);
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1,
+ AR5K_RF_PWD_166, 1);
+ }
+ }
+
+ ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
+ AR5K_RF_GAIN_I, 1);
+
+ /* TODO: Half/quarter channel support */
+
+ }
+
+ if (ah->ah_radio == AR5K_RF5413 &&
+ channel->hw_value & CHANNEL_2GHZ) {
+
+ ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
+ 1);
+
+ /* Set optimum value for early revisions (on pci-e chips) */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
+ ah->ah_mac_srev < AR5K_SREV_AR5413)
+ ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
+ AR5K_RF_PWD_ICLOBUF_2G, 1);
+
+ }
+
+ /* Write RF banks on hw */
+ for (i = 0; i < ah->ah_rf_banks_size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
+ }
+
+ return 0;
+}
+
+
+/**************************\
+ PHY/RF channel functions
+\**************************/
+
+/*
+ * Check if a channel is supported
+ */
+int ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+{
+ /* Check if the channel is in our supported range */
+ if (flags & CHANNEL_2GHZ) {
+ if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
+ return 1;
+ } else if (flags & CHANNEL_5GHZ)
+ if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Convertion needed for RF5110
+ */
+static u32 ath5k_hw_rf5110_chan2athchan(struct net80211_channel *channel)
+{
+ u32 athchan;
+
+ /*
+ * Convert IEEE channel/MHz to an internal channel value used
+ * by the AR5210 chipset. This has not been verified with
+ * newer chipsets like the AR5212A who have a completely
+ * different RF/PHY part.
+ */
+ athchan = (ath5k_hw_bitswap((ath5k_freq_to_channel(channel->center_freq)
+ - 24) / 2, 5) << 1)
+ | (1 << 6) | 0x1;
+ return athchan;
+}
+
+/*
+ * Set channel on RF5110
+ */
+static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 data;
+
+ /*
+ * Set the channel and wait
+ */
+ data = ath5k_hw_rf5110_chan2athchan(channel);
+ ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
+ mdelay(1);
+
+ return 0;
+}
+
+/*
+ * Convertion needed for 5111
+ */
+static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
+ struct ath5k_athchan_2ghz *athchan)
+{
+ int channel;
+
+ /* Cast this value to catch negative channel numbers (>= -19) */
+ channel = (int)ieee;
+
+ /*
+ * Map 2GHz IEEE channel to 5GHz Atheros channel
+ */
+ if (channel <= 13) {
+ athchan->a2_athchan = 115 + channel;
+ athchan->a2_flags = 0x46;
+ } else if (channel == 14) {
+ athchan->a2_athchan = 124;
+ athchan->a2_flags = 0x44;
+ } else if (channel >= 15 && channel <= 26) {
+ athchan->a2_athchan = ((channel - 14) * 4) + 132;
+ athchan->a2_flags = 0x46;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Set channel on 5111
+ */
+static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ struct ath5k_athchan_2ghz ath5k_channel_2ghz;
+ unsigned int ath5k_channel = ath5k_freq_to_channel(channel->center_freq);
+ u32 data0, data1, clock;
+ int ret;
+
+ /*
+ * Set the channel on the RF5111 radio
+ */
+ data0 = data1 = 0;
+
+ if (channel->hw_value & CHANNEL_2GHZ) {
+ /* Map 2GHz channel to 5GHz Atheros channel ID */
+ ret = ath5k_hw_rf5111_chan2athchan(ath5k_channel,
+ &ath5k_channel_2ghz);
+ if (ret)
+ return ret;
+
+ ath5k_channel = ath5k_channel_2ghz.a2_athchan;
+ data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
+ << 5) | (1 << 4);
+ }
+
+ if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
+ clock = 1;
+ data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
+ (clock << 1) | (1 << 10) | 1;
+ } else {
+ clock = 0;
+ data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
+ << 2) | (clock << 1) | (1 << 10) | 1;
+ }
+
+ ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
+ AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
+ AR5K_RF_BUFFER_CONTROL_3);
+
+ return 0;
+}
+
+/*
+ * Set channel on 5112 and newer
+ */
+static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 data, data0, data1, data2;
+ u16 c;
+
+ data = data0 = data1 = data2 = 0;
+ c = channel->center_freq;
+
+ if (c < 4800) {
+ if (!((c - 2224) % 5)) {
+ data0 = ((2 * (c - 704)) - 3040) / 10;
+ data1 = 1;
+ } else if (!((c - 2192) % 5)) {
+ data0 = ((2 * (c - 672)) - 3040) / 10;
+ data1 = 0;
+ } else
+ return -EINVAL;
+
+ data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
+ } else if ((c - (c % 5)) != 2 || c > 5435) {
+ if (!(c % 20) && c >= 5120) {
+ data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+ data2 = ath5k_hw_bitswap(3, 2);
+ } else if (!(c % 10)) {
+ data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+ data2 = ath5k_hw_bitswap(2, 2);
+ } else if (!(c % 5)) {
+ data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+ data2 = ath5k_hw_bitswap(1, 2);
+ } else
+ return -EINVAL;
+ } else {
+ data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+ data2 = ath5k_hw_bitswap(0, 2);
+ }
+
+ data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
+
+ ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+ return 0;
+}
+
+/*
+ * Set the channel on the RF2425
+ */
+static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 data, data0, data2;
+ u16 c;
+
+ data = data0 = data2 = 0;
+ c = channel->center_freq;
+
+ if (c < 4800) {
+ data0 = ath5k_hw_bitswap((c - 2272), 8);
+ data2 = 0;
+ /* ? 5GHz ? */
+ } else if ((c - (c % 5)) != 2 || c > 5435) {
+ if (!(c % 20) && c < 5120)
+ data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+ else if (!(c % 10))
+ data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+ else if (!(c % 5))
+ data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+ else
+ return -EINVAL;
+ data2 = ath5k_hw_bitswap(1, 2);
+ } else {
+ data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+ data2 = ath5k_hw_bitswap(0, 2);
+ }
+
+ data = (data0 << 4) | data2 << 2 | 0x1001;
+
+ ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+ return 0;
+}
+
+/*
+ * Set a channel on the radio chip
+ */
+int ath5k_hw_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
+{
+ int ret;
+ /*
+ * Check bounds supported by the PHY (we don't care about regultory
+ * restrictions at this point). Note: hw_value already has the band
+ * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
+ * of the band by that */
+ if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
+ DBG("ath5k: channel frequency (%d MHz) out of supported "
+ "range\n", channel->center_freq);
+ return -EINVAL;
+ }
+
+ /*
+ * Set the channel and wait
+ */
+ switch (ah->ah_radio) {
+ case AR5K_RF5110:
+ ret = ath5k_hw_rf5110_channel(ah, channel);
+ break;
+ case AR5K_RF5111:
+ ret = ath5k_hw_rf5111_channel(ah, channel);
+ break;
+ case AR5K_RF2425:
+ ret = ath5k_hw_rf2425_channel(ah, channel);
+ break;
+ default:
+ ret = ath5k_hw_rf5112_channel(ah, channel);
+ break;
+ }
+
+ if (ret) {
+ DBG("ath5k: setting channel failed: %s\n", strerror(ret));
+ return ret;
+ }
+
+ /* Set JAPAN setting for channel 14 */
+ if (channel->center_freq == 2484) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
+ AR5K_PHY_CCKTXCTL_JAPAN);
+ } else {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
+ AR5K_PHY_CCKTXCTL_WORLD);
+ }
+
+ ah->ah_current_channel = channel;
+ ah->ah_turbo = (channel->hw_value == CHANNEL_T ? 1 : 0);
+
+ return 0;
+}
+
+/*****************\
+ PHY calibration
+\*****************/
+
+/**
+ * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
+ *
+ * @ah: struct ath5k_hw pointer we are operating on
+ * @freq: the channel frequency, just used for error logging
+ *
+ * This function performs a noise floor calibration of the PHY and waits for
+ * it to complete. Then the noise floor value is compared to some maximum
+ * noise floor we consider valid.
+ *
+ * Note that this is different from what the madwifi HAL does: it reads the
+ * noise floor and afterwards initiates the calibration. Since the noise floor
+ * calibration can take some time to finish, depending on the current channel
+ * use, that avoids the occasional timeout warnings we are seeing now.
+ *
+ * See the following link for an Atheros patent on noise floor calibration:
+ * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
+ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
+ *
+ * XXX: Since during noise floor calibration antennas are detached according to
+ * the patent, we should stop tx queues here.
+ */
+int
+ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
+{
+ int ret;
+ unsigned int i;
+ s32 noise_floor;
+
+ /*
+ * Enable noise floor calibration
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_NF);
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_NF, 0, 0);
+
+ if (ret) {
+ DBG("ath5k: noise floor calibration timeout (%d MHz)\n", freq);
+ return -EAGAIN;
+ }
+
+ /* Wait until the noise floor is calibrated and read the value */
+ for (i = 20; i > 0; i--) {
+ mdelay(1);
+ noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
+ noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
+ if (noise_floor & AR5K_PHY_NF_ACTIVE) {
+ noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
+
+ if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
+ break;
+ }
+ }
+
+ DBG2("ath5k: noise floor %d\n", noise_floor);
+
+ if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
+ DBG("ath5k: noise floor calibration failed (%d MHz)\n", freq);
+ return -EAGAIN;
+ }
+
+ ah->ah_noise_floor = noise_floor;
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5110
+ * -Fix BPSK/QAM Constellation (I/Q correction)
+ * -Calculate Noise Floor
+ */
+static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 phy_sig, phy_agc, phy_sat, beacon;
+ int ret;
+
+ /*
+ * Disable beacons and RX/TX queues, wait
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
+ ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
+
+ mdelay(2);
+
+ /*
+ * Set the channel (with AGC turned off)
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+ udelay(10);
+ ret = ath5k_hw_channel(ah, channel);
+
+ /*
+ * Activate PHY and wait
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+ mdelay(1);
+
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+ if (ret)
+ return ret;
+
+ /*
+ * Calibrate the radio chip
+ */
+
+ /* Remember normal state */
+ phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
+ phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
+ phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
+
+ /* Update radio registers */
+ ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
+ AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
+
+ ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
+ AR5K_PHY_AGCCOARSE_LO)) |
+ AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
+ AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
+
+ ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
+ AR5K_PHY_ADCSAT_THR)) |
+ AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
+ AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
+
+ udelay(20);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+ udelay(10);
+ ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+ mdelay(1);
+
+ /*
+ * Enable calibration and wait until completion
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, 0);
+
+ /* Reset to normal state */
+ ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
+ ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
+ ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
+
+ if (ret) {
+ DBG("ath5k: calibration timeout (%d MHz)\n",
+ channel->center_freq);
+ return ret;
+ }
+
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+ /*
+ * Re-enable RX/TX and beacons
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5111/5112 and newer chips
+ */
+static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u32 i_pwr, q_pwr;
+ s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
+ int i;
+
+ if (!ah->ah_calibration ||
+ ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
+ goto done;
+
+ /* Calibration has finished, get the results and re-run */
+ for (i = 0; i <= 10; i++) {
+ iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
+ i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
+ q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
+ }
+
+ i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
+ q_coffd = q_pwr >> 7;
+
+ /* No correction */
+ if (i_coffd == 0 || q_coffd == 0)
+ goto done;
+
+ i_coff = ((-iq_corr) / i_coffd) & 0x3f;
+
+ /* Boundary check */
+ if (i_coff > 31)
+ i_coff = 31;
+ if (i_coff < -32)
+ i_coff = -32;
+
+ q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
+
+ /* Boundary check */
+ if (q_coff > 15)
+ q_coff = 15;
+ if (q_coff < -16)
+ q_coff = -16;
+
+ /* Commit new I/Q value */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
+ ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
+
+ /* Re-enable calibration -if we don't we'll commit
+ * the same values again and again */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
+
+done:
+
+ /* TODO: Separate noise floor calibration from I/Q calibration
+ * since noise floor calibration interrupts rx path while I/Q
+ * calibration doesn't. We don't need to run noise floor calibration
+ * as often as I/Q calibration.*/
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+ /* Initiate a gain_F calibration */
+ ath5k_hw_request_rfgain_probe(ah);
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration
+ */
+int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ int ret;
+
+ if (ah->ah_radio == AR5K_RF5110)
+ ret = ath5k_hw_rf5110_calibrate(ah, channel);
+ else
+ ret = ath5k_hw_rf511x_calibrate(ah, channel);
+
+ return ret;
+}
+
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
+{
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+
+ return 0;
+}
+
+/********************\
+ Misc PHY functions
+\********************/
+
+/*
+ * Get the PHY Chip revision
+ */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+{
+ unsigned int i;
+ u32 srev;
+ u16 ret;
+
+ /*
+ * Set the radio chip access register
+ */
+ switch (chan) {
+ case CHANNEL_2GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
+ break;
+ case CHANNEL_5GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ break;
+ default:
+ return 0;
+ }
+
+ mdelay(2);
+
+ /* ...wait until PHY is ready and read the selected radio revision */
+ ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
+
+ for (i = 0; i < 8; i++)
+ ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
+
+ if (ah->ah_version == AR5K_AR5210) {
+ srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+ ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
+ } else {
+ srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
+ ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
+ ((srev & 0x0f) << 4), 8);
+ }
+
+ /* Reset to the 5GHz mode */
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+ return ret;
+}
+
+void /*TODO:Boundary check*/
+ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
+{
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
+}
+
+unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
+{
+ if (ah->ah_version != AR5K_AR5210)
+ return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ return 0; /*XXX: What do we return for 5210 ?*/
+}
+
+
+/****************\
+* TX power setup *
+\****************/
+
+/*
+ * Helper functions
+ */
+
+/*
+ * Do linear interpolation between two given (x, y) points
+ */
+static s16
+ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
+ s16 y_left, s16 y_right)
+{
+ s16 ratio, result;
+
+ /* Avoid divide by zero and skip interpolation
+ * if we have the same point */
+ if ((x_left == x_right) || (y_left == y_right))
+ return y_left;
+
+ /*
+ * Since we use ints and not fps, we need to scale up in
+ * order to get a sane ratio value (or else we 'll eg. get
+ * always 1 instead of 1.25, 1.75 etc). We scale up by 100
+ * to have some accuracy both for 0.5 and 0.25 steps.
+ */
+ ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
+
+ /* Now scale down to be in range */
+ result = y_left + (ratio * (target - x_left) / 100);
+
+ return result;
+}
+
+/*
+ * Find vertical boundary (min pwr) for the linear PCDAC curve.
+ *
+ * Since we have the top of the curve and we draw the line below
+ * until we reach 1 (1 pcdac step) we need to know which point
+ * (x value) that is so that we don't go below y axis and have negative
+ * pcdac values when creating the curve, or fill the table with zeroes.
+ */
+static s16
+ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
+ const s16 *pwrL, const s16 *pwrR)
+{
+ s8 tmp;
+ s16 min_pwrL, min_pwrR;
+ s16 pwr_i;
+
+ if (pwrL[0] == pwrL[1])
+ min_pwrL = pwrL[0];
+ else {
+ pwr_i = pwrL[0];
+ do {
+ pwr_i--;
+ tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+ pwrL[0], pwrL[1],
+ stepL[0], stepL[1]);
+ } while (tmp > 1);
+
+ min_pwrL = pwr_i;
+ }
+
+ if (pwrR[0] == pwrR[1])
+ min_pwrR = pwrR[0];
+ else {
+ pwr_i = pwrR[0];
+ do {
+ pwr_i--;
+ tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+ pwrR[0], pwrR[1],
+ stepR[0], stepR[1]);
+ } while (tmp > 1);
+
+ min_pwrR = pwr_i;
+ }
+
+ /* Keep the right boundary so that it works for both curves */
+ return max(min_pwrL, min_pwrR);
+}
+
+/*
+ * Interpolate (pwr,vpd) points to create a Power to PDADC or a
+ * Power to PCDAC curve.
+ *
+ * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC
+ * steps (offsets) on y axis. Power can go up to 31.5dB and max
+ * PCDAC/PDADC step for each curve is 64 but we can write more than
+ * one curves on hw so we can go up to 128 (which is the max step we
+ * can write on the final table).
+ *
+ * We write y values (PCDAC/PDADC steps) on hw.
+ */
+static void
+ath5k_create_power_curve(s16 pmin, s16 pmax,
+ const s16 *pwr, const u8 *vpd,
+ u8 num_points,
+ u8 *vpd_table, u8 type)
+{
+ u8 idx[2] = { 0, 1 };
+ s16 pwr_i = 2*pmin;
+ int i;
+
+ if (num_points < 2)
+ return;
+
+ /* We want the whole line, so adjust boundaries
+ * to cover the entire power range. Note that
+ * power values are already 0.25dB so no need
+ * to multiply pwr_i by 2 */
+ if (type == AR5K_PWRTABLE_LINEAR_PCDAC) {
+ pwr_i = pmin;
+ pmin = 0;
+ pmax = 63;
+ }
+
+ /* Find surrounding turning points (TPs)
+ * and interpolate between them */
+ for (i = 0; (i <= (u16) (pmax - pmin)) &&
+ (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
+
+ /* We passed the right TP, move to the next set of TPs
+ * if we pass the last TP, extrapolate above using the last
+ * two TPs for ratio */
+ if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
+ idx[0]++;
+ idx[1]++;
+ }
+
+ vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
+ pwr[idx[0]], pwr[idx[1]],
+ vpd[idx[0]], vpd[idx[1]]);
+
+ /* Increase by 0.5dB
+ * (0.25 dB units) */
+ pwr_i += 2;
+ }
+}
+
+/*
+ * Get the surrounding per-channel power calibration piers
+ * for a given frequency so that we can interpolate between
+ * them and come up with an apropriate dataset for our current
+ * channel.
+ */
+static void
+ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ struct ath5k_chan_pcal_info **pcinfo_l,
+ struct ath5k_chan_pcal_info **pcinfo_r)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcinfo;
+ u8 idx_l, idx_r;
+ u8 mode, max, i;
+ u32 target = channel->center_freq;
+
+ idx_l = 0;
+ idx_r = 0;
+
+ if (!(channel->hw_value & CHANNEL_OFDM)) {
+ pcinfo = ee->ee_pwr_cal_b;
+ mode = AR5K_EEPROM_MODE_11B;
+ } else if (channel->hw_value & CHANNEL_2GHZ) {
+ pcinfo = ee->ee_pwr_cal_g;
+ mode = AR5K_EEPROM_MODE_11G;
+ } else {
+ pcinfo = ee->ee_pwr_cal_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ }
+ max = ee->ee_n_piers[mode] - 1;
+
+ /* Frequency is below our calibrated
+ * range. Use the lowest power curve
+ * we have */
+ if (target < pcinfo[0].freq) {
+ idx_l = idx_r = 0;
+ goto done;
+ }
+
+ /* Frequency is above our calibrated
+ * range. Use the highest power curve
+ * we have */
+ if (target > pcinfo[max].freq) {
+ idx_l = idx_r = max;
+ goto done;
+ }
+
+ /* Frequency is inside our calibrated
+ * channel range. Pick the surrounding
+ * calibration piers so that we can
+ * interpolate */
+ for (i = 0; i <= max; i++) {
+
+ /* Frequency matches one of our calibration
+ * piers, no need to interpolate, just use
+ * that calibration pier */
+ if (pcinfo[i].freq == target) {
+ idx_l = idx_r = i;
+ goto done;
+ }
+
+ /* We found a calibration pier that's above
+ * frequency, use this pier and the previous
+ * one to interpolate */
+ if (target < pcinfo[i].freq) {
+ idx_r = i;
+ idx_l = idx_r - 1;
+ goto done;
+ }
+ }
+
+done:
+ *pcinfo_l = &pcinfo[idx_l];
+ *pcinfo_r = &pcinfo[idx_r];
+
+ return;
+}
+
+/*
+ * Get the surrounding per-rate power calibration data
+ * for a given frequency and interpolate between power
+ * values to set max target power supported by hw for
+ * each rate.
+ */
+static void
+ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ struct ath5k_rate_pcal_info *rates)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_rate_pcal_info *rpinfo;
+ u8 idx_l, idx_r;
+ u8 mode, max, i;
+ u32 target = channel->center_freq;
+
+ idx_l = 0;
+ idx_r = 0;
+
+ if (!(channel->hw_value & CHANNEL_OFDM)) {
+ rpinfo = ee->ee_rate_tpwr_b;
+ mode = AR5K_EEPROM_MODE_11B;
+ } else if (channel->hw_value & CHANNEL_2GHZ) {
+ rpinfo = ee->ee_rate_tpwr_g;
+ mode = AR5K_EEPROM_MODE_11G;
+ } else {
+ rpinfo = ee->ee_rate_tpwr_a;
+ mode = AR5K_EEPROM_MODE_11A;
+ }
+ max = ee->ee_rate_target_pwr_num[mode] - 1;
+
+ /* Get the surrounding calibration
+ * piers - same as above */
+ if (target < rpinfo[0].freq) {
+ idx_l = idx_r = 0;
+ goto done;
+ }
+
+ if (target > rpinfo[max].freq) {
+ idx_l = idx_r = max;
+ goto done;
+ }
+
+ for (i = 0; i <= max; i++) {
+
+ if (rpinfo[i].freq == target) {
+ idx_l = idx_r = i;
+ goto done;
+ }
+
+ if (target < rpinfo[i].freq) {
+ idx_r = i;
+ idx_l = idx_r - 1;
+ goto done;
+ }
+ }
+
+done:
+ /* Now interpolate power value, based on the frequency */
+ rates->freq = target;
+
+ rates->target_power_6to24 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_6to24,
+ rpinfo[idx_r].target_power_6to24);
+
+ rates->target_power_36 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_36,
+ rpinfo[idx_r].target_power_36);
+
+ rates->target_power_48 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_48,
+ rpinfo[idx_r].target_power_48);
+
+ rates->target_power_54 =
+ ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+ rpinfo[idx_r].freq,
+ rpinfo[idx_l].target_power_54,
+ rpinfo[idx_r].target_power_54);
+}
+
+/*
+ * Get the max edge power for this channel if
+ * we have such data from EEPROM's Conformance Test
+ * Limits (CTL), and limit max power if needed.
+ *
+ * FIXME: Only works for world regulatory domains
+ */
+static void
+ath5k_get_max_ctl_power(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
+ u8 *ctl_val = ee->ee_ctl;
+ s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
+ s16 edge_pwr = 0;
+ u8 rep_idx;
+ u8 i, ctl_mode;
+ u8 ctl_idx = 0xFF;
+ u32 target = channel->center_freq;
+
+ /* Find out a CTL for our mode that's not mapped
+ * on a specific reg domain.
+ *
+ * TODO: Map our current reg domain to one of the 3 available
+ * reg domain ids so that we can support more CTLs. */
+ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+ ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_G:
+ ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_B:
+ ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_T:
+ ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_TG:
+ ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN;
+ break;
+ case CHANNEL_XR:
+ /* Fall through */
+ default:
+ return;
+ }
+
+ for (i = 0; i < ee->ee_ctls; i++) {
+ if (ctl_val[i] == ctl_mode) {
+ ctl_idx = i;
+ break;
+ }
+ }
+
+ /* If we have a CTL dataset available grab it and find the
+ * edge power for our frequency */
+ if (ctl_idx == 0xFF)
+ return;
+
+ /* Edge powers are sorted by frequency from lower
+ * to higher. Each CTL corresponds to 8 edge power
+ * measurements. */
+ rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
+
+ /* Don't do boundaries check because we
+ * might have more that one bands defined
+ * for this mode */
+
+ /* Get the edge power that's closer to our
+ * frequency */
+ for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
+ rep_idx += i;
+ if (target <= rep[rep_idx].freq)
+ edge_pwr = (s16) rep[rep_idx].edge;
+ }
+
+ if (edge_pwr) {
+ ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
+ }
+}
+
+
+/*
+ * Power to PCDAC table functions
+ */
+
+/*
+ * Fill Power to PCDAC table on RF5111
+ *
+ * No further processing is needed for RF5111, the only thing we have to
+ * do is fill the values below and above calibration range since eeprom data
+ * may not cover the entire PCDAC table.
+ */
+static void
+ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
+ s16 *table_max)
+{
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
+ u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
+ s16 min_pwr, max_pwr;
+
+ /* Get table boundaries */
+ min_pwr = table_min[0];
+ pcdac_0 = pcdac_tmp[0];
+
+ max_pwr = table_max[0];
+ pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
+
+ /* Extrapolate below minimum using pcdac_0 */
+ pcdac_i = 0;
+ for (i = 0; i < min_pwr; i++)
+ pcdac_out[pcdac_i++] = pcdac_0;
+
+ /* Copy values from pcdac_tmp */
+ pwr_idx = min_pwr;
+ for (i = 0 ; pwr_idx <= max_pwr &&
+ pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
+ pcdac_out[pcdac_i++] = pcdac_tmp[i];
+ pwr_idx++;
+ }
+
+ /* Extrapolate above maximum */
+ while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
+ pcdac_out[pcdac_i++] = pcdac_n;
+
+}
+
+/*
+ * Combine available XPD Curves and fill Linear Power to PCDAC table
+ * on RF5112
+ *
+ * RFX112 can have up to 2 curves (one for low txpower range and one for
+ * higher txpower range). We need to put them both on pcdac_out and place
+ * them in the correct location. In case we only have one curve available
+ * just fit it on pcdac_out (it's supposed to cover the entire range of
+ * available pwr levels since it's always the higher power curve). Extrapolate
+ * below and above final table if needed.
+ */
+static void
+ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
+ s16 *table_max, u8 pdcurves)
+{
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ u8 *pcdac_low_pwr;
+ u8 *pcdac_high_pwr;
+ u8 *pcdac_tmp;
+ u8 pwr;
+ s16 max_pwr_idx;
+ s16 min_pwr_idx;
+ s16 mid_pwr_idx = 0;
+ /* Edge flag turs on the 7nth bit on the PCDAC
+ * to delcare the higher power curve (force values
+ * to be greater than 64). If we only have one curve
+ * we don't need to set this, if we have 2 curves and
+ * fill the table backwards this can also be used to
+ * switch from higher power curve to lower power curve */
+ u8 edge_flag;
+ int i;
+
+ /* When we have only one curve available
+ * that's the higher power curve. If we have
+ * two curves the first is the high power curve
+ * and the next is the low power curve. */
+ if (pdcurves > 1) {
+ pcdac_low_pwr = ah->ah_txpower.tmpL[1];
+ pcdac_high_pwr = ah->ah_txpower.tmpL[0];
+ mid_pwr_idx = table_max[1] - table_min[1] - 1;
+ max_pwr_idx = (table_max[0] - table_min[0]) / 2;
+
+ /* If table size goes beyond 31.5dB, keep the
+ * upper 31.5dB range when setting tx power.
+ * Note: 126 = 31.5 dB in quarter dB steps */
+ if (table_max[0] - table_min[1] > 126)
+ min_pwr_idx = table_max[0] - 126;
+ else
+ min_pwr_idx = table_min[1];
+
+ /* Since we fill table backwards
+ * start from high power curve */
+ pcdac_tmp = pcdac_high_pwr;
+
+ edge_flag = 0x40;
+ } else {
+ pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
+ pcdac_high_pwr = ah->ah_txpower.tmpL[0];
+ min_pwr_idx = table_min[0];
+ max_pwr_idx = (table_max[0] - table_min[0]) / 2;
+ pcdac_tmp = pcdac_high_pwr;
+ edge_flag = 0;
+ }
+
+ /* This is used when setting tx power*/
+ ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
+
+ /* Fill Power to PCDAC table backwards */
+ pwr = max_pwr_idx;
+ for (i = 63; i >= 0; i--) {
+ /* Entering lower power range, reset
+ * edge flag and set pcdac_tmp to lower
+ * power curve.*/
+ if (edge_flag == 0x40 &&
+ (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
+ edge_flag = 0x00;
+ pcdac_tmp = pcdac_low_pwr;
+ pwr = mid_pwr_idx/2;
+ }
+
+ /* Don't go below 1, extrapolate below if we have
+ * already swithced to the lower power curve -or
+ * we only have one curve and edge_flag is zero
+ * anyway */
+ if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
+ while (i >= 0) {
+ pcdac_out[i] = pcdac_out[i + 1];
+ i--;
+ }
+ break;
+ }
+
+ pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
+
+ /* Extrapolate above if pcdac is greater than
+ * 126 -this can happen because we OR pcdac_out
+ * value with edge_flag on high power curve */
+ if (pcdac_out[i] > 126)
+ pcdac_out[i] = 126;
+
+ /* Decrease by a 0.5dB step */
+ pwr--;
+ }
+}
+
+/* Write PCDAC values on hw */
+static void
+ath5k_setup_pcdac_table(struct ath5k_hw *ah)
+{
+ u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
+ int i;
+
+ /*
+ * Write TX power values
+ */
+ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+ ath5k_hw_reg_write(ah,
+ (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
+ (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
+ AR5K_PHY_PCDAC_TXPOWER(i));
+ }
+}
+
+
+/*
+ * Power to PDADC table functions
+ */
+
+/*
+ * Set the gain boundaries and create final Power to PDADC table
+ *
+ * We can have up to 4 pd curves, we need to do a simmilar process
+ * as we do for RF5112. This time we don't have an edge_flag but we
+ * set the gain boundaries on a separate register.
+ */
+static void
+ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
+ s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
+{
+ u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
+ u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+ u8 *pdadc_tmp;
+ s16 pdadc_0;
+ u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
+ u8 pd_gain_overlap;
+
+ /* Note: Register value is initialized on initvals
+ * there is no feedback from hw.
+ * XXX: What about pd_gain_overlap from EEPROM ? */
+ pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
+ AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP;
+
+ /* Create final PDADC table */
+ for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
+ pdadc_tmp = ah->ah_txpower.tmpL[pdg];
+
+ if (pdg == pdcurves - 1)
+ /* 2 dB boundary stretch for last
+ * (higher power) curve */
+ gain_boundaries[pdg] = pwr_max[pdg] + 4;
+ else
+ /* Set gain boundary in the middle
+ * between this curve and the next one */
+ gain_boundaries[pdg] =
+ (pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
+
+ /* Sanity check in case our 2 db stretch got out of
+ * range. */
+ if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
+ gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
+
+ /* For the first curve (lower power)
+ * start from 0 dB */
+ if (pdg == 0)
+ pdadc_0 = 0;
+ else
+ /* For the other curves use the gain overlap */
+ pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
+ pd_gain_overlap;
+
+ /* Force each power step to be at least 0.5 dB */
+ if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
+ pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
+ else
+ pwr_step = 1;
+
+ /* If pdadc_0 is negative, we need to extrapolate
+ * below this pdgain by a number of pwr_steps */
+ while ((pdadc_0 < 0) && (pdadc_i < 128)) {
+ s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
+ pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
+ pdadc_0++;
+ }
+
+ /* Set last pwr level, using gain boundaries */
+ pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
+ /* Limit it to be inside pwr range */
+ table_size = pwr_max[pdg] - pwr_min[pdg];
+ max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
+
+ /* Fill pdadc_out table */
+ while (pdadc_0 < max_idx)
+ pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
+
+ /* Need to extrapolate above this pdgain? */
+ if (pdadc_n <= max_idx)
+ continue;
+
+ /* Force each power step to be at least 0.5 dB */
+ if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
+ pwr_step = pdadc_tmp[table_size - 1] -
+ pdadc_tmp[table_size - 2];
+ else
+ pwr_step = 1;
+
+ /* Extrapolate above */
+ while ((pdadc_0 < (s16) pdadc_n) &&
+ (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
+ s16 tmp = pdadc_tmp[table_size - 1] +
+ (pdadc_0 - max_idx) * pwr_step;
+ pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
+ pdadc_0++;
+ }
+ }
+
+ while (pdg < AR5K_EEPROM_N_PD_GAINS) {
+ gain_boundaries[pdg] = gain_boundaries[pdg - 1];
+ pdg++;
+ }
+
+ while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
+ pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
+ pdadc_i++;
+ }
+
+ /* Set gain boundaries */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(pd_gain_overlap,
+ AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) |
+ AR5K_REG_SM(gain_boundaries[0],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) |
+ AR5K_REG_SM(gain_boundaries[1],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) |
+ AR5K_REG_SM(gain_boundaries[2],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) |
+ AR5K_REG_SM(gain_boundaries[3],
+ AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4),
+ AR5K_PHY_TPC_RG5);
+
+ /* Used for setting rate power table */
+ ah->ah_txpower.txp_min_idx = pwr_min[0];
+
+}
+
+/* Write PDADC values on hw */
+static void
+ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
+ u8 pdcurves, u8 *pdg_to_idx)
+{
+ u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+ u32 reg;
+ u8 i;
+
+ /* Select the right pdgain curves */
+
+ /* Clear current settings */
+ reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1);
+ reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 |
+ AR5K_PHY_TPC_RG1_PDGAIN_2 |
+ AR5K_PHY_TPC_RG1_PDGAIN_3 |
+ AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
+
+ /*
+ * Use pd_gains curve from eeprom
+ *
+ * This overrides the default setting from initvals
+ * in case some vendors (e.g. Zcomax) don't use the default
+ * curves. If we don't honor their settings we 'll get a
+ * 5dB (1 * gain overlap ?) drop.
+ */
+ reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
+
+ switch (pdcurves) {
+ case 3:
+ reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
+ /* Fall through */
+ case 2:
+ reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
+ /* Fall through */
+ case 1:
+ reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
+ break;
+ }
+ ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1);
+
+ /*
+ * Write TX power values
+ */
+ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+ ath5k_hw_reg_write(ah,
+ ((pdadc_out[4*i + 0] & 0xff) << 0) |
+ ((pdadc_out[4*i + 1] & 0xff) << 8) |
+ ((pdadc_out[4*i + 2] & 0xff) << 16) |
+ ((pdadc_out[4*i + 3] & 0xff) << 24),
+ AR5K_PHY_PDADC_TXPOWER(i));
+ }
+}
+
+
+/*
+ * Common code for PCDAC/PDADC tables
+ */
+
+/*
+ * This is the main function that uses all of the above
+ * to set PCDAC/PDADC table on hw for the current channel.
+ * This table is used for tx power calibration on the basband,
+ * without it we get weird tx power levels and in some cases
+ * distorted spectral mask
+ */
+static int
+ath5k_setup_channel_powertable(struct ath5k_hw *ah,
+ struct net80211_channel *channel,
+ u8 ee_mode, u8 type)
+{
+ struct ath5k_pdgain_info *pdg_L, *pdg_R;
+ struct ath5k_chan_pcal_info *pcinfo_L;
+ struct ath5k_chan_pcal_info *pcinfo_R;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
+ s16 table_min[AR5K_EEPROM_N_PD_GAINS];
+ s16 table_max[AR5K_EEPROM_N_PD_GAINS];
+ u8 *tmpL;
+ u8 *tmpR;
+ u32 target = channel->center_freq;
+ int pdg, i;
+
+ /* Get surounding freq piers for this channel */
+ ath5k_get_chan_pcal_surrounding_piers(ah, channel,
+ &pcinfo_L,
+ &pcinfo_R);
+
+ /* Loop over pd gain curves on
+ * surounding freq piers by index */
+ for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
+
+ /* Fill curves in reverse order
+ * from lower power (max gain)
+ * to higher power. Use curve -> idx
+ * backmaping we did on eeprom init */
+ u8 idx = pdg_curve_to_idx[pdg];
+
+ /* Grab the needed curves by index */
+ pdg_L = &pcinfo_L->pd_curves[idx];
+ pdg_R = &pcinfo_R->pd_curves[idx];
+
+ /* Initialize the temp tables */
+ tmpL = ah->ah_txpower.tmpL[pdg];
+ tmpR = ah->ah_txpower.tmpR[pdg];
+
+ /* Set curve's x boundaries and create
+ * curves so that they cover the same
+ * range (if we don't do that one table
+ * will have values on some range and the
+ * other one won't have any so interpolation
+ * will fail) */
+ table_min[pdg] = min(pdg_L->pd_pwr[0],
+ pdg_R->pd_pwr[0]) / 2;
+
+ table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
+ pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
+
+ /* Now create the curves on surrounding channels
+ * and interpolate if needed to get the final
+ * curve for this gain on this channel */
+ switch (type) {
+ case AR5K_PWRTABLE_LINEAR_PCDAC:
+ /* Override min/max so that we don't loose
+ * accuracy (don't divide by 2) */
+ table_min[pdg] = min(pdg_L->pd_pwr[0],
+ pdg_R->pd_pwr[0]);
+
+ table_max[pdg] =
+ max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
+ pdg_R->pd_pwr[pdg_R->pd_points - 1]);
+
+ /* Override minimum so that we don't get
+ * out of bounds while extrapolating
+ * below. Don't do this when we have 2
+ * curves and we are on the high power curve
+ * because table_min is ok in this case */
+ if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
+
+ table_min[pdg] =
+ ath5k_get_linear_pcdac_min(pdg_L->pd_step,
+ pdg_R->pd_step,
+ pdg_L->pd_pwr,
+ pdg_R->pd_pwr);
+
+ /* Don't go too low because we will
+ * miss the upper part of the curve.
+ * Note: 126 = 31.5dB (max power supported)
+ * in 0.25dB units */
+ if (table_max[pdg] - table_min[pdg] > 126)
+ table_min[pdg] = table_max[pdg] - 126;
+ }
+
+ /* Fall through */
+ case AR5K_PWRTABLE_PWR_TO_PCDAC:
+ case AR5K_PWRTABLE_PWR_TO_PDADC:
+
+ ath5k_create_power_curve(table_min[pdg],
+ table_max[pdg],
+ pdg_L->pd_pwr,
+ pdg_L->pd_step,
+ pdg_L->pd_points, tmpL, type);
+
+ /* We are in a calibration
+ * pier, no need to interpolate
+ * between freq piers */
+ if (pcinfo_L == pcinfo_R)
+ continue;
+
+ ath5k_create_power_curve(table_min[pdg],
+ table_max[pdg],
+ pdg_R->pd_pwr,
+ pdg_R->pd_step,
+ pdg_R->pd_points, tmpR, type);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Interpolate between curves
+ * of surounding freq piers to
+ * get the final curve for this
+ * pd gain. Re-use tmpL for interpolation
+ * output */
+ for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
+ (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
+ tmpL[i] = (u8) ath5k_get_interpolated_value(target,
+ (s16) pcinfo_L->freq,
+ (s16) pcinfo_R->freq,
+ (s16) tmpL[i],
+ (s16) tmpR[i]);
+ }
+ }
+
+ /* Now we have a set of curves for this
+ * channel on tmpL (x range is table_max - table_min
+ * and y values are tmpL[pdg][]) sorted in the same
+ * order as EEPROM (because we've used the backmaping).
+ * So for RF5112 it's from higher power to lower power
+ * and for RF2413 it's from lower power to higher power.
+ * For RF5111 we only have one curve. */
+
+ /* Fill min and max power levels for this
+ * channel by interpolating the values on
+ * surounding channels to complete the dataset */
+ ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
+ (s16) pcinfo_L->freq,
+ (s16) pcinfo_R->freq,
+ pcinfo_L->min_pwr, pcinfo_R->min_pwr);
+
+ ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
+ (s16) pcinfo_L->freq,
+ (s16) pcinfo_R->freq,
+ pcinfo_L->max_pwr, pcinfo_R->max_pwr);
+
+ /* We are ready to go, fill PCDAC/PDADC
+ * table and write settings on hardware */
+ switch (type) {
+ case AR5K_PWRTABLE_LINEAR_PCDAC:
+ /* For RF5112 we can have one or two curves
+ * and each curve covers a certain power lvl
+ * range so we need to do some more processing */
+ ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
+ ee->ee_pd_gains[ee_mode]);
+
+ /* Set txp.offset so that we can
+ * match max power value with max
+ * table index */
+ ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
+
+ /* Write settings on hw */
+ ath5k_setup_pcdac_table(ah);
+ break;
+ case AR5K_PWRTABLE_PWR_TO_PCDAC:
+ /* We are done for RF5111 since it has only
+ * one curve, just fit the curve on the table */
+ ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
+
+ /* No rate powertable adjustment for RF5111 */
+ ah->ah_txpower.txp_min_idx = 0;
+ ah->ah_txpower.txp_offset = 0;
+
+ /* Write settings on hw */
+ ath5k_setup_pcdac_table(ah);
+ break;
+ case AR5K_PWRTABLE_PWR_TO_PDADC:
+ /* Set PDADC boundaries and fill
+ * final PDADC table */
+ ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
+ ee->ee_pd_gains[ee_mode]);
+
+ /* Write settings on hw */
+ ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
+
+ /* Set txp.offset, note that table_min
+ * can be negative */
+ ah->ah_txpower.txp_offset = table_min[0];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Per-rate tx power setting
+ *
+ * This is the code that sets the desired tx power (below
+ * maximum) on hw for each rate (we also have TPC that sets
+ * power per packet). We do that by providing an index on the
+ * PCDAC/PDADC table we set up.
+ */
+
+/*
+ * Set rate power table
+ *
+ * For now we only limit txpower based on maximum tx power
+ * supported by hw (what's inside rate_info). We need to limit
+ * this even more, based on regulatory domain etc.
+ *
+ * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps)
+ * and is indexed as follows:
+ * rates[0] - rates[7] -> OFDM rates
+ * rates[8] - rates[14] -> CCK rates
+ * rates[15] -> XR rates (they all have the same power)
+ */
+static void
+ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
+ struct ath5k_rate_pcal_info *rate_info,
+ u8 ee_mode)
+{
+ unsigned int i;
+ u16 *rates;
+
+ /* max_pwr is power level we got from driver/user in 0.5dB
+ * units, switch to 0.25dB units so we can compare */
+ max_pwr *= 2;
+ max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
+
+ /* apply rate limits */
+ rates = ah->ah_txpower.txp_rates_power_table;
+
+ /* OFDM rates 6 to 24Mb/s */
+ for (i = 0; i < 5; i++)
+ rates[i] = min(max_pwr, rate_info->target_power_6to24);
+
+ /* Rest OFDM rates */
+ rates[5] = min(rates[0], rate_info->target_power_36);
+ rates[6] = min(rates[0], rate_info->target_power_48);
+ rates[7] = min(rates[0], rate_info->target_power_54);
+
+ /* CCK rates */
+ /* 1L */
+ rates[8] = min(rates[0], rate_info->target_power_6to24);
+ /* 2L */
+ rates[9] = min(rates[0], rate_info->target_power_36);
+ /* 2S */
+ rates[10] = min(rates[0], rate_info->target_power_36);
+ /* 5L */
+ rates[11] = min(rates[0], rate_info->target_power_48);
+ /* 5S */
+ rates[12] = min(rates[0], rate_info->target_power_48);
+ /* 11L */
+ rates[13] = min(rates[0], rate_info->target_power_54);
+ /* 11S */
+ rates[14] = min(rates[0], rate_info->target_power_54);
+
+ /* XR rates */
+ rates[15] = min(rates[0], rate_info->target_power_6to24);
+
+ /* CCK rates have different peak to average ratio
+ * so we have to tweak their power so that gainf
+ * correction works ok. For this we use OFDM to
+ * CCK delta from eeprom */
+ if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
+ (ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
+ for (i = 8; i <= 15; i++)
+ rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
+
+ ah->ah_txpower.txp_min_pwr = rates[7];
+ ah->ah_txpower.txp_max_pwr = rates[0];
+ ah->ah_txpower.txp_ofdm = rates[7];
+}
+
+
+/*
+ * Set transmition power
+ */
+int
+ath5k_hw_txpower(struct ath5k_hw *ah, struct net80211_channel *channel,
+ u8 ee_mode, u8 txpower)
+{
+ struct ath5k_rate_pcal_info rate_info;
+ u8 type;
+ int ret;
+
+ if (txpower > AR5K_TUNE_MAX_TXPOWER) {
+ DBG("ath5k: invalid tx power %d\n", txpower);
+ return -EINVAL;
+ }
+ if (txpower == 0)
+ txpower = AR5K_TUNE_DEFAULT_TXPOWER;
+
+ /* Reset TX power values */
+ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+ ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+ ah->ah_txpower.txp_min_pwr = 0;
+ ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
+
+ /* Initialize TX power table */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ type = AR5K_PWRTABLE_PWR_TO_PCDAC;
+ break;
+ case AR5K_RF5112:
+ type = AR5K_PWRTABLE_LINEAR_PCDAC;
+ break;
+ case AR5K_RF2413:
+ case AR5K_RF5413:
+ case AR5K_RF2316:
+ case AR5K_RF2317:
+ case AR5K_RF2425:
+ type = AR5K_PWRTABLE_PWR_TO_PDADC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* FIXME: Only on channel/mode change */
+ ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
+ if (ret)
+ return ret;
+
+ /* Limit max power if we have a CTL available */
+ ath5k_get_max_ctl_power(ah, channel);
+
+ /* FIXME: Tx power limit for this regdomain
+ * XXX: Mac80211/CRDA will do that anyway ? */
+
+ /* FIXME: Antenna reduction stuff */
+
+ /* FIXME: Limit power on turbo modes */
+
+ /* FIXME: TPC scale reduction */
+
+ /* Get surounding channels for per-rate power table
+ * calibration */
+ ath5k_get_rate_pcal_data(ah, channel, &rate_info);
+
+ /* Setup rate power table */
+ ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
+
+ /* Write rate power table on hw */
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
+ AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
+ AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
+ AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
+ AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
+ AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
+ AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
+ AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
+ AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
+
+ /* FIXME: TPC support */
+ if (ah->ah_txpower.txp_tpc) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) |
+ AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) |
+ AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
+ AR5K_TPC);
+ } else {
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+ }
+
+ return 0;
+}
+
+int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower)
+{
+ struct net80211_channel *channel = ah->ah_current_channel;
+
+ DBG2("ath5k: changing txpower to %d\n", txpower);
+
+ return ath5k_hw_txpower(ah, channel, mode, txpower);
+}
+
+#undef _ATH5K_PHY
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_qcu.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_qcu.c
new file mode 100644
index 0000000..a674b85
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_qcu.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+/********************************************\
+Queue Control Unit, DFS Control Unit Functions
+\********************************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/*
+ * Set properties for a transmit queue
+ */
+int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah,
+ const struct ath5k_txq_info *queue_info)
+{
+ if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ memcpy(&ah->ah_txq, queue_info, sizeof(struct ath5k_txq_info));
+
+ /*XXX: Is this supported on 5210 ?*/
+ if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
+ ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
+ (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
+ queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
+ ah->ah_txq.tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+
+ return 0;
+}
+
+/*
+ * Initialize a transmit queue
+ */
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info)
+{
+ unsigned int queue;
+ int ret;
+
+ /* We only use one queue */
+ queue = 0;
+
+ /*
+ * Setup internal queue structure
+ */
+ memset(&ah->ah_txq, 0, sizeof(struct ath5k_txq_info));
+ ah->ah_txq.tqi_type = queue_type;
+
+ if (queue_info != NULL) {
+ queue_info->tqi_type = queue_type;
+ ret = ath5k_hw_set_tx_queueprops(ah, queue_info);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * We use ah_txq_status to hold a temp value for
+ * the Secondary interrupt mask registers on 5211+
+ * check out ath5k_hw_reset_tx_queue
+ */
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_status, 0);
+
+ return 0;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah)
+{
+ /* This queue will be skipped in further operations */
+ ah->ah_txq.tqi_type = AR5K_TX_QUEUE_INACTIVE;
+ /*For SIMR setup*/
+ AR5K_Q_DISABLE_BITS(ah->ah_txq_status, 0);
+}
+
+/*
+ * Set DFS properties for a transmit queue on DCU
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah)
+{
+ u32 cw_min, cw_max, retry_lg, retry_sh;
+ struct ath5k_txq_info *tq = &ah->ah_txq;
+ const int queue = 0;
+
+ tq = &ah->ah_txq;
+
+ if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return 0;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Only handle data queues, others will be ignored */
+ if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
+ return 0;
+
+ /* Set Slot time */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+ AR5K_SLOT_TIME);
+ /* Set ACK_CTS timeout */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+ AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+ /* Set Transmit Latency */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+ AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+
+ /* Set IFS0 */
+ if (ah->ah_turbo) {
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME_TURBO) <<
+ AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
+ AR5K_IFS0);
+ } else {
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+ AR5K_INIT_SIFS, AR5K_IFS0);
+ }
+
+ /* Set IFS1 */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+ AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+ /* Set AR5K_PHY_SETTLING */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+ | 0x38 :
+ (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+ | 0x1C,
+ AR5K_PHY_SETTLING);
+ /* Set Frame Control Register */
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+ AR5K_PHY_TURBO_SHORT | 0x2020) :
+ (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+ AR5K_PHY_FRAME_CTL_5210);
+ }
+
+ /*
+ * Calculate cwmin/max by channel mode
+ */
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ /*XR is only supported on 5212*/
+ if (IS_CHAN_XR(ah->ah_current_channel) &&
+ ah->ah_version == AR5K_AR5212) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
+ ah->ah_aifs = AR5K_TUNE_AIFS_XR;
+ /*B mode is not supported on 5210*/
+ } else if (IS_CHAN_B(ah->ah_current_channel) &&
+ ah->ah_version != AR5K_AR5210) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
+ ah->ah_aifs = AR5K_TUNE_AIFS_11B;
+ }
+
+ cw_min = 1;
+ while (cw_min < ah->ah_cw_min)
+ cw_min = (cw_min << 1) | 1;
+
+ cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
+ ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
+ cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
+ ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
+
+ /*
+ * Calculate and set retry limits
+ */
+ if (ah->ah_software_retry) {
+ /* XXX Need to test this */
+ retry_lg = ah->ah_limit_tx_retries;
+ retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+ AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
+ } else {
+ retry_lg = AR5K_INIT_LG_RETRY;
+ retry_sh = AR5K_INIT_SH_RETRY;
+ }
+
+ /*No QCU/DCU [5210]*/
+ if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_reg_write(ah,
+ (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+ | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+ | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+ | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
+ | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
+ AR5K_NODCU_RETRY_LMT);
+ } else {
+ /*QCU/DCU [5211+]*/
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_DCU_RETRY_LMT_SLG_RETRY) |
+ AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_DCU_RETRY_LMT_SSH_RETRY) |
+ AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
+ AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
+ AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+
+ /*===Rest is also for QCU/DCU only [5211+]===*/
+
+ /*
+ * Set initial content window (cw_min/cw_max)
+ * and arbitrated interframe space (aifs)...
+ */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
+ AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+ /*
+ * Set misc registers
+ */
+ /* Enable DCU early termination for this queue */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_DCU_EARLY);
+
+ /* Enable DCU to wait for next fragment from QCU */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_DCU_MISC_FRAG_WAIT);
+
+ /* On Maui and Spirit use the global seqnum on DCU */
+ if (ah->ah_mac_version < AR5K_SREV_AR5211)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_DCU_MISC_SEQNUM_CTL);
+
+ if (tq->tqi_cbr_period) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+ AR5K_QCU_CBRCFG_INTVAL) |
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+ AR5K_QCU_CBRCFG_ORN_THRES),
+ AR5K_QUEUE_CBRCFG(queue));
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_CBR);
+ if (tq->tqi_cbr_overflow_limit)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBR_THRES_ENABLE);
+ }
+
+ if (tq->tqi_ready_time &&
+ (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+
+ if (tq->tqi_burst_time) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+ AR5K_DCU_CHAN_TIME_DUR) |
+ AR5K_DCU_CHAN_TIME_ENABLE,
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+
+ if (tq->tqi_flags
+ & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_RDY_VEOL_POLICY);
+ }
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ /* TODO: Handle frame compression */
+
+ /*
+ * Enable interrupts for this tx queue
+ * in the secondary interrupt mask registers
+ */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
+
+ /* Update secondary interrupt mask registers */
+
+ /* Filter out inactive queues */
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+ ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+ AR5K_SIMR0_QCU_TXOK) |
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+ AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+ AR5K_SIMR1_QCU_TXERR) |
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
+ AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
+ /* Update simr2 but don't overwrite rest simr2 settings */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+ AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN));
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+ AR5K_SIMR3_QCBRORN) |
+ AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+ AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+ AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+ /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+ AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+ /* No queue has TXNOFRM enabled, disable the interrupt
+ * by setting AR5K_TXNOFRM to zero */
+ if (ah->ah_txq_imr_nofrm == 0)
+ ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+ /* Set QCU mask for this DCU to save power */
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
+ }
+
+ return 0;
+}
+
+/*
+ * Set slot time on DCU
+ */
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+{
+ if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
+ return -EINVAL;
+
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
+ ah->ah_turbo), AR5K_SLOT_TIME);
+ else
+ ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
+
+ return 0;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_reset.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_reset.c
new file mode 100644
index 0000000..dc80093
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_reset.c
@@ -0,0 +1,1176 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+FILE_LICENCE ( MIT );
+
+#define _ATH5K_RESET
+
+/*****************************\
+ Reset functions and helpers
+\*****************************/
+
+#include <gpxe/pci.h> /* To determine if a card is pci-e */
+#include <unistd.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/* Find last set bit; fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32 */
+static int fls(int x)
+{
+ int r = 32;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+
+
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
+ *
+ * Since delta slope is floating point we split it on its exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this patent is related
+ * http://www.freepatentsonline.com/7184495.html
+ */
+static int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ /* Get exponent and mantissa and set it */
+ u32 coef_scaled, coef_exp, coef_man,
+ ds_coef_exp, ds_coef_man, clock;
+
+ if (!(ah->ah_version == AR5K_AR5212) ||
+ !(channel->hw_value & CHANNEL_OFDM)) {
+ DBG("ath5k: attempt to set OFDM timings on non-OFDM channel\n");
+ return -EFAULT;
+ }
+
+ /* Get coefficient
+ * ALGO: coef = (5 * clock * carrier_freq) / 2)
+ * we scale coef by shifting clock value by 24 for
+ * better precision since we use integers */
+ /* TODO: Half/quarter rate */
+ clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
+
+ coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+
+ /* Get exponent
+ * ALGO: coef_exp = 14 - highest set bit position */
+ coef_exp = fls(coef_scaled) - 1;
+
+ /* Doesn't make sense if it's zero*/
+ if (!coef_scaled || !coef_exp)
+ return -EINVAL;
+
+ /* Note: we've shifted coef_scaled by 24 */
+ coef_exp = 14 - (coef_exp - 24);
+
+
+ /* Get mantissa (significant digits)
+ * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
+ coef_man = coef_scaled +
+ (1 << (24 - coef_exp - 1));
+
+ /* Calculate delta slope coefficient exponent
+ * and mantissa (remove scaling) and set them on hw */
+ ds_coef_man = coef_man >> (24 - coef_exp);
+ ds_coef_exp = coef_exp - 16;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+ return 0;
+}
+
+
+/*
+ * index into rates for control rates, we can set it up like this because
+ * this is only used for AR5212 and we know it supports G mode
+ */
+static const unsigned int control_rates[] =
+ { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
+
+/**
+ * ath5k_hw_write_rate_duration - fill rate code to duration table
+ *
+ * @ah: the &struct ath5k_hw
+ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are
+ * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
+ * different rate code so we write their value twice (one for long preample
+ * and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
+ * quarter rate mode, we need to use another set of bitrates (that's why we
+ * need the mode parameter) but we don't handle these proprietary modes yet.
+ */
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+ unsigned int mode __unused)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+ u16 rate;
+ int i;
+
+ /* Write rate duration table */
+ for (i = 0; i < sc->hwinfo->nr_rates[NET80211_BAND_2GHZ]; i++) {
+ u32 reg;
+ u16 tx_time;
+
+ rate = sc->hwinfo->rates[NET80211_BAND_2GHZ][i];
+
+ /* Set ACK timeout */
+ reg = AR5K_RATE_DUR(ath5k_bitrate_to_hw_rix(rate));
+
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
+ * it's 14 bytes. Note we use the control rate and not the
+ * actual rate for this rate. See mac80211 tx.c
+ * ieee80211_duration() for a brief description of
+ * what rate we should choose to TX ACKs. */
+ tx_time = net80211_duration(sc->dev, 14, rate);
+
+ ath5k_hw_reg_write(ah, tx_time, reg);
+
+ if (rate != 20 && rate != 55 && rate != 110)
+ continue;
+
+ /*
+ * We're not distinguishing short preamble here,
+ * This is true, all we'll get is a longer value here
+ * which is not necessarilly bad.
+ */
+ ath5k_hw_reg_write(ah, tx_time,
+ reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+ }
+}
+
+/*
+ * Reset chipset
+ */
+static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
+{
+ int ret;
+ u32 mask = val ? val : ~0U;
+
+ /* Read-and-clear RX Descriptor Pointer*/
+ ath5k_hw_reg_read(ah, AR5K_RXDP);
+
+ /*
+ * Reset the device and wait until success
+ */
+ ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
+
+ /* Wait at least 128 PCI clocks */
+ udelay(15);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+ | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+ | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+ } else {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ }
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, 0);
+
+ /*
+ * Reset configuration register (for hw byte-swap). Note that this
+ * is only set for big endian. We do the necessary magic in
+ * AR5K_INIT_CFG.
+ */
+ if ((val & AR5K_RESET_CTL_PCU) == 0)
+ ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+ return ret;
+}
+
+/*
+ * Sleep control
+ */
+int ath5k_hw_wake(struct ath5k_hw *ah)
+{
+ unsigned int i;
+ u32 staid, data;
+
+ staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+ staid &= ~AR5K_STA_ID1_PWR_SV;
+
+ /* Preserve sleep duration */
+ data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+ if (data & 0xffc00000)
+ data = 0;
+ else
+ data = data & 0xfffcffff;
+
+ ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ udelay(15);
+
+ for (i = 50; i > 0; i--) {
+ /* Check if the chip did wake up */
+ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_SPWR_DN) == 0)
+ break;
+
+ /* Wait a bit and retry */
+ udelay(200);
+ ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ }
+
+ /* Fail if the chip didn't wake up */
+ if (i <= 0)
+ return -EIO;
+
+ ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/*
+ * Bring up MAC + PHY Chips and program PLL
+ * TODO: Half/Quarter rate support
+ */
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, int initial __unused)
+{
+ struct pci_device *pdev = ah->ah_sc->pdev;
+ u32 turbo, mode, clock, bus_flags;
+ int ret;
+
+ turbo = 0;
+ mode = 0;
+ clock = 0;
+
+ /* Wakeup the device */
+ ret = ath5k_hw_wake(ah);
+ if (ret) {
+ DBG("ath5k: failed to wake up the MAC chip\n");
+ return ret;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Get channel mode flags
+ */
+
+ if (ah->ah_radio >= AR5K_RF5112) {
+ mode = AR5K_PHY_MODE_RAD_RF5112;
+ clock = AR5K_PHY_PLL_RF5112;
+ } else {
+ mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
+ clock = AR5K_PHY_PLL_RF5111; /*Zero*/
+ }
+
+ if (flags & CHANNEL_2GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_2GHZ;
+ clock |= AR5K_PHY_PLL_44MHZ;
+
+ if (flags & CHANNEL_CCK) {
+ mode |= AR5K_PHY_MODE_MOD_CCK;
+ } else if (flags & CHANNEL_OFDM) {
+ /* XXX Dynamic OFDM/CCK is not supported by the
+ * AR5211 so we set MOD_OFDM for plain g (no
+ * CCK headers) operation. We need to test
+ * this, 5211 might support ofdm-only g after
+ * all, there are also initial register values
+ * in the code for g mode (see initvals.c). */
+ if (ah->ah_version == AR5K_AR5211)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else
+ mode |= AR5K_PHY_MODE_MOD_DYN;
+ } else {
+ DBG("ath5k: invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else if (flags & CHANNEL_5GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+
+ if (ah->ah_radio == AR5K_RF5413)
+ clock = AR5K_PHY_PLL_40MHZ_5413;
+ else
+ clock |= AR5K_PHY_PLL_40MHZ;
+
+ if (flags & CHANNEL_OFDM)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else {
+ DBG("ath5k: invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else {
+ DBG("ath5k: invalid radio frequency mode\n");
+ return -EINVAL;
+ }
+
+ if (flags & CHANNEL_TURBO)
+ turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+ } else { /* Reset the device */
+
+ /* ...enable Atheros turbo mode if requested */
+ if (flags & CHANNEL_TURBO)
+ ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
+ AR5K_PHY_TURBO);
+ }
+
+ /* reseting PCI on PCI-E cards results card to hang
+ * and always return 0xffff... so we ingore that flag
+ * for PCI-E cards */
+ if (pci_find_capability(pdev, PCI_CAP_ID_EXP))
+ bus_flags = 0;
+ else
+ bus_flags = AR5K_RESET_CTL_PCI;
+
+ /* Reset chipset */
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+ if (ret) {
+ DBG("ath5k: failed to reset the MAC chip\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_wake(ah);
+ if (ret) {
+ DBG("ath5k: failed to resume the MAC chip\n");
+ return ret;
+ }
+
+ /* ...final warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ DBG("ath5k: failed to warm reset the MAC chip\n");
+ return -EIO;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+
+ /* ...update PLL if needed */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+ udelay(300);
+ }
+
+ /* ...set the PHY operating mode */
+ ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
+ ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
+ }
+
+ return 0;
+}
+
+static int ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ u8 refclk_freq;
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ refclk_freq = 40;
+ else
+ refclk_freq = 32;
+
+ if ((channel->center_freq % refclk_freq != 0) &&
+ ((channel->center_freq % refclk_freq < 10) ||
+ (channel->center_freq % refclk_freq > 22)))
+ return 1;
+ else
+ return 0;
+}
+
+/* TODO: Half/Quarter rate */
+static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
+ struct net80211_channel *channel)
+{
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+
+ /* Setup ADC control */
+ ath5k_hw_reg_write(ah,
+ (AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
+ AR5K_REG_SM(2,
+ AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
+ AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
+ AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
+ AR5K_PHY_ADC_CTL);
+
+
+
+ /* Disable barker RSSI threshold */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+ AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
+
+ /* Set the mute mask */
+ ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
+ }
+
+ /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
+
+ /* Enable DCU double buffering */
+ if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_DCU_DBL_BUF_DIS);
+
+ /* Set DAC/ADC delays */
+ if (ah->ah_version == AR5K_AR5212) {
+ u32 scal;
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ scal = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ath5k_eeprom_is_hb63(ah))
+ scal = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ scal = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+ }
+
+ /* Set fast ADC */
+ if ((ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ u32 fast_adc = 1;
+
+ if (channel->center_freq == 2462 ||
+ channel->center_freq == 2467)
+ fast_adc = 0;
+
+ /* Only update if needed */
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
+ ath5k_hw_reg_write(ah, fast_adc,
+ AR5K_PHY_FAST_ADC);
+ }
+
+ /* Fix for first revision of the RF5112 RF chipset */
+ if (ah->ah_radio == AR5K_RF5112 &&
+ ah->ah_radio_5ghz_revision <
+ AR5K_SREV_RAD_5112A) {
+ u32 data;
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+ if (channel->hw_value & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+ }
+
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ u32 usec_reg;
+ /* 5311 has different tx/rx latency masks
+ * from 5211, since we deal 5311 the same
+ * as 5211 when setting initvals, shift
+ * values here to their proper locations */
+ usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+ ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
+ AR5K_USEC_32 |
+ AR5K_USEC_TX_LATENCY_5211 |
+ AR5K_REG_SM(29,
+ AR5K_USEC_RX_LATENCY_5210)),
+ AR5K_USEC_5211);
+ /* Clear QCU/DCU clock gating register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
+ /* Set DAC/ADC delays */
+ ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+ /* Enable PCU FIFO corruption ECO */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+ AR5K_DIAG_SW_ECO_ENABLE);
+ }
+}
+
+static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
+ struct net80211_channel *channel, u8 *ant, u8 ee_mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ s16 cck_ofdm_pwr_delta;
+
+ /* Adjust power delta for channel 14 */
+ if (channel->center_freq == 2484)
+ cck_ofdm_pwr_delta =
+ ((ee->ee_cck_ofdm_power_delta -
+ ee->ee_scaled_cck_delta) * 2) / 10;
+ else
+ cck_ofdm_pwr_delta =
+ (ee->ee_cck_ofdm_power_delta * 2) / 10;
+
+ /* Set CCK to OFDM power delta on tx power
+ * adjustment register */
+ if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+ if (channel->hw_value == CHANNEL_G)
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
+ AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
+ AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
+ AR5K_PHY_TX_PWR_ADJ);
+ else
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
+ } else {
+ /* For older revs we scale power on sw during tx power
+ * setup */
+ ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
+ ah->ah_txpower.txp_cck_ofdm_gainf_delta =
+ ee->ee_cck_ofdm_gain_delta;
+ }
+
+ /* Set antenna idle switch table */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
+ AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
+ (ah->ah_antenna[ee_mode][0] |
+ AR5K_PHY_ANT_CTL_TXRX_EN));
+
+ /* Set antenna switch table */
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+ /* Noise floor threshold */
+ ath5k_hw_reg_write(ah,
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+ AR5K_PHY_NFTHRES);
+
+ if ((channel->hw_value & CHANNEL_TURBO) &&
+ (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
+ /* Switch settling time (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling_turbo[ee_mode]);
+
+ /* Tx/Rx attenuation (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx_turbo[ee_mode]);
+
+ /* ADC/PGA desired size (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size_turbo[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size_turbo[ee_mode]);
+
+ /* Tx/Rx margin (Turbo) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx_turbo[ee_mode]);
+
+ } else {
+ /* Switch settling time */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ ee->ee_switch_settling[ee_mode]);
+
+ /* Tx/Rx attenuation */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+ AR5K_PHY_GAIN_TXRX_ATTEN,
+ ee->ee_atn_tx_rx[ee_mode]);
+
+ /* ADC/PGA desired size */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_ADC,
+ ee->ee_adc_desired_size[ee_mode]);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+ AR5K_PHY_DESIRED_SIZE_PGA,
+ ee->ee_pga_desired_size[ee_mode]);
+
+ /* Tx/Rx margin */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx[ee_mode]);
+ }
+
+ /* XPA delays */
+ ath5k_hw_reg_write(ah,
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
+
+ /* XLNA delay */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
+ AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
+ ee->ee_tx_end2xlna_enable[ee_mode]);
+
+ /* Thresh64 (ANI) */
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
+ AR5K_PHY_NF_THRESH62,
+ ee->ee_thr_62[ee_mode]);
+
+
+ /* False detect backoff for channels
+ * that have spur noise. Write the new
+ * cyclic power RSSI threshold. */
+ if (ath5k_hw_chan_has_spur_noise(ah, channel))
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1 +
+ ee->ee_false_detect[ee_mode]);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+ AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+ AR5K_INIT_CYCRSSI_THR1);
+
+ /* I/Q correction
+ * TODO: Per channel i/q infos ? */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CORR_ENABLE |
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+ ee->ee_q_cal[ee_mode]);
+
+ /* Heavy clipping -disable for now */
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
+ ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
+
+ return;
+}
+
+/*
+ * Main reset function
+ */
+int ath5k_hw_reset(struct ath5k_hw *ah,
+ struct net80211_channel *channel, int change_channel)
+{
+ u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
+ u32 phy_tst1;
+ u8 mode, freq, ee_mode, ant[2];
+ int i, ret;
+
+ s_ant = 0;
+ ee_mode = 0;
+ staid1_flags = 0;
+ tsf_up = 0;
+ tsf_lo = 0;
+ freq = 0;
+ mode = 0;
+
+ /*
+ * Save some registers before a reset
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+
+ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+ mode = AR5K_MODE_11A;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case CHANNEL_G:
+ mode = AR5K_MODE_11G;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_B:
+ mode = AR5K_MODE_11B;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ break;
+ case CHANNEL_T:
+ mode = AR5K_MODE_11A_TURBO;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case CHANNEL_TG:
+ if (ah->ah_version == AR5K_AR5211) {
+ DBG("ath5k: TurboG not available on 5211\n");
+ return -EINVAL;
+ }
+ mode = AR5K_MODE_11G_TURBO;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_XR:
+ if (ah->ah_version == AR5K_AR5211) {
+ DBG("ath5k: XR mode not available on 5211\n");
+ return -EINVAL;
+ }
+ mode = AR5K_MODE_XR;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ DBG("ath5k: invalid channel (%d MHz)\n",
+ channel->center_freq);
+ return -EINVAL;
+ }
+
+ if (change_channel) {
+ /*
+ * Save frame sequence count
+ * For revs. after Oahu, only save
+ * seq num for DCU 0 (Global seq num)
+ */
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+ for (i = 0; i < 10; i++)
+ s_seq[i] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(i));
+
+ } else {
+ s_seq[0] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+ }
+
+ /* Save default antenna */
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ if (ah->ah_version == AR5K_AR5212) {
+ /* Since we are going to write rf buffer
+ * check if we have any pending gain_F
+ * optimization settings */
+ if (change_channel && ah->ah_rf_banks != NULL)
+ ath5k_hw_gainf_calibrate(ah);
+ }
+ }
+
+ /*GPIOs*/
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_LEDSTATE;
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ /* AR5K_STA_ID1 flags, only preserve antenna
+ * settings and ack/cts rate mode */
+ staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
+ (AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_DESC_ANTENNA |
+ AR5K_STA_ID1_RTS_DEF_ANTENNA |
+ AR5K_STA_ID1_ACKCTS_6MB |
+ AR5K_STA_ID1_BASE_RATE_11B |
+ AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+ /* Wakeup the device */
+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, 0);
+ if (ret)
+ return ret;
+
+ /* PHY access enable */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ else
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
+ AR5K_PHY(0));
+
+ /* Write initial settings */
+ ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+ if (ret)
+ return ret;
+
+ /*
+ * 5211/5212 Specific
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+
+ /*
+ * Write initial RF gain settings
+ * This should work for both 5111/5112
+ */
+ ret = ath5k_hw_rfgain_init(ah, freq);
+ if (ret)
+ return ret;
+
+ mdelay(1);
+
+ /*
+ * Tweak initval settings for revised
+ * chipsets and add some more config
+ * bits
+ */
+ ath5k_hw_tweak_initval_settings(ah, channel);
+
+ /*
+ * Set TX power (FIXME)
+ */
+ ret = ath5k_hw_txpower(ah, channel, ee_mode,
+ AR5K_TUNE_DEFAULT_TXPOWER);
+ if (ret)
+ return ret;
+
+ /* Write rate duration table only on AR5212 */
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_write_rate_duration(ah, mode);
+
+ /*
+ * Write RF buffer
+ */
+ ret = ath5k_hw_rfregs_init(ah, channel, mode);
+ if (ret)
+ return ret;
+
+
+ /* Write OFDM timings on 5212*/
+ if (ah->ah_version == AR5K_AR5212 &&
+ channel->hw_value & CHANNEL_OFDM) {
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ if (ret)
+ return ret;
+ }
+
+ /*Enable/disable 802.11b mode on 5111
+ (enable 2111 frequency converter + CCK)*/
+ if (ah->ah_radio == AR5K_RF5111) {
+ if (mode == AR5K_MODE_11B)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ }
+
+ /*
+ * In case a fixed antenna was set as default
+ * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
+ * registers.
+ */
+ if (s_ant != 0) {
+ if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_A;
+ else /* 2 - Aux */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_B;
+ } else {
+ ant[0] = AR5K_ANT_FIXED_A;
+ ant[1] = AR5K_ANT_FIXED_B;
+ }
+
+ /* Commit values from EEPROM */
+ ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
+
+ } else {
+ /*
+ * For 5210 we do all initialization using
+ * initvals, so we don't have to modify
+ * any settings (5210 also only supports
+ * a/aturbo modes)
+ */
+ mdelay(1);
+ /* Disable phy and wait */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+ mdelay(1);
+ }
+
+ /*
+ * Restore saved values
+ */
+
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+
+ if (change_channel) {
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ for (i = 0; i < 10; i++)
+ ath5k_hw_reg_write(ah, s_seq[i],
+ AR5K_QUEUE_DCU_SEQNUM(i));
+ } else {
+ ath5k_hw_reg_write(ah, s_seq[0],
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+ }
+
+ ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
+ }
+
+ /* Ledstate */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+
+ /* Gpio settings */
+ ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
+ ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
+
+ /* Restore sta_id flags and preserve our mac address*/
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
+ AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
+ AR5K_STA_ID1);
+
+
+ /*
+ * Configure PCU
+ */
+
+ /* Restore bssid and bssid mask */
+ /* XXX: add ah->aid once mac80211 gives this to us */
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+
+ /* Set PCU config */
+ ath5k_hw_set_opmode(ah);
+
+ /* Clear any pending interrupts
+ * PISR/SISR Not available on 5210 */
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+
+ /* Set RSSI/BRSSI thresholds
+ *
+ * Note: If we decide to set this value
+ * dynamicaly, have in mind that when AR5K_RSSI_THR
+ * register is read it might return 0x40 if we haven't
+ * wrote anything to it plus BMISS RSSI threshold is zeroed.
+ * So doing a save/restore procedure here isn't the right
+ * choice. Instead store it on ath5k_hw */
+ ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
+ AR5K_TUNE_BMISS_THRES <<
+ AR5K_RSSI_THR_BMISS_S),
+ AR5K_RSSI_THR);
+
+ /* MIC QoS support */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+ ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+ ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+ }
+
+ /* QoS NOACK Policy */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+ AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
+ AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+ AR5K_QOS_NOACK);
+ }
+
+
+ /*
+ * Configure PHY
+ */
+
+ /* Set channel on PHY */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable the PHY and wait until completion
+ * This includes BaseBand and Synthesizer
+ * activation.
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+ /*
+ * On 5211+ read activation -> rx delay
+ * and use it.
+ *
+ * TODO: Half/quarter rate support
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ u32 delay;
+ delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ AR5K_PHY_RX_DELAY_M;
+ delay = (channel->hw_value & CHANNEL_CCK) ?
+ ((delay << 2) / 22) : (delay / 10);
+
+ udelay(100 + (2 * delay));
+ } else {
+ mdelay(1);
+ }
+
+ /*
+ * Perform ADC test to see if baseband is ready
+ * Set tx hold and check adc test register
+ */
+ phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+ ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
+ for (i = 0; i <= 20; i++) {
+ if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
+ break;
+ udelay(200);
+ }
+ ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
+
+ /*
+ * Start automatic gain control calibration
+ *
+ * During AGC calibration RX path is re-routed to
+ * a power detector so we don't receive anything.
+ *
+ * This method is used to calibrate some static offsets
+ * used together with on-the fly I/Q calibration (the
+ * one performed via ath5k_hw_phy_calibrate), that doesn't
+ * interrupt rx path.
+ *
+ * While rx path is re-routed to the power detector we also
+ * start a noise floor calibration, to measure the
+ * card's noise floor (the noise we measure when we are not
+ * transmiting or receiving anything).
+ *
+ * If we are in a noisy environment AGC calibration may time
+ * out and/or noise floor calibration might timeout.
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL);
+
+ /* At the same time start I/Q calibration for QAM constellation
+ * -no need for CCK- */
+ ah->ah_calibration = 0;
+ if (!(mode == AR5K_MODE_11B)) {
+ ah->ah_calibration = 1;
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_RUN);
+ }
+
+ /* Wait for gain calibration to finish (we check for I/Q calibration
+ * during ath5k_phy_calibrate) */
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, 0)) {
+ DBG("ath5k: gain calibration timeout (%d MHz)\n",
+ channel->center_freq);
+ }
+
+ /*
+ * If we run NF calibration before AGC, it always times out.
+ * Binary HAL starts NF and AGC calibration at the same time
+ * and only waits for AGC to finish. Also if AGC or NF cal.
+ * times out, reset doesn't fail on binary HAL. I believe
+ * that's wrong because since rx path is routed to a detector,
+ * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
+ * enables noise floor calibration after offset calibration and if noise
+ * floor calibration fails, reset fails. I believe that's
+ * a better approach, we just need to find a polling interval
+ * that suits best, even if reset continues we need to make
+ * sure that rx path is ready.
+ */
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+
+ /*
+ * Configure QCUs/DCUs
+ */
+
+ /* TODO: HW Compression support for data queues */
+ /* TODO: Burst prefetch for data queues */
+
+ /*
+ * Reset queues and start beacon timers at the end of the reset routine
+ * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+ * Note: If we want we can assign multiple qcus on one dcu.
+ */
+ ret = ath5k_hw_reset_tx_queue(ah);
+ if (ret) {
+ DBG("ath5k: failed to reset TX queue\n");
+ return ret;
+ }
+
+ /*
+ * Configure DMA/Interrupts
+ */
+
+ /*
+ * Set Rx/Tx DMA Configuration
+ *
+ * Set standard DMA size (128). Note that
+ * a DMA size of 512 causes rx overruns and tx errors
+ * on pci-e cards (tested on 5424 but since rx overruns
+ * also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_set_imr(ah, ah->ah_imr);
+
+ /*
+ * Setup RFKill interrupt if rfkill flag is set on eeprom.
+ * TODO: Use gpio pin and polarity infos from eeprom
+ * TODO: Handle this in ath5k_intr because it'll result
+ * a nasty interrupt storm.
+ */
+#if 0
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
+ ath5k_hw_set_gpio_input(ah, 0);
+ ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
+ if (ah->ah_gpio[0] == 0)
+ ath5k_hw_set_gpio_intr(ah, 0, 1);
+ else
+ ath5k_hw_set_gpio_intr(ah, 0, 0);
+ }
+#endif
+
+ /*
+ * Disable beacons and reset the register
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
+ AR5K_BEACON_RESET_TSF);
+
+ return 0;
+}
+
+#undef _ATH5K_RESET
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/base.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/base.h
new file mode 100644
index 0000000..45dad07
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/base.h
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
+ * Original from Linux kernel 2.6.30.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+/*
+ * Defintions for the Atheros Wireless LAN controller driver.
+ */
+#ifndef _DEV_ATH_ATHVAR_H
+#define _DEV_ATH_ATHVAR_H
+
+FILE_LICENCE ( BSD3 );
+
+#include "ath5k.h"
+#include <gpxe/iobuf.h>
+
+#define ATH_RXBUF 16 /* number of RX buffers */
+#define ATH_TXBUF 16 /* number of TX buffers */
+
+struct ath5k_buf {
+ struct list_head list;
+ unsigned int flags; /* rx descriptor flags */
+ struct ath5k_desc *desc; /* virtual addr of desc */
+ u32 daddr; /* physical addr of desc */
+ struct io_buffer *iob; /* I/O buffer for buf */
+ u32 iobaddr;/* physical addr of iob data */
+};
+
+/*
+ * Data transmit queue state. One of these exists for each
+ * hardware transmit queue. Packets sent to us from above
+ * are assigned to queues based on their priority. Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+ unsigned int qnum; /* hardware q number */
+ u32 *link; /* link ptr in last TX desc */
+ struct list_head q; /* transmit queue */
+ int setup;
+};
+
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX (26+26+26+200+200)
+#else
+#define ATH_CHAN_MAX (14+14+14+252+20)
+#endif
+
+/* Software Carrier, keeps track of the driver state
+ * associated with an instance of a device */
+struct ath5k_softc {
+ struct pci_device *pdev; /* for dma mapping */
+ void *iobase; /* address of the device */
+ struct net80211_device *dev; /* IEEE 802.11 common */
+ struct ath5k_hw *ah; /* Atheros HW */
+ struct net80211_hw_info *hwinfo;
+ int curband;
+ int irq_ena; /* interrupts enabled */
+
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
+ struct ath5k_desc *desc; /* TX/RX descriptors */
+ u32 desc_daddr; /* DMA (physical) address */
+ size_t desc_len; /* size of TX/RX descriptors */
+ u16 cachelsz; /* cache line size */
+
+ int status;
+#define ATH_STAT_INVALID 0x01 /* disable hardware accesses */
+#define ATH_STAT_MRRETRY 0x02 /* multi-rate retry support */
+#define ATH_STAT_PROMISC 0x04
+#define ATH_STAT_LEDSOFT 0x08 /* enable LED gpio status */
+#define ATH_STAT_STARTED 0x10 /* opened & irqs enabled */
+
+ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
+ unsigned int curmode; /* current phy mode */
+ struct net80211_channel *curchan; /* current h/w channel */
+
+ enum ath5k_int imask; /* interrupt mask copy */
+
+ u8 bssidmask[ETH_ALEN];
+
+ unsigned int rxbufsize; /* rx size based on mtu */
+ struct list_head rxbuf; /* receive buffer */
+ u32 *rxlink; /* link ptr in last RX desc */
+
+ struct list_head txbuf; /* transmit buffer */
+ unsigned int txbuf_len; /* buf count in txbuf list */
+ struct ath5k_txq txq; /* tx queue */
+
+ int last_calib_ticks;
+
+ int power_level; /* Requested tx power in dbm */
+ int assoc; /* assocate state */
+
+ int hw_rate; /* Hardware tx rate code */
+ int hw_rtscts_rate; /* Hardware rts/cts rate code */
+};
+
+#define ath5k_hw_hasbssidmask(_ah) \
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
+#define ath5k_hw_hasveol(_ah) \
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/desc.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/desc.h
new file mode 100644
index 0000000..6e11b0d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/desc.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Internal RX/TX descriptor structures
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
+ */
+
+/*
+ * common hardware RX control descriptor
+ */
+struct ath5k_hw_rx_ctl {
+ u32 rx_control_0; /* RX control word 0 */
+ u32 rx_control_1; /* RX control word 1 */
+} __attribute__ ((packed));
+
+/* RX control word 0 field/sflags */
+#define AR5K_DESC_RX_CTL0 0x00000000
+
+/* RX control word 1 fields/flags */
+#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff
+#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000
+
+/*
+ * common hardware RX status descriptor
+ * 5210/11 and 5212 differ only in the flags defined below
+ */
+struct ath5k_hw_rx_status {
+ u32 rx_status_0; /* RX status word 0 */
+ u32 rx_status_1; /* RX status word 1 */
+} __attribute__ ((packed));
+
+/* 5210/5211 */
+/* RX status word 0 fields/flags */
+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
+
+/* RX status word 1 fields/flags */
+#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
+
+/* 5212 */
+/* RX status word 0 fields/flags */
+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
+
+/* RX status word 1 fields/flags */
+#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010
+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
+
+/*
+ * common hardware RX error descriptor
+ */
+struct ath5k_hw_rx_error {
+ u32 rx_error_0; /* RX status word 0 */
+ u32 rx_error_1; /* RX status word 1 */
+} __attribute__ ((packed));
+
+/* RX error word 0 fields/flags */
+#define AR5K_RX_DESC_ERROR0 0x00000000
+
+/* RX error word 1 fields/flags */
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
+
+/* PHY Error codes */
+#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
+#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
+#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
+#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60
+#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80
+#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0
+#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
+#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
+
+/*
+ * 5210/5211 hardware 2-word TX control descriptor
+ */
+struct ath5k_hw_2w_tx_ctl {
+ u32 tx_control_0; /* TX control word 0 */
+ u32 tx_control_1; /* TX control word 1 */
+} __attribute__ ((packed));
+
+/* TX control word 0 fields/flags */
+#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18
+#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000
+#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000
+#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \
+ (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
+#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000
+#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
+
+/* TX control word 1 fields/flags */
+#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff
+#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \
+ (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20
+#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/
+
+/* Frame types */
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
+
+/*
+ * 5212 hardware 4-word TX control descriptor
+ */
+struct ath5k_hw_4w_tx_ctl {
+ u32 tx_control_0; /* TX control word 0 */
+
+#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16
+#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000
+#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000
+#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
+#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000
+#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
+#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000
+
+ u32 tx_control_1; /* TX control word 1 */
+
+#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff
+#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20
+#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29
+
+ u32 tx_control_2; /* TX control word 2 */
+
+#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff
+#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28
+
+ u32 tx_control_3; /* TX control word 3 */
+
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20
+} __attribute__ ((packed));
+
+/*
+ * Common TX status descriptor
+ */
+struct ath5k_hw_tx_status {
+ u32 tx_status_0; /* TX status word 0 */
+ u32 tx_status_1; /* TX status word 1 */
+} __attribute__ ((packed));
+
+/* TX status word 0 fields/flags */
+#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001
+#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002
+#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004
+#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008
+/*???
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4
+*/
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4
+/*???
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8
+*/
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16
+
+/* TX status word 1 fields/flags */
+#define AR5K_DESC_TX_STATUS1_DONE 0x00000001
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21
+#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000
+#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000
+
+/*
+ * 5210/5211 hardware TX descriptor
+ */
+struct ath5k_hw_5210_tx_desc {
+ struct ath5k_hw_2w_tx_ctl tx_ctl;
+ struct ath5k_hw_tx_status tx_stat;
+} __attribute__ ((packed));
+
+/*
+ * 5212 hardware TX descriptor
+ */
+struct ath5k_hw_5212_tx_desc {
+ struct ath5k_hw_4w_tx_ctl tx_ctl;
+ struct ath5k_hw_tx_status tx_stat;
+} __attribute__ ((packed));
+
+/*
+ * common hardware RX descriptor
+ */
+struct ath5k_hw_all_rx_desc {
+ struct ath5k_hw_rx_ctl rx_ctl;
+ union {
+ struct ath5k_hw_rx_status rx_stat;
+ struct ath5k_hw_rx_error rx_err;
+ } u;
+} __attribute__ ((packed));
+
+/*
+ * Atheros hardware descriptor
+ * This is read and written to by the hardware
+ */
+struct ath5k_desc {
+ u32 ds_link; /* physical address of the next descriptor */
+ u32 ds_data; /* physical address of data buffer (skb) */
+
+ union {
+ struct ath5k_hw_5210_tx_desc ds_tx5210;
+ struct ath5k_hw_5212_tx_desc ds_tx5212;
+ struct ath5k_hw_all_rx_desc ds_rx;
+ } ud;
+} __attribute__ ((packed));
+
+#define AR5K_RXDESC_INTREQ 0x0020
+
+#define AR5K_TXDESC_CLRDMASK 0x0001
+#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
+#define AR5K_TXDESC_RTSENA 0x0004
+#define AR5K_TXDESC_CTSENA 0x0008
+#define AR5K_TXDESC_INTREQ 0x0010
+#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/eeprom.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/eeprom.h
new file mode 100644
index 0000000..4d6250a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/eeprom.h
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
+ */
+#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
+#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
+#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
+#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
+#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
+
+#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
+#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
+#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
+#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
+#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
+#define AR5K_EEPROM_INFO_CKSUM 0xffff
+#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
+
+#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
+#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
+#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */
+#define AR5K_EEPROM_VERSION_4_4 0x4004
+#define AR5K_EEPROM_VERSION_4_5 0x4005
+#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
+#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */
+#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */
+#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */
+#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */
+#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */
+
+#define AR5K_EEPROM_MODE_11A 0
+#define AR5K_EEPROM_MODE_11B 1
+#define AR5K_EEPROM_MODE_11G 2
+
+#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
+#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
+#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
+#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
+#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
+#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
+
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
+/* Newer EEPROMs are using a different offset */
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
+ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
+
+#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff))
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4)
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1)
+#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1)
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+
+#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1)
+
+#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6)
+#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff)
+#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7)
+#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f)
+#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8)
+#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff)
+#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3)
+#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3)
+
+#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9)
+#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1)
+#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1)
+#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1)
+#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1)
+#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf)
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf)
+
+#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
+#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8)
+#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8)
+#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1)
+#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1)
+#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1)
+#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1)
+
+/* calibration settings */
+#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
+#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
+#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
+#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
+#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */
+#define AR5K_EEPROM_GROUP1_OFFSET 0x0
+#define AR5K_EEPROM_GROUP2_OFFSET 0x5
+#define AR5K_EEPROM_GROUP3_OFFSET 0x37
+#define AR5K_EEPROM_GROUP4_OFFSET 0x46
+#define AR5K_EEPROM_GROUP5_OFFSET 0x55
+#define AR5K_EEPROM_GROUP6_OFFSET 0x65
+#define AR5K_EEPROM_GROUP7_OFFSET 0x69
+#define AR5K_EEPROM_GROUP8_OFFSET 0x6f
+
+#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
+
+/* [3.1 - 3.3] */
+#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
+#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
+
+#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
+
+/* Some EEPROM defines */
+#define AR5K_EEPROM_EEP_SCALE 100
+#define AR5K_EEPROM_EEP_DELTA 10
+#define AR5K_EEPROM_N_MODES 3
+#define AR5K_EEPROM_N_5GHZ_CHAN 10
+#define AR5K_EEPROM_N_2GHZ_CHAN 3
+#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
+#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4
+#define AR5K_EEPROM_MAX_CHAN 10
+#define AR5K_EEPROM_N_PWR_POINTS_5111 11
+#define AR5K_EEPROM_N_PCDAC 11
+#define AR5K_EEPROM_N_PHASE_CAL 5
+#define AR5K_EEPROM_N_TEST_FREQ 8
+#define AR5K_EEPROM_N_EDGES 8
+#define AR5K_EEPROM_N_INTERCEPTS 11
+#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
+#define AR5K_EEPROM_PCDAC_M 0x3f
+#define AR5K_EEPROM_PCDAC_START 1
+#define AR5K_EEPROM_PCDAC_STOP 63
+#define AR5K_EEPROM_PCDAC_STEP 1
+#define AR5K_EEPROM_NON_EDGE_M 0x40
+#define AR5K_EEPROM_CHANNEL_POWER 8
+#define AR5K_EEPROM_N_OBDB 4
+#define AR5K_EEPROM_OBDB_DIS 0xffff
+#define AR5K_EEPROM_CHANNEL_DIS 0xff
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
+#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
+#define AR5K_EEPROM_MAX_CTLS 32
+#define AR5K_EEPROM_N_PD_CURVES 4
+#define AR5K_EEPROM_N_XPD0_POINTS 4
+#define AR5K_EEPROM_N_XPD3_POINTS 3
+#define AR5K_EEPROM_N_PD_GAINS 4
+#define AR5K_EEPROM_N_PD_POINTS 5
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
+#define AR5K_EEPROM_POWER_M 0x3f
+#define AR5K_EEPROM_POWER_MIN 0
+#define AR5K_EEPROM_POWER_MAX 3150
+#define AR5K_EEPROM_POWER_STEP 50
+#define AR5K_EEPROM_POWER_TABLE_SIZE 64
+#define AR5K_EEPROM_N_POWER_LOC_11B 4
+#define AR5K_EEPROM_N_POWER_LOC_11G 6
+#define AR5K_EEPROM_I_GAIN 10
+#define AR5K_EEPROM_CCK_OFDM_DELTA 15
+#define AR5K_EEPROM_N_IQ_CAL 2
+
+#define AR5K_EEPROM_READ(_o, _v) do { \
+ ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \
+ if (ret) \
+ return ret; \
+} while (0)
+
+#define AR5K_EEPROM_READ_HDR(_o, _v) \
+ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
+
+enum ath5k_ant_setting {
+ AR5K_ANT_VARIABLE = 0, /* variable by programming */
+ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
+ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
+ AR5K_ANT_MAX = 3,
+};
+
+enum ath5k_ctl_mode {
+ AR5K_CTL_11A = 0,
+ AR5K_CTL_11B = 1,
+ AR5K_CTL_11G = 2,
+ AR5K_CTL_TURBO = 3,
+ AR5K_CTL_TURBOG = 4,
+ AR5K_CTL_2GHT20 = 5,
+ AR5K_CTL_5GHT20 = 6,
+ AR5K_CTL_2GHT40 = 7,
+ AR5K_CTL_5GHT40 = 8,
+ AR5K_CTL_MODE_M = 15,
+};
+
+/* Default CTL ids for the 3 main reg domains.
+ * Atheros only uses these by default but vendors
+ * can have up to 32 different CTLs for different
+ * scenarios. Note that theese values are ORed with
+ * the mode id (above) so we can have up to 24 CTL
+ * datasets out of these 3 main regdomains. That leaves
+ * 8 ids that can be used by vendors and since 0x20 is
+ * missing from HAL sources i guess this is the set of
+ * custom CTLs vendors can use. */
+#define AR5K_CTL_FCC 0x10
+#define AR5K_CTL_CUSTOM 0x20
+#define AR5K_CTL_ETSI 0x30
+#define AR5K_CTL_MKK 0x40
+
+/* Indicates a CTL with only mode set and
+ * no reg domain mapping, such CTLs are used
+ * for world roaming domains or simply when
+ * a reg domain is not set */
+#define AR5K_CTL_NO_REGDOMAIN 0xf0
+
+/* Indicates an empty (invalid) CTL */
+#define AR5K_CTL_NO_CTL 0xff
+
+/* Per channel calibration data, used for power table setup */
+struct ath5k_chan_pcal_info_rf5111 {
+ /* Power levels in half dbm units
+ * for one power curve. */
+ u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
+ /* PCDAC table steps
+ * for the above values */
+ u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
+ /* Starting PCDAC step */
+ u8 pcdac_min;
+ /* Final PCDAC step */
+ u8 pcdac_max;
+};
+
+struct ath5k_chan_pcal_info_rf5112 {
+ /* Power levels in quarter dBm units
+ * for lower (0) and higher (3)
+ * level curves in 0.25dB units */
+ s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
+ s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
+ /* PCDAC table steps
+ * for the above values */
+ u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
+ u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
+};
+
+struct ath5k_chan_pcal_info_rf2413 {
+ /* Starting pwr/pddac values */
+ s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
+ u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
+ /* (pwr,pddac) points
+ * power levels in 0.5dB units */
+ s8 pwr[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_N_PD_POINTS];
+ u8 pddac[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_N_PD_POINTS];
+};
+
+enum ath5k_powertable_type {
+ AR5K_PWRTABLE_PWR_TO_PCDAC = 0,
+ AR5K_PWRTABLE_LINEAR_PCDAC = 1,
+ AR5K_PWRTABLE_PWR_TO_PDADC = 2,
+};
+
+struct ath5k_pdgain_info {
+ u8 pd_points;
+ u8 *pd_step;
+ /* Power values are in
+ * 0.25dB units */
+ s16 *pd_pwr;
+};
+
+struct ath5k_chan_pcal_info {
+ /* Frequency */
+ u16 freq;
+ /* Tx power boundaries */
+ s16 max_pwr;
+ s16 min_pwr;
+ union {
+ struct ath5k_chan_pcal_info_rf5111 rf5111_info;
+ struct ath5k_chan_pcal_info_rf5112 rf5112_info;
+ struct ath5k_chan_pcal_info_rf2413 rf2413_info;
+ };
+ /* Raw values used by phy code
+ * Curves are stored in order from lower
+ * gain to higher gain (max txpower -> min txpower) */
+ struct ath5k_pdgain_info *pd_curves;
+};
+
+/* Per rate calibration data for each mode,
+ * used for rate power table setup.
+ * Note: Values in 0.5dB units */
+struct ath5k_rate_pcal_info {
+ u16 freq; /* Frequency */
+ /* Power level for 6-24Mbit/s rates or
+ * 1Mb rate */
+ u16 target_power_6to24;
+ /* Power level for 36Mbit rate or
+ * 2Mb rate */
+ u16 target_power_36;
+ /* Power level for 48Mbit rate or
+ * 5.5Mbit rate */
+ u16 target_power_48;
+ /* Power level for 54Mbit rate or
+ * 11Mbit rate */
+ u16 target_power_54;
+};
+
+/* Power edges for conformance test limits */
+struct ath5k_edge_power {
+ u16 freq;
+ u16 edge; /* in half dBm */
+ int flag;
+};
+
+/* EEPROM calibration data */
+struct ath5k_eeprom_info {
+
+ /* Header information */
+ u16 ee_magic;
+ u16 ee_protect;
+ u16 ee_regdomain;
+ u16 ee_version;
+ u16 ee_header;
+ u16 ee_ant_gain;
+ u16 ee_misc0;
+ u16 ee_misc1;
+ u16 ee_misc2;
+ u16 ee_misc3;
+ u16 ee_misc4;
+ u16 ee_misc5;
+ u16 ee_misc6;
+ u16 ee_cck_ofdm_gain_delta;
+ u16 ee_cck_ofdm_power_delta;
+ u16 ee_scaled_cck_delta;
+
+ /* RF Calibration settings (reset, rfregs) */
+ u16 ee_i_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_q_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
+ u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
+ u16 ee_xr_power[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
+ u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
+ u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_thr_62[AR5K_EEPROM_N_MODES];
+ u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_xpd[AR5K_EEPROM_N_MODES];
+ u16 ee_x_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_i_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+ u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+
+ /* Power calibration data */
+ u16 ee_false_detect[AR5K_EEPROM_N_MODES];
+
+ /* Number of pd gain curves per mode */
+ u8 ee_pd_gains[AR5K_EEPROM_N_MODES];
+ /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */
+ u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS];
+
+ u8 ee_n_piers[AR5K_EEPROM_N_MODES];
+ struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
+ struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+ struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+
+ /* Per rate target power levels */
+ u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+
+ /* Conformance test limits (Unused) */
+ u8 ee_ctls;
+ u8 ee_ctl[AR5K_EEPROM_MAX_CTLS];
+ struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
+
+ /* Noise Floor Calibration settings */
+ s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
+ s8 ee_pd_gain_overlap;
+
+ u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+};
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/reg.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/reg.h
new file mode 100644
index 0000000..7070d15
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/reg.h
@@ -0,0 +1,2589 @@
+/*
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
+ * maintained by Reyk Floeter
+ *
+ * I tried to document those registers by looking at ar5k code, some
+ * 802.11 (802.11e mostly) papers and by reading various public available
+ * Atheros presentations and papers like these:
+ *
+ * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
+ * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
+ *
+ * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
+ *
+ * This file also contains register values found on a memory dump of
+ * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal
+ * released by Atheros and on various debug messages found on the net.
+ */
+
+
+
+/*====MAC DMA REGISTERS====*/
+
+/*
+ * AR5210-Specific TXDP registers
+ * 5210 has only 2 transmit queues so no DCU/QCU, just
+ * 2 transmit descriptor pointers...
+ */
+#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */
+#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */
+
+/*
+ * Mac Control Register
+ */
+#define AR5K_CR 0x0008 /* Register Address */
+#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */
+#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */
+#define AR5K_CR_RXE 0x00000004 /* RX Enable */
+#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */
+#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */
+#define AR5K_CR_RXD 0x00000020 /* RX Disable */
+#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */
+
+/*
+ * RX Descriptor Pointer register
+ */
+#define AR5K_RXDP 0x000c
+
+/*
+ * Configuration and status register
+ */
+#define AR5K_CFG 0x0014 /* Register Address */
+#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */
+#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */
+#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
+#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
+#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
+#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
+#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
+#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
+#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
+#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */
+#define AR5K_CFG_TXCNT_S 11
+#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */
+#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */
+#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */
+#define AR5K_CFG_PCI_THRES_S 17
+
+/*
+ * Interrupt enable register
+ */
+#define AR5K_IER 0x0024 /* Register Address */
+#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */
+#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */
+
+
+/*
+ * 0x0028 is Beacon Control Register on 5210
+ * and first RTS duration register on 5211
+ */
+
+/*
+ * Beacon control register [5210]
+ */
+#define AR5K_BCR 0x0028 /* Register Address */
+#define AR5K_BCR_AP 0x00000000 /* AP mode */
+#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */
+#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */
+#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */
+#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */
+#define AR5K_BCR_BCGET 0x00000010
+
+/*
+ * First RTS duration register [5211]
+ */
+#define AR5K_RTSD0 0x0028 /* Register Address */
+#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */
+#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */
+#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/
+#define AR5K_RTSD0_9_S 8
+#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/
+#define AR5K_RTSD0_12_S 16
+#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/
+#define AR5K_RTSD0_18_S 24
+
+
+/*
+ * 0x002c is Beacon Status Register on 5210
+ * and second RTS duration register on 5211
+ */
+
+/*
+ * Beacon status register [5210]
+ *
+ * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
+ * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
+ * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
+ * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
+ * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
+ * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
+ */
+#define AR5K_BSR 0x002c /* Register Address */
+#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */
+#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */
+#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */
+#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */
+#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */
+#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */
+#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */
+#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */
+#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */
+#define AR5K_BSR_SWBA_CNT 0x00ff0000
+
+/*
+ * Second RTS duration register [5211]
+ */
+#define AR5K_RTSD1 0x002c /* Register Address */
+#define AR5K_RTSD1_24 0x000000ff /* 24Mb */
+#define AR5K_RTSD1_24_S 0
+#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */
+#define AR5K_RTSD1_36_S 8
+#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */
+#define AR5K_RTSD1_48_S 16
+#define AR5K_RTSD1_54 0xff000000 /* 54Mb */
+#define AR5K_RTSD1_54_S 24
+
+
+/*
+ * Transmit configuration register
+ */
+#define AR5K_TXCFG 0x0030 /* Register Address */
+#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */
+#define AR5K_TXCFG_SDMAMR_S 0
+#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
+#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
+#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL_S 4
+#define AR5K_TXCFG_TXFULL_0B 0x00000000
+#define AR5K_TXCFG_TXFULL_64B 0x00000010
+#define AR5K_TXCFG_TXFULL_128B 0x00000020
+#define AR5K_TXCFG_TXFULL_192B 0x00000030
+#define AR5K_TXCFG_TXFULL_256B 0x00000040
+#define AR5K_TXCFG_TXCONT_EN 0x00000080
+#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */
+#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */
+#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */
+#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */
+#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */
+#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
+#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */
+#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */
+#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */
+#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */
+
+/*
+ * Receive configuration register
+ */
+#define AR5K_RXCFG 0x0034 /* Register Address */
+#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */
+#define AR5K_RXCFG_SDMAMW_S 0
+#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */
+#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */
+#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */
+#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */
+#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */
+
+/*
+ * Receive jumbo descriptor last address register
+ * Only found in 5211 (?)
+ */
+#define AR5K_RXJLA 0x0038
+
+/*
+ * MIB control register
+ */
+#define AR5K_MIBC 0x0040 /* Register Address */
+#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */
+#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */
+#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */
+#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */
+
+/*
+ * Timeout prescale register
+ */
+#define AR5K_TOPS 0x0044
+#define AR5K_TOPS_M 0x0000ffff
+
+/*
+ * Receive timeout register (no frame received)
+ */
+#define AR5K_RXNOFRM 0x0048
+#define AR5K_RXNOFRM_M 0x000003ff
+
+/*
+ * Transmit timeout register (no frame sent)
+ */
+#define AR5K_TXNOFRM 0x004c
+#define AR5K_TXNOFRM_M 0x000003ff
+#define AR5K_TXNOFRM_QCU 0x000ffc00
+#define AR5K_TXNOFRM_QCU_S 10
+
+/*
+ * Receive frame gap timeout register
+ */
+#define AR5K_RPGTO 0x0050
+#define AR5K_RPGTO_M 0x000003ff
+
+/*
+ * Receive frame count limit register
+ */
+#define AR5K_RFCNT 0x0054
+#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */
+#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */
+
+/*
+ * Misc settings register
+ * (reserved0-3)
+ */
+#define AR5K_MISC 0x0058 /* Register Address */
+#define AR5K_MISC_DMA_OBS_M 0x000001e0
+#define AR5K_MISC_DMA_OBS_S 5
+#define AR5K_MISC_MISC_OBS_M 0x00000e00
+#define AR5K_MISC_MISC_OBS_S 9
+#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000
+#define AR5K_MISC_MAC_OBS_LSB_S 12
+#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000
+#define AR5K_MISC_MAC_OBS_MSB_S 15
+#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */
+#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */
+
+/*
+ * QCU/DCU clock gating register (5311)
+ * (reserved4-5)
+ */
+#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */
+#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */
+#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */
+
+/*
+ * Interrupt Status Registers
+ *
+ * For 5210 there is only one status register but for
+ * 5211/5212 we have one primary and 4 secondary registers.
+ * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
+ * Most of these bits are common for all chipsets.
+ */
+#define AR5K_ISR 0x001c /* Register Address [5210] */
+#define AR5K_PISR 0x0080 /* Register Address [5211+] */
+#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */
+#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
+#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
+#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
+#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
+#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
+#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
+#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
+#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
+#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
+#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
+#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
+#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */
+#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */
+#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */
+#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
+#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
+#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
+#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
+#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
+#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */
+#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */
+#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */
+#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
+#define AR5K_ISR_TIM 0x00800000 /* [5211+] */
+#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+ CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */
+#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */
+#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */
+#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
+
+/*
+ * Secondary status registers [5211+] (0 - 4)
+ *
+ * These give the status for each QCU, only QCUs 0-9 are
+ * represented.
+ */
+#define AR5K_SISR0 0x0084 /* Register Address [5211+] */
+#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SISR0_QCU_TXOK_S 0
+#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+#define AR5K_SISR0_QCU_TXDESC_S 16
+
+#define AR5K_SISR1 0x0088 /* Register Address [5211+] */
+#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SISR1_QCU_TXERR_S 0
+#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+#define AR5K_SISR1_QCU_TXEOL_S 16
+
+#define AR5K_SISR2 0x008c /* Register Address [5211+] */
+#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SISR2_QCU_TXURN_S 0
+#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */
+#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */
+#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */
+#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
+#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
+#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */
+#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
+#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
+#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
+#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */
+
+#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
+#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SISR3_QCBRORN_S 0
+#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+#define AR5K_SISR3_QCBRURN_S 16
+
+#define AR5K_SISR4 0x0094 /* Register Address [5211+] */
+#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */
+#define AR5K_SISR4_QTRIG_S 0
+
+/*
+ * Shadow read-and-clear interrupt status registers [5211+]
+ */
+#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */
+#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */
+#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */
+#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */
+#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */
+#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */
+
+/*
+ * Interrupt Mask Registers
+ *
+ * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
+ * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
+ */
+#define AR5K_IMR 0x0020 /* Register Address [5210] */
+#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
+#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/
+#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
+#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
+#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
+#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
+#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
+#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
+#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
+#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
+#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
+#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
+#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
+#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */
+#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/
+#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */
+#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/
+#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */
+#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
+#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
+#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */
+#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/
+#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */
+#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */
+#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */
+#define AR5K_IMR_TIM 0x00800000 /* [5211+] */
+#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+ CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/
+#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */
+#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */
+#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */
+
+/*
+ * Secondary interrupt mask registers [5211+] (0 - 4)
+ */
+#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */
+#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SIMR0_QCU_TXOK_S 0
+#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+#define AR5K_SIMR0_QCU_TXDESC_S 16
+
+#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */
+#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SIMR1_QCU_TXERR_S 0
+#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+#define AR5K_SIMR1_QCU_TXEOL_S 16
+
+#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */
+#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SIMR2_QCU_TXURN_S 0
+#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */
+#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */
+#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */
+#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
+#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
+#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */
+#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */
+#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */
+#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */
+#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */
+
+#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */
+#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SIMR3_QCBRORN_S 0
+#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+#define AR5K_SIMR3_QCBRURN_S 16
+
+#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */
+#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */
+#define AR5K_SIMR4_QTRIG_S 0
+
+/*
+ * DMA Debug registers 0-7
+ * 0xe0 - 0xfc
+ */
+
+/*
+ * Decompression mask registers [5212+]
+ */
+#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */
+#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */
+
+/*
+ * Wake On Wireless pattern control register [5212+]
+ */
+#define AR5K_WOW_PCFG 0x0410 /* Register Address */
+#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */
+#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */
+#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */
+#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */
+#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */
+#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */
+#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */
+#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */
+#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */
+
+/*
+ * Wake On Wireless pattern index register (?) [5212+]
+ */
+#define AR5K_WOW_PAT_IDX 0x0414
+
+/*
+ * Wake On Wireless pattern data register [5212+]
+ */
+#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */
+#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */
+#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */
+#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */
+#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */
+#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */
+#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */
+
+/*
+ * Decompression configuration registers [5212+]
+ */
+#define AR5K_DCCFG 0x0420 /* Register Address */
+#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */
+#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */
+#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */
+#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */
+
+/*
+ * Compression configuration registers [5212+]
+ */
+#define AR5K_CCFG 0x0600 /* Register Address */
+#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */
+#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */
+
+#define AR5K_CCFG_CCU 0x0604 /* Register Address */
+#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */
+#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */
+#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */
+#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */
+#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */
+
+/*
+ * Compression performance counter registers [5212+]
+ */
+#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */
+#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/
+#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */
+#define AR5K_CPC3 0x061c /* Compression performance counter 3 */
+#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */
+
+
+/*
+ * Queue control unit (QCU) registers [5211+]
+ *
+ * Card has 12 TX Queues but i see that only 0-9 are used (?)
+ * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
+ * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
+ * configuration register (0x08c0 - 0x08ec), a ready time configuration
+ * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
+ * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
+ * global registers, QCU transmit enable/disable and "one shot arm (?)"
+ * set/clear, which contain status for all queues (we shift by 1 for each
+ * queue). To access these registers easily we define some macros here
+ * that are used inside HAL. For more infos check out *_tx_queue functs.
+ */
+
+/*
+ * Generic QCU Register access macros
+ */
+#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r)
+#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q))
+#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q))
+
+/*
+ * QCU Transmit descriptor pointer registers
+ */
+#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */
+#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
+
+/*
+ * QCU Transmit enable register
+ */
+#define AR5K_QCU_TXE 0x0840
+#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
+#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
+
+/*
+ * QCU Transmit disable register
+ */
+#define AR5K_QCU_TXD 0x0880
+#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
+#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
+
+/*
+ * QCU Constant Bit Rate configuration registers
+ */
+#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */
+#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */
+#define AR5K_QCU_CBRCFG_INTVAL_S 0
+#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */
+#define AR5K_QCU_CBRCFG_ORN_THRES_S 24
+#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
+
+/*
+ * QCU Ready time configuration registers
+ */
+#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */
+#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */
+#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0
+#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */
+#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
+
+/*
+ * QCU one shot arm set registers
+ */
+#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */
+#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff
+
+/*
+ * QCU one shot arm clear registers
+ */
+#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */
+#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff
+
+/*
+ * QCU misc registers
+ */
+#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
+#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
+#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
+#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
+#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */
+#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */
+#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */
+#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */
+#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */
+#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */
+#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */
+#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */
+#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */
+#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */
+#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */
+#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */
+#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
+
+
+/*
+ * QCU status registers
+ */
+#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */
+#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */
+#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */
+#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
+
+/*
+ * QCU ready time shutdown register
+ */
+#define AR5K_QCU_RDYTIMESHDN 0x0a40
+#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff
+
+/*
+ * QCU compression buffer base registers [5212+]
+ */
+#define AR5K_QCU_CBB_SELECT 0x0b00
+#define AR5K_QCU_CBB_ADDR 0x0b04
+#define AR5K_QCU_CBB_ADDR_S 9
+
+/*
+ * QCU compression buffer configuration register [5212+]
+ * (buffer size)
+ */
+#define AR5K_QCU_CBCFG 0x0b08
+
+
+
+/*
+ * Distributed Coordination Function (DCF) control unit (DCU)
+ * registers [5211+]
+ *
+ * These registers control the various characteristics of each queue
+ * for 802.11e (WME) combatibility so they go together with
+ * QCU registers in pairs. For each queue we have a QCU mask register,
+ * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
+ * a retry limit register (0x1080 - 0x10ac), a channel time register
+ * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
+ * a sequence number register (0x1140 - 0x116c). It seems that "global"
+ * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * We use the same macros here for easier register access.
+ *
+ */
+
+/*
+ * DCU QCU mask registers
+ */
+#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */
+#define AR5K_DCU_QCUMASK_M 0x000003ff
+#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
+
+/*
+ * DCU local Inter Frame Space settings register
+ */
+#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */
+#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */
+#define AR5K_DCU_LCL_IFS_CW_MIN_S 0
+#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */
+#define AR5K_DCU_LCL_IFS_CW_MAX_S 10
+#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */
+#define AR5K_DCU_LCL_IFS_AIFS_S 20
+#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */
+#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
+
+/*
+ * DCU retry limit registers
+ */
+#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0
+#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */
+#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14
+#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
+
+/*
+ * DCU channel time registers
+ */
+#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */
+#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */
+#define AR5K_DCU_CHAN_TIME_DUR_S 0
+#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */
+#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
+
+/*
+ * DCU misc registers [5211+]
+ *
+ * Note: Arbiter lockout control controls the
+ * behaviour on low priority queues when we have multiple queues
+ * with pending frames. Intra-frame lockout means we wait until
+ * the queue's current frame transmits (with post frame backoff and bursting)
+ * before we transmit anything else and global lockout means we
+ * wait for the whole queue to finish before higher priority queues
+ * can transmit (this is used on beacon and CAB queues).
+ * No lockout means there is no special handling.
+ */
+#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */
+#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */
+#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series
+ station RTS/data failure count
+ reset policy (?) */
+#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series
+ CW reset policy */
+#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */
+#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */
+#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */
+#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */
+#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */
+#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */
+#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
+#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1
+#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */
+#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17
+#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */
+#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */
+#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */
+#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */
+#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */
+#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */
+#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */
+#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
+
+/*
+ * DCU frame sequence number registers
+ */
+#define AR5K_DCU_SEQNUM_BASE 0x1140
+#define AR5K_DCU_SEQNUM_M 0x00000fff
+#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
+
+/*
+ * DCU global IFS SIFS register
+ */
+#define AR5K_DCU_GBL_IFS_SIFS 0x1030
+#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff
+
+/*
+ * DCU global IFS slot interval register
+ */
+#define AR5K_DCU_GBL_IFS_SLOT 0x1070
+#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff
+
+/*
+ * DCU global IFS EIFS register
+ */
+#define AR5K_DCU_GBL_IFS_EIFS 0x10b0
+#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff
+
+/*
+ * DCU global IFS misc register
+ *
+ * LFSR stands for Linear Feedback Shift Register
+ * and it's used for generating pseudo-random
+ * number sequences.
+ *
+ * (If i understand corectly, random numbers are
+ * used for idle sensing -multiplied with cwmin/max etc-)
+ */
+#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
+#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */
+#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10
+#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */
+
+/*
+ * DCU frame prefetch control register
+ */
+#define AR5K_DCU_FP 0x1230 /* Register Address */
+#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */
+#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */
+#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */
+
+/*
+ * DCU transmit pause control/status register
+ */
+#define AR5K_DCU_TXP 0x1270 /* Register Address */
+#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */
+#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */
+
+/*
+ * DCU transmit filter table 0 (32 entries)
+ * each entry contains a 32bit slice of the
+ * 128bit tx filter for each DCU (4 slices per DCU)
+ */
+#define AR5K_DCU_TX_FILTER_0_BASE 0x1038
+#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64))
+
+/*
+ * DCU transmit filter table 1 (16 entries)
+ */
+#define AR5K_DCU_TX_FILTER_1_BASE 0x103c
+#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + (_n * 64))
+
+/*
+ * DCU clear transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_CLR 0x143c
+
+/*
+ * DCU set transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_SET 0x147c
+
+/*
+ * Reset control register
+ */
+#define AR5K_RESET_CTL 0x4000 /* Register Address */
+#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */
+#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */
+#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */
+#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
+#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
+#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
+
+/*
+ * Sleep control register
+ */
+#define AR5K_SLEEP_CTL 0x4004 /* Register Address */
+#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */
+#define AR5K_SLEEP_CTL_SLDUR_S 0
+#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */
+#define AR5K_SLEEP_CTL_SLE_S 16
+#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */
+#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */
+#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */
+#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */
+#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */
+#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */
+#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */
+
+/*
+ * Interrupt pending register
+ */
+#define AR5K_INTPEND 0x4008
+#define AR5K_INTPEND_M 0x00000001
+
+/*
+ * Sleep force register
+ */
+#define AR5K_SFR 0x400c
+#define AR5K_SFR_EN 0x00000001
+
+/*
+ * PCI configuration register
+ * TODO: Fix LED stuff
+ */
+#define AR5K_PCICFG 0x4010 /* Register Address */
+#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
+#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */
+#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
+#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
+#define AR5K_PCICFG_EESIZE_S 3
+#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */
+#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */
+#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */
+#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */
+#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */
+#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */
+#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */
+#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */
+#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */
+#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */
+#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */
+#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */
+#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */
+#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/
+#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */
+#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */
+#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */
+#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */
+#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */
+#define AR5K_PCICFG_LEDBLINK_S 20
+#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */
+#define AR5K_PCICFG_LEDSTATE \
+ (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \
+ AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
+#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */
+#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24
+
+/*
+ * "General Purpose Input/Output" (GPIO) control register
+ *
+ * I'm not sure about this but after looking at the code
+ * for all chipsets here is what i got.
+ *
+ * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
+ * Mode 0 -> always input
+ * Mode 1 -> output when GPIODO for this GPIO is set to 0
+ * Mode 2 -> output when GPIODO for this GPIO is set to 1
+ * Mode 3 -> always output
+ *
+ * For more infos check out get_gpio/set_gpio and
+ * set_gpio_input/set_gpio_output functs.
+ * For more infos on gpio interrupt check out set_gpio_intr.
+ */
+#define AR5K_NUM_GPIO 6
+
+#define AR5K_GPIOCR 0x4014 /* Register Address */
+#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */
+#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */
+#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */
+#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */
+#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */
+#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */
+#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */
+#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */
+
+/*
+ * "General Purpose Input/Output" (GPIO) data output register
+ */
+#define AR5K_GPIODO 0x4018
+
+/*
+ * "General Purpose Input/Output" (GPIO) data input register
+ */
+#define AR5K_GPIODI 0x401c
+#define AR5K_GPIODI_M 0x0000002f
+
+/*
+ * Silicon revision register
+ */
+#define AR5K_SREV 0x4020 /* Register Address */
+#define AR5K_SREV_REV 0x0000000f /* Mask for revision */
+#define AR5K_SREV_REV_S 0
+#define AR5K_SREV_VER 0x000000ff /* Mask for version */
+#define AR5K_SREV_VER_S 4
+
+/*
+ * TXE write posting register
+ */
+#define AR5K_TXEPOST 0x4028
+
+/*
+ * QCU sleep mask
+ */
+#define AR5K_QCU_SLEEP_MASK 0x402c
+
+/* 0x4068 is compression buffer configuration
+ * register on 5414 and pm configuration register
+ * on 5424 and newer pci-e chips. */
+
+/*
+ * Compression buffer configuration
+ * register (enable/disable) [5414]
+ */
+#define AR5K_5414_CBCFG 0x4068
+#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */
+
+/*
+ * PCI-E Power managment configuration
+ * and status register [5424+]
+ */
+#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */
+/* Only 5424 */
+#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1
+ when d2_sleep_en is asserted */
+#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */
+#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */
+#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes
+ down */
+/* Wake On Wireless */
+#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */
+#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */
+#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */
+#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080
+#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100
+#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200
+#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400
+
+/*
+ * PCI-E Workaround enable register
+ */
+#define AR5K_PCIE_WAEN 0x407c
+
+/*
+ * PCI-E Serializer/Desirializer
+ * registers
+ */
+#define AR5K_PCIE_SERDES 0x4080
+#define AR5K_PCIE_SERDES_RESET 0x4084
+
+/*====EEPROM REGISTERS====*/
+
+/*
+ * EEPROM access registers
+ *
+ * Here we got a difference between 5210/5211-12
+ * read data register for 5210 is at 0x6800 and
+ * status register is at 0x6c00. There is also
+ * no eeprom command register on 5210 and the
+ * offsets are different.
+ *
+ * To read eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ * read AR5K_EEPROM_BASE +(4 * offset)
+ * check the eeprom status register
+ * and read eeprom data register.
+ *
+ * 5211 - write offset to AR5K_EEPROM_BASE
+ * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
+ * check the eeprom status register
+ * and read eeprom data register.
+ *
+ * To write eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ * write data to AR5K_EEPROM_BASE +(4 * offset)
+ * check the eeprom status register
+ * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
+ * 5212 write offset to AR5K_EEPROM_BASE
+ * write data to data register
+ * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
+ * check the eeprom status register
+ *
+ * For more infos check eeprom_* functs and the ar5k.c
+ * file posted in madwifi-devel mailing list.
+ * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
+ *
+ */
+#define AR5K_EEPROM_BASE 0x6000
+
+/*
+ * EEPROM data register
+ */
+#define AR5K_EEPROM_DATA_5211 0x6004
+#define AR5K_EEPROM_DATA_5210 0x6800
+#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
+
+/*
+ * EEPROM command register
+ */
+#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */
+#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */
+#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */
+#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */
+
+/*
+ * EEPROM status register
+ */
+#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
+#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
+#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
+#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */
+#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */
+#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */
+#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */
+
+/*
+ * EEPROM config register
+ */
+#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */
+#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */
+#define AR5K_EEPROM_CFG_SIZE_AUTO 0
+#define AR5K_EEPROM_CFG_SIZE_4KBIT 1
+#define AR5K_EEPROM_CFG_SIZE_8KBIT 2
+#define AR5K_EEPROM_CFG_SIZE_16KBIT 3
+#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */
+#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */
+#define AR5K_EEPROM_CFG_CLK_RATE_S 3
+#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0
+#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1
+#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2
+#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */
+#define AR5K_EEPROM_CFG_PROT_KEY_S 8
+#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */
+
+
+/*
+ * TODO: Wake On Wireless registers
+ * Range 0x7000 - 0x7ce0
+ */
+
+/*
+ * Protocol Control Unit (PCU) registers
+ */
+/*
+ * Used for checking initial register writes
+ * during channel reset (see reset func)
+ */
+#define AR5K_PCU_MIN 0x8000
+#define AR5K_PCU_MAX 0x8fff
+
+/*
+ * First station id register (Lower 32 bits of MAC address)
+ */
+#define AR5K_STA_ID0 0x8000
+#define AR5K_STA_ID0_ARRD_L32 0xffffffff
+
+/*
+ * Second station id register (Upper 16 bits of MAC address + PCU settings)
+ */
+#define AR5K_STA_ID1 0x8004 /* Register Address */
+#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */
+#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
+#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
+#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */
+#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */
+#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */
+#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */
+#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/
+#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
+#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */
+#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
+#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */
+#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */
+#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */
+#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */
+#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */
+#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */
+#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */
+#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */
+#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */
+
+/*
+ * First BSSID register (MAC address, lower 32bits)
+ */
+#define AR5K_BSS_ID0 0x8008
+
+/*
+ * Second BSSID register (MAC address in upper 16 bits)
+ *
+ * AID: Association ID
+ */
+#define AR5K_BSS_ID1 0x800c
+#define AR5K_BSS_ID1_AID 0xffff0000
+#define AR5K_BSS_ID1_AID_S 16
+
+/*
+ * Backoff slot time register
+ */
+#define AR5K_SLOT_TIME 0x8010
+
+/*
+ * ACK/CTS timeout register
+ */
+#define AR5K_TIME_OUT 0x8014 /* Register Address */
+#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */
+#define AR5K_TIME_OUT_ACK_S 0
+#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */
+#define AR5K_TIME_OUT_CTS_S 16
+
+/*
+ * RSSI threshold register
+ */
+#define AR5K_RSSI_THR 0x8018 /* Register Address */
+#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */
+#define AR5K_RSSI_THR_BMISS_5210_S 8
+#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5211_S 8
+#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
+#define AR5K_RSSI_THR_BMISS_S 8
+
+/*
+ * 5210 has more PCU registers because there is no QCU/DCU
+ * so queue parameters are set here, this way a lot common
+ * registers have different address for 5210. To make things
+ * easier we define a macro based on ah->ah_version for common
+ * registers with different addresses and common flags.
+ */
+
+/*
+ * Retry limit register
+ *
+ * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
+ */
+#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14
+#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */
+#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20
+
+/*
+ * Transmit latency register
+ */
+#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */
+#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */
+#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_USEC_5210 : AR5K_USEC_5211)
+#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */
+#define AR5K_USEC_1_S 0
+#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */
+#define AR5K_USEC_32_S 7
+#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
+#define AR5K_USEC_TX_LATENCY_5211_S 14
+#define AR5K_USEC_RX_LATENCY_5211 0x1f800000
+#define AR5K_USEC_RX_LATENCY_5211_S 23
+#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */
+#define AR5K_USEC_TX_LATENCY_5210_S 14
+#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */
+#define AR5K_USEC_RX_LATENCY_5210_S 20
+
+/*
+ * PCU beacon control register
+ */
+#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */
+#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */
+#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_BEACON_5210 : AR5K_BEACON_5211)
+#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */
+#define AR5K_BEACON_PERIOD_S 0
+#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */
+#define AR5K_BEACON_TIM_S 16
+#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */
+#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */
+
+/*
+ * CFP period register
+ */
+#define AR5K_CFP_PERIOD_5210 0x8028
+#define AR5K_CFP_PERIOD_5211 0x8024
+#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
+
+/*
+ * Next beacon time register
+ */
+#define AR5K_TIMER0_5210 0x802c
+#define AR5K_TIMER0_5211 0x8028
+#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
+
+/*
+ * Next DMA beacon alert register
+ */
+#define AR5K_TIMER1_5210 0x8030
+#define AR5K_TIMER1_5211 0x802c
+#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
+
+/*
+ * Next software beacon alert register
+ */
+#define AR5K_TIMER2_5210 0x8034
+#define AR5K_TIMER2_5211 0x8030
+#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
+
+/*
+ * Next ATIM window time register
+ */
+#define AR5K_TIMER3_5210 0x8038
+#define AR5K_TIMER3_5211 0x8034
+#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
+
+
+/*
+ * 5210 First inter frame spacing register (IFS)
+ */
+#define AR5K_IFS0 0x8040
+#define AR5K_IFS0_SIFS 0x000007ff
+#define AR5K_IFS0_SIFS_S 0
+#define AR5K_IFS0_DIFS 0x007ff800
+#define AR5K_IFS0_DIFS_S 11
+
+/*
+ * 5210 Second inter frame spacing register (IFS)
+ */
+#define AR5K_IFS1 0x8044
+#define AR5K_IFS1_PIFS 0x00000fff
+#define AR5K_IFS1_PIFS_S 0
+#define AR5K_IFS1_EIFS 0x03fff000
+#define AR5K_IFS1_EIFS_S 12
+#define AR5K_IFS1_CS_EN 0x04000000
+
+
+/*
+ * CFP duration register
+ */
+#define AR5K_CFP_DUR_5210 0x8048
+#define AR5K_CFP_DUR_5211 0x8038
+#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
+
+/*
+ * Receive filter register
+ */
+#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */
+#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
+#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
+#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
+#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
+#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
+#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
+#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
+#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
+#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
+#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
+#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
+#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
+#define AR5K_RX_FILTER_PHYERR \
+ ((ah->ah_version == AR5K_AR5211 ? \
+ AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
+#define AR5K_RX_FILTER_RADARERR \
+ ((ah->ah_version == AR5K_AR5211 ? \
+ AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
+
+/*
+ * Multicast filter register (lower 32 bits)
+ */
+#define AR5K_MCAST_FILTER0_5210 0x8050
+#define AR5K_MCAST_FILTER0_5211 0x8040
+#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
+
+/*
+ * Multicast filter register (higher 16 bits)
+ */
+#define AR5K_MCAST_FILTER1_5210 0x8054
+#define AR5K_MCAST_FILTER1_5211 0x8044
+#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
+
+
+/*
+ * Transmit mask register (lower 32 bits) [5210]
+ */
+#define AR5K_TX_MASK0 0x8058
+
+/*
+ * Transmit mask register (higher 16 bits) [5210]
+ */
+#define AR5K_TX_MASK1 0x805c
+
+/*
+ * Clear transmit mask [5210]
+ */
+#define AR5K_CLR_TMASK 0x8060
+
+/*
+ * Trigger level register (before transmission) [5210]
+ */
+#define AR5K_TRIG_LVL 0x8064
+
+
+/*
+ * PCU control register
+ *
+ * Only DIS_RX is used in the code, the rest i guess are
+ * for tweaking/diagnostics.
+ */
+#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
+#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
+#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
+#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */
+#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */
+#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */
+#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */
+#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */
+#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
+#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
+#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
+#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
+#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
+#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
+#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
+#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */
+#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
+#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
+#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */
+#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
+#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200
+#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
+#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */
+#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
+#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */
+#define AR5K_DIAG_SW_SCRAM_SEED_S 10
+#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
+#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
+#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */
+#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
+#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */
+#define AR5K_DIAG_SW_OBSPT_S 18
+#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */
+#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */
+#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */
+#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */
+
+/*
+ * TSF (clock) register (lower 32 bits)
+ */
+#define AR5K_TSF_L32_5210 0x806c
+#define AR5K_TSF_L32_5211 0x804c
+#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
+
+/*
+ * TSF (clock) register (higher 32 bits)
+ */
+#define AR5K_TSF_U32_5210 0x8070
+#define AR5K_TSF_U32_5211 0x8050
+#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
+
+/*
+ * Last beacon timestamp register (Read Only)
+ */
+#define AR5K_LAST_TSTP 0x8080
+
+/*
+ * ADDAC test register [5211+]
+ */
+#define AR5K_ADDAC_TEST 0x8054 /* Register Address */
+#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */
+#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */
+#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */
+#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */
+#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */
+#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */
+#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */
+#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */
+#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */
+#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */
+#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */
+
+/*
+ * Default antenna register [5211+]
+ */
+#define AR5K_DEFAULT_ANTENNA 0x8058
+
+/*
+ * Frame control QoS mask register (?) [5211+]
+ * (FC_QOS_MASK)
+ */
+#define AR5K_FRAME_CTL_QOSM 0x805c
+
+/*
+ * Seq mask register (?) [5211+]
+ */
+#define AR5K_SEQ_MASK 0x8060
+
+/*
+ * Retry count register [5210]
+ */
+#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */
+#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */
+#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */
+
+/*
+ * Back-off status register [5210]
+ */
+#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */
+#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */
+#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */
+
+
+
+/*
+ * NAV register (current)
+ */
+#define AR5K_NAV_5210 0x808c
+#define AR5K_NAV_5211 0x8084
+#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_NAV_5210 : AR5K_NAV_5211)
+
+/*
+ * RTS success register
+ */
+#define AR5K_RTS_OK_5210 0x8090
+#define AR5K_RTS_OK_5211 0x8088
+#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
+
+/*
+ * RTS failure register
+ */
+#define AR5K_RTS_FAIL_5210 0x8094
+#define AR5K_RTS_FAIL_5211 0x808c
+#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
+
+/*
+ * ACK failure register
+ */
+#define AR5K_ACK_FAIL_5210 0x8098
+#define AR5K_ACK_FAIL_5211 0x8090
+#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
+
+/*
+ * FCS failure register
+ */
+#define AR5K_FCS_FAIL_5210 0x809c
+#define AR5K_FCS_FAIL_5211 0x8094
+#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
+
+/*
+ * Beacon count register
+ */
+#define AR5K_BEACON_CNT_5210 0x80a0
+#define AR5K_BEACON_CNT_5211 0x8098
+#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
+
+
+/*===5212 Specific PCU registers===*/
+
+/*
+ * Transmit power control register
+ */
+#define AR5K_TPC 0x80e8
+#define AR5K_TPC_ACK 0x0000003f /* ack frames */
+#define AR5K_TPC_ACK_S 0
+#define AR5K_TPC_CTS 0x00003f00 /* cts frames */
+#define AR5K_TPC_CTS_S 8
+#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */
+#define AR5K_TPC_CHIRP_S 16
+#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */
+#define AR5K_TPC_DOPPLER_S 24
+
+/*
+ * XR (eXtended Range) mode register
+ */
+#define AR5K_XRMODE 0x80c0 /* Register Address */
+#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */
+#define AR5K_XRMODE_POLL_TYPE_S 0
+#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */
+#define AR5K_XRMODE_POLL_SUBTYPE_S 2
+#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */
+#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */
+#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */
+#define AR5K_XRMODE_FRAME_HOLD_S 20
+
+/*
+ * XR delay register
+ */
+#define AR5K_XRDELAY 0x80c4 /* Register Address */
+#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */
+#define AR5K_XRDELAY_SLOT_DELAY_S 0
+#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */
+#define AR5K_XRDELAY_CHIRP_DELAY_S 16
+
+/*
+ * XR timeout register
+ */
+#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */
+#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */
+#define AR5K_XRTIMEOUT_CHIRP_S 0
+#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */
+#define AR5K_XRTIMEOUT_POLL_S 16
+
+/*
+ * XR chirp register
+ */
+#define AR5K_XRCHIRP 0x80cc /* Register Address */
+#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */
+#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */
+
+/*
+ * XR stomp register
+ */
+#define AR5K_XRSTOMP 0x80d0 /* Register Address */
+#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */
+#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */
+#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */
+#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */
+#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/
+#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */
+
+/*
+ * First enhanced sleep register
+ */
+#define AR5K_SLEEP0 0x80d4 /* Register Address */
+#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */
+#define AR5K_SLEEP0_NEXT_DTIM_S 0
+#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */
+#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */
+#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */
+#define AR5K_SLEEP0_CABTO_S 24
+
+/*
+ * Second enhanced sleep register
+ */
+#define AR5K_SLEEP1 0x80d8 /* Register Address */
+#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */
+#define AR5K_SLEEP1_NEXT_TIM_S 0
+#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */
+#define AR5K_SLEEP1_BEACON_TO_S 24
+
+/*
+ * Third enhanced sleep register
+ */
+#define AR5K_SLEEP2 0x80dc /* Register Address */
+#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */
+#define AR5K_SLEEP2_TIM_PER_S 0
+#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */
+#define AR5K_SLEEP2_DTIM_PER_S 16
+
+/*
+ * BSSID mask registers
+ */
+#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */
+#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */
+
+/*
+ * TX power control (TPC) register
+ *
+ * XXX: PCDAC steps (0.5dbm) or DBM ?
+ *
+ */
+#define AR5K_TXPC 0x80e8 /* Register Address */
+#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */
+#define AR5K_TXPC_ACK_S 0
+#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */
+#define AR5K_TXPC_CTS_S 8
+#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */
+#define AR5K_TXPC_CHIRP_S 16
+#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */
+#define AR5K_TXPC_DOPPLER_S 24
+
+/*
+ * Profile count registers
+ */
+#define AR5K_PROFCNT_TX 0x80ec /* Tx count */
+#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */
+#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */
+#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */
+
+/*
+ * Quiet period control registers
+ */
+#define AR5K_QUIET_CTL1 0x80fc /* Register Address */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0
+#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */
+#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */
+
+#define AR5K_QUIET_CTL2 0x8100 /* Register Address */
+#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */
+#define AR5K_QUIET_CTL2_QT_PER_S 0
+#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */
+#define AR5K_QUIET_CTL2_QT_DUR_S 16
+
+/*
+ * TSF parameter register
+ */
+#define AR5K_TSF_PARM 0x8104 /* Register Address */
+#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */
+#define AR5K_TSF_PARM_INC_S 0
+
+/*
+ * QoS NOACK policy
+ */
+#define AR5K_QOS_NOACK 0x8108 /* Register Address */
+#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */
+#define AR5K_QOS_NOACK_2BIT_VALUES_S 0
+#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */
+#define AR5K_QOS_NOACK_BIT_OFFSET_S 4
+#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */
+#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7
+
+/*
+ * PHY error filter register
+ */
+#define AR5K_PHY_ERR_FIL 0x810c
+#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */
+#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */
+#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */
+
+/*
+ * XR latency register
+ */
+#define AR5K_XRLAT_TX 0x8110
+
+/*
+ * ACK SIFS register
+ */
+#define AR5K_ACKSIFS 0x8114 /* Register Address */
+#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */
+
+/*
+ * MIC QoS control register (?)
+ */
+#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */
+#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2))
+#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */
+
+/*
+ * MIC QoS select register (?)
+ */
+#define AR5K_MIC_QOS_SEL 0x811c
+#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4))
+
+/*
+ * Misc mode control register (?)
+ */
+#define AR5K_MISC_MODE 0x8120 /* Register Address */
+#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */
+#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */
+#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */
+/* more bits */
+
+/*
+ * OFDM Filter counter
+ */
+#define AR5K_OFDM_FIL_CNT 0x8124
+
+/*
+ * CCK Filter counter
+ */
+#define AR5K_CCK_FIL_CNT 0x8128
+
+/*
+ * PHY Error Counters (?)
+ */
+#define AR5K_PHYERR_CNT1 0x812c
+#define AR5K_PHYERR_CNT1_MASK 0x8130
+
+#define AR5K_PHYERR_CNT2 0x8134
+#define AR5K_PHYERR_CNT2_MASK 0x8138
+
+/*
+ * TSF Threshold register (?)
+ */
+#define AR5K_TSF_THRES 0x813c
+
+/*
+ * TODO: Wake On Wireless registers
+ * Range: 0x8147 - 0x818c
+ */
+
+/*
+ * Rate -> ACK SIFS mapping table (32 entries)
+ */
+#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */
+#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2))
+#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */
+#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */
+
+/*
+ * Rate -> duration mapping table (32 entries)
+ */
+#define AR5K_RATE_DUR_BASE 0x8700
+#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2))
+
+/*
+ * Rate -> db mapping table
+ * (8 entries, each one has 4 8bit fields)
+ */
+#define AR5K_RATE2DB_BASE 0x87c0
+#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2))
+
+/*
+ * db -> Rate mapping table
+ * (8 entries, each one has 4 8bit fields)
+ */
+#define AR5K_DB2RATE_BASE 0x87e0
+#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2))
+
+/*===5212 end===*/
+
+/*
+ * Key table (WEP) register
+ */
+#define AR5K_KEYTABLE_0_5210 0x9000
+#define AR5K_KEYTABLE_0_5211 0x8800
+#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5))
+#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
+#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
+#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2))
+#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5)
+#define AR5K_KEYTABLE_TYPE_40 0x00000000
+#define AR5K_KEYTABLE_TYPE_104 0x00000001
+#define AR5K_KEYTABLE_TYPE_128 0x00000003
+#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */
+#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */
+#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */
+#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */
+#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */
+#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6)
+#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
+#define AR5K_KEYTABLE_VALID 0x00008000
+
+/* If key type is TKIP and MIC is enabled
+ * MIC key goes in offset entry + 64 */
+#define AR5K_KEYTABLE_MIC_OFFSET 64
+
+/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
+ * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
+ * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
+ *
+ * Some vendors have introduced bigger WEP keys to address
+ * security vulnerabilities in WEP. This includes:
+ *
+ * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
+ *
+ * We can expand this if we find ar5k Atheros cards with a larger
+ * key table size.
+ */
+#define AR5K_KEYTABLE_SIZE_5210 64
+#define AR5K_KEYTABLE_SIZE_5211 128
+#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
+
+
+/*===PHY REGISTERS===*/
+
+/*
+ * PHY registers start
+ */
+#define AR5K_PHY_BASE 0x9800
+#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
+
+/*
+ * TST_2 (Misc config parameters)
+ */
+#define AR5K_PHY_TST2 0x9800 /* Register Address */
+#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/
+#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */
+#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */
+#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */
+#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */
+#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */
+#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */
+#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */
+#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */
+#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */
+#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */
+#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */
+#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */
+#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */
+#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */
+#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */
+#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */
+#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */
+
+/*
+ * PHY frame control register [5110] /turbo mode register [5111+]
+ *
+ * There is another frame control register for [5111+]
+ * at address 0x9944 (see below) but the 2 first flags
+ * are common here between 5110 frame control register
+ * and [5111+] turbo mode register, so this also works as
+ * a "turbo mode register" for 5110. We treat this one as
+ * a frame control register for 5110 below.
+ */
+#define AR5K_PHY_TURBO 0x9804 /* Register Address */
+#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */
+#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */
+#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */
+
+/*
+ * PHY agility command register
+ * (aka TST_1)
+ */
+#define AR5K_PHY_AGC 0x9808 /* Register Address */
+#define AR5K_PHY_TST1 0x9808
+#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/
+#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */
+#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */
+#define AR5K_PHY_TST1_TXSRC_SRC_S 1
+#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */
+#define AR5K_PHY_TST1_TXSRC_ALT_S 7
+
+
+/*
+ * PHY timing register 3 [5112+]
+ */
+#define AR5K_PHY_TIMING_3 0x9814
+#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000
+#define AR5K_PHY_TIMING_3_DSC_MAN_S 17
+#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000
+#define AR5K_PHY_TIMING_3_DSC_EXP_S 13
+
+/*
+ * PHY chip revision register
+ */
+#define AR5K_PHY_CHIP_ID 0x9818
+
+/*
+ * PHY activation register
+ */
+#define AR5K_PHY_ACT 0x981c /* Register Address */
+#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */
+#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */
+
+/*
+ * PHY RF control registers
+ */
+#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */
+#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */
+#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0
+
+#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8
+
+#define AR5K_PHY_ADC_CTL 0x982c
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0
+#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000
+#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000
+#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000
+#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16
+
+#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */
+#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */
+#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */
+#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */
+#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */
+
+/*
+ * Pre-Amplifier control register
+ * (XPA -> external pre-amplifier)
+ */
+#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */
+#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */
+#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */
+#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */
+#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */
+
+/*
+ * PHY settling register
+ */
+#define AR5K_PHY_SETTLING 0x9844 /* Register Address */
+#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */
+#define AR5K_PHY_SETTLING_AGC_S 0
+#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */
+#define AR5K_PHY_SETTLING_SWITCH_S 7
+
+/*
+ * PHY Gain registers
+ */
+#define AR5K_PHY_GAIN 0x9848 /* Register Address */
+#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */
+#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12
+#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000
+#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18
+
+#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */
+#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */
+
+/*
+ * Desired ADC/PGA size register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */
+#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */
+#define AR5K_PHY_DESIRED_SIZE_ADC_S 0
+#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */
+#define AR5K_PHY_DESIRED_SIZE_PGA_S 8
+#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */
+#define AR5K_PHY_DESIRED_SIZE_TOT_S 20
+
+/*
+ * PHY signal register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_SIG 0x9858 /* Register Address */
+#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */
+#define AR5K_PHY_SIG_FIRSTEP_S 12
+#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */
+#define AR5K_PHY_SIG_FIRPWR_S 18
+
+/*
+ * PHY coarse agility control register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */
+#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */
+#define AR5K_PHY_AGCCOARSE_LO_S 7
+#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */
+#define AR5K_PHY_AGCCOARSE_HI_S 15
+
+/*
+ * PHY agility control register
+ */
+#define AR5K_PHY_AGCCTL 0x9860 /* Register address */
+#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */
+#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */
+#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */
+#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
+
+/*
+ * PHY noise floor status register
+ */
+#define AR5K_PHY_NF 0x9864 /* Register address */
+#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */
+#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */
+#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
+#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
+#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
+#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */
+#define AR5K_PHY_NF_THRESH62_S 12
+#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */
+#define AR5K_PHY_NF_MINCCA_PWR_S 19
+
+/*
+ * PHY ADC saturation register [5110]
+ */
+#define AR5K_PHY_ADCSAT 0x9868
+#define AR5K_PHY_ADCSAT_ICNT 0x0001f800
+#define AR5K_PHY_ADCSAT_ICNT_S 11
+#define AR5K_PHY_ADCSAT_THR 0x000007e0
+#define AR5K_PHY_ADCSAT_THR_S 5
+
+/*
+ * PHY Weak ofdm signal detection threshold registers (ANI) [5212+]
+ */
+
+/* High thresholds */
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24
+
+/* Low thresholds */
+#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21
+
+
+/*
+ * PHY sleep registers [5112+]
+ */
+#define AR5K_PHY_SCR 0x9870
+
+#define AR5K_PHY_SLMT 0x9874
+#define AR5K_PHY_SLMT_32MHZ 0x0000007f
+
+#define AR5K_PHY_SCAL 0x9878
+#define AR5K_PHY_SCAL_32MHZ 0x0000000e
+#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a
+#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032
+
+/*
+ * PHY PLL (Phase Locked Loop) control register
+ */
+#define AR5K_PHY_PLL 0x987c
+#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */
+/* 40MHz -> 5GHz band */
+#define AR5K_PHY_PLL_40MHZ_5211 0x00000018
+#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa
+#define AR5K_PHY_PLL_40MHZ_5413 0x00000004
+#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \
+ AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
+/* 44MHz -> 2.4GHz band */
+#define AR5K_PHY_PLL_44MHZ_5211 0x00000019
+#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab
+#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \
+ AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
+
+#define AR5K_PHY_PLL_RF5111 0x00000000
+#define AR5K_PHY_PLL_RF5112 0x00000040
+#define AR5K_PHY_PLL_HALF_RATE 0x00000100
+#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200
+
+/*
+ * RF Buffer register
+ *
+ * It's obvious from the code that 0x989c is the buffer register but
+ * for the other special registers that we write to after sending each
+ * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * for now. It's interesting that they are also used for some other operations.
+ */
+
+#define AR5K_RF_BUFFER 0x989c
+#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */
+#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */
+#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */
+ /* Channel set on 5111 */
+ /* Used to read radio revision*/
+
+#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */
+ /* Bank 0,1,2,6 on 5111 */
+ /* Bank 1 on 5112 */
+ /* Used during activation on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */
+ /* Used during activation on 5111 */
+ /* Channel on 5112 */
+ /* Bank 6 on 5112 */
+
+#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */
+
+/*
+ * PHY RF stage register [5210]
+ */
+#define AR5K_PHY_RFSTG 0x98d4
+#define AR5K_PHY_RFSTG_DISABLE 0x00000021
+
+/*
+ * BIN masks (?)
+ */
+#define AR5K_PHY_BIN_MASK_1 0x9900
+#define AR5K_PHY_BIN_MASK_2 0x9904
+#define AR5K_PHY_BIN_MASK_3 0x9908
+
+#define AR5K_PHY_BIN_MASK_CTL 0x990c
+#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff
+#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0
+#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000
+#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24
+
+/*
+ * PHY Antenna control register
+ */
+#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */
+#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */
+#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */
+#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */
+#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4
+
+/*
+ * PHY receiver delay register [5111+]
+ */
+#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */
+#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */
+
+/*
+ * PHY max rx length register (?) [5111]
+ */
+#define AR5K_PHY_MAX_RX_LEN 0x991c
+
+/*
+ * PHY timing register 4
+ * I(nphase)/Q(adrature) calibration register [5111+]
+ */
+#define AR5K_PHY_IQ 0x9920 /* Register Address */
+#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */
+#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */
+#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5
+#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12
+#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */
+#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */
+#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */
+#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */
+#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */
+#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */
+#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */
+
+/*
+ * PHY timing register 5
+ * OFDM Self-correlator Cyclic RSSI threshold params
+ * (Check out bb_cycpwr_thr1 on ANI patent)
+ */
+#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1
+#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */
+#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */
+#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */
+#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */
+
+/*
+ * PHY-only warm reset register
+ */
+#define AR5K_PHY_WARM_RESET 0x9928
+
+/*
+ * PHY-only control register
+ */
+#define AR5K_PHY_CTL 0x992c /* Register Address */
+#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */
+#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */
+#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */
+#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */
+#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */
+#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */
+#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */
+#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */
+
+/*
+ * PHY PAPD probe register [5111+]
+ */
+#define AR5K_PHY_PAPD_PROBE 0x9930
+#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001
+#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002
+#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040
+#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00
+#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9
+#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000
+#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000
+#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */
+#define AR5K_PHY_PAPD_PROBE_TYPE_S 23
+#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0
+#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1
+#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2
+#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000
+#define AR5K_PHY_PAPD_PROBE_GAINF_S 25
+#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */
+#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */
+
+/*
+ * PHY TX rate power registers [5112+]
+ */
+#define AR5K_PHY_TXPOWER_RATE1 0x9934
+#define AR5K_PHY_TXPOWER_RATE2 0x9938
+#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c
+#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040
+#define AR5K_PHY_TXPOWER_RATE3 0xa234
+#define AR5K_PHY_TXPOWER_RATE4 0xa238
+
+/*
+ * PHY frame control register [5111+]
+ */
+#define AR5K_PHY_FRAME_CTL_5210 0x9804
+#define AR5K_PHY_FRAME_CTL_5211 0x9944
+#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
+/*---[5111+]---*/
+#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */
+#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
+#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */
+#define AR5K_PHY_FRAME_CTL_EMU 0x80000000
+#define AR5K_PHY_FRAME_CTL_EMU_S 31
+/*---[5110/5111]---*/
+#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */
+#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */
+#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */
+#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */
+#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
+#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */
+#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+ AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+ AR5K_PHY_FRAME_CTL_TIMING_ERR
+
+/*
+ * PHY Tx Power adjustment register [5212A+]
+ */
+#define AR5K_PHY_TX_PWR_ADJ 0x994c
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0
+#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000
+#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18
+
+/*
+ * PHY radar detection register [5111+]
+ */
+#define AR5K_PHY_RADAR 0x9954
+#define AR5K_PHY_RADAR_ENABLE 0x00000001
+#define AR5K_PHY_RADAR_DISABLE 0x00000000
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold
+ 5-bits, units unknown {0..31}
+ (? MHz ?) */
+#define AR5K_PHY_RADAR_INBANDTHR_S 1
+
+#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_PRSSI_THR_S 6
+
+#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12
+
+#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold.
+ 6-bits, dBm range {0..63}
+ in dBm units. */
+#define AR5K_PHY_RADAR_RSSI_THR_S 18
+
+#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response
+ filter power out threshold.
+ 7-bits, standard power range
+ {0..127} in 1/2 dBm units. */
+#define AR5K_PHY_RADAR_FIRPWR_THRS 24
+
+/*
+ * PHY antenna switch table registers
+ */
+#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960
+#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964
+
+/*
+ * PHY Noise floor threshold
+ */
+#define AR5K_PHY_NFTHRES 0x9968
+
+/*
+ * Sigma Delta register (?) [5213]
+ */
+#define AR5K_PHY_SIGMA_DELTA 0x996C
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8
+#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00
+#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+/*
+ * RF restart register [5112+] (?)
+ */
+#define AR5K_PHY_RESTART 0x9970 /* restart */
+#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */
+#define AR5K_PHY_RESTART_DIV_GC_S 18
+
+/*
+ * RF Bus access request register (for synth-oly channel switching)
+ */
+#define AR5K_PHY_RFBUS_REQ 0x997C
+#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001
+
+/*
+ * Spur mitigation masks (?)
+ */
+#define AR5K_PHY_TIMING_7 0x9980
+#define AR5K_PHY_TIMING_8 0x9984
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0
+
+#define AR5K_PHY_BIN_MASK2_1 0x9988
+#define AR5K_PHY_BIN_MASK2_2 0x998c
+#define AR5K_PHY_BIN_MASK2_3 0x9990
+
+#define AR5K_PHY_BIN_MASK2_4 0x9994
+#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff
+#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR5K_PHY_TIMING_9 0x9998
+#define AR5K_PHY_TIMING_10 0x999c
+#define AR5K_PHY_TIMING_10_PILOT_MASK_2 0x000fffff
+#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S 0
+
+/*
+ * Spur mitigation control
+ */
+#define AR5K_PHY_TIMING_11 0x99a0 /* Register address */
+#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */
+#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0
+#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */
+#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S 20
+#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */
+#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */
+
+/*
+ * Gain tables
+ */
+#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
+#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
+#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
+#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
+
+/*
+ * PHY timing IQ calibration result register [5111+]
+ */
+#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */
+#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */
+#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */
+
+/*
+ * PHY current RSSI register [5111+]
+ */
+#define AR5K_PHY_CURRENT_RSSI 0x9c1c
+
+/*
+ * PHY RF Bus grant register
+ */
+#define AR5K_PHY_RFBUS_GRANT 0x9c20
+#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001
+
+/*
+ * PHY ADC test register
+ */
+#define AR5K_PHY_ADC_TEST 0x9c24
+#define AR5K_PHY_ADC_TEST_I 0x00000001
+#define AR5K_PHY_ADC_TEST_Q 0x00000200
+
+/*
+ * PHY DAC test register
+ */
+#define AR5K_PHY_DAC_TEST 0x9c28
+#define AR5K_PHY_DAC_TEST_I 0x00000001
+#define AR5K_PHY_DAC_TEST_Q 0x00000200
+
+/*
+ * PHY PTAT register (?)
+ */
+#define AR5K_PHY_PTAT 0x9c2c
+
+/*
+ * PHY Illegal TX rate register [5112+]
+ */
+#define AR5K_PHY_BAD_TX_RATE 0x9c30
+
+/*
+ * PHY SPUR Power register [5112+]
+ */
+#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */
+#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */
+#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */
+#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */
+
+/*
+ * PHY Channel status register [5112+] (?)
+ */
+#define AR5K_PHY_CHAN_STATUS 0x9c38
+#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001
+#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002
+#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004
+#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008
+
+/*
+ * Heavy clip enable register
+ */
+#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0
+
+/*
+ * PHY clock sleep registers [5112+]
+ */
+#define AR5K_PHY_SCLOCK 0x99f0
+#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
+#define AR5K_PHY_SDELAY 0x99f4
+#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
+#define AR5K_PHY_SPENDING 0x99f8
+
+
+/*
+ * PHY PAPD I (power?) table (?)
+ * (92! entries)
+ */
+#define AR5K_PHY_PAPD_I_BASE 0xa000
+#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2))
+
+/*
+ * PHY PCDAC TX power table
+ */
+#define AR5K_PHY_PCDAC_TXPOWER_BASE 0xa180
+#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
+
+/*
+ * PHY mode register [5111+]
+ */
+#define AR5K_PHY_MODE 0x0a200 /* Register Address */
+#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */
+#define AR5K_PHY_MODE_MOD_OFDM 0
+#define AR5K_PHY_MODE_MOD_CCK 1
+#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */
+#define AR5K_PHY_MODE_FREQ_5GHZ 0
+#define AR5K_PHY_MODE_FREQ_2GHZ 2
+#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */
+#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */
+#define AR5K_PHY_MODE_RAD_RF5111 0
+#define AR5K_PHY_MODE_RAD_RF5112 8
+#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */
+#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */
+#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */
+
+/*
+ * PHY CCK transmit control register [5111+ (?)]
+ */
+#define AR5K_PHY_CCKTXCTL 0xa204
+#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000
+#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010
+#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001
+#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004
+
+/*
+ * PHY CCK Cross-correlator Barker RSSI threshold register [5212+]
+ */
+#define AR5K_PHY_CCK_CROSSCORR 0xa208
+#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f
+#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0
+
+/* Same address is used for antenna diversity activation */
+#define AR5K_PHY_FAST_ANT_DIV 0xa208
+#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000
+
+/*
+ * PHY 2GHz gain register [5111+]
+ */
+#define AR5K_PHY_GAIN_2GHZ 0xa20c
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18
+#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
+
+#define AR5K_PHY_CCK_RX_CTL_4 0xa21c
+#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000
+#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19
+
+#define AR5K_PHY_DAG_CCK_CTL 0xa228
+#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200
+#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00
+#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10
+
+#define AR5K_PHY_FAST_ADC 0xa24c
+
+#define AR5K_PHY_BLUETOOTH 0xa254
+
+/*
+ * Transmit Power Control register
+ * [2413+]
+ */
+#define AR5K_PHY_TPC_RG1 0xa258
+#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000
+#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14
+#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000
+#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16
+#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000
+#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18
+#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000
+#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20
+
+#define AR5K_PHY_TPC_RG5 0xa26C
+#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22
+
+/*
+ * PHY PDADC Tx power table
+ */
+#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280
+#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfbuffer.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfbuffer.h
new file mode 100644
index 0000000..e50baff
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfbuffer.h
@@ -0,0 +1,1181 @@
+/*
+ * RF Buffer handling functions
+ *
+ * Copyright (c) 2009 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+
+/*
+ * There are some special registers on the RF chip
+ * that control various operation settings related mostly to
+ * the analog parts (channel, gain adjustment etc).
+ *
+ * We don't write on those registers directly but
+ * we send a data packet on the chip, using a special register,
+ * that holds all the settings we need. After we 've sent the
+ * data packet, we write on another special register to notify hw
+ * to apply the settings. This is done so that control registers
+ * can be dynamicaly programmed during operation and the settings
+ * are applied faster on the hw.
+ *
+ * We call each data packet an "RF Bank" and all the data we write
+ * (all RF Banks) "RF Buffer". This file holds initial RF Buffer
+ * data for the different RF chips, and various info to match RF
+ * Buffer offsets with specific RF registers so that we can access
+ * them. We tweak these settings on rfregs_init function.
+ *
+ * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer
+ * registers and control registers):
+ *
+ * http://www.google.com/patents?id=qNURAAAAEBAJ
+ */
+
+
+/*
+ * Struct to hold default mode specific RF
+ * register values (RF Banks)
+ */
+struct ath5k_ini_rfbuffer {
+ u8 rfb_bank; /* RF Bank number */
+ u16 rfb_ctrl_register; /* RF Buffer control register */
+ u32 rfb_mode_data[5]; /* RF Buffer data for each mode */
+};
+
+/*
+ * Struct to hold RF Buffer field
+ * infos used to access certain RF
+ * analog registers
+ */
+struct ath5k_rfb_field {
+ u8 len; /* Field length */
+ u16 pos; /* Offset on the raw packet */
+ u8 col; /* Column -used for shifting */
+};
+
+/*
+ * RF analog register definition
+ */
+struct ath5k_rf_reg {
+ u8 bank; /* RF Buffer Bank number */
+ u8 index; /* Register's index on rf_regs_idx */
+ struct ath5k_rfb_field field; /* RF Buffer field for this register */
+};
+
+/* Map RF registers to indexes
+ * We do this to handle common bits and make our
+ * life easier by using an index for each register
+ * instead of a full rfb_field */
+enum ath5k_rf_regs_idx {
+ /* BANK 6 */
+ AR5K_RF_OB_2GHZ = 0,
+ AR5K_RF_OB_5GHZ,
+ AR5K_RF_DB_2GHZ,
+ AR5K_RF_DB_5GHZ,
+ AR5K_RF_FIXED_BIAS_A,
+ AR5K_RF_FIXED_BIAS_B,
+ AR5K_RF_PWD_XPD,
+ AR5K_RF_XPD_SEL,
+ AR5K_RF_XPD_GAIN,
+ AR5K_RF_PD_GAIN_LO,
+ AR5K_RF_PD_GAIN_HI,
+ AR5K_RF_HIGH_VC_CP,
+ AR5K_RF_MID_VC_CP,
+ AR5K_RF_LOW_VC_CP,
+ AR5K_RF_PUSH_UP,
+ AR5K_RF_PAD2GND,
+ AR5K_RF_XB2_LVL,
+ AR5K_RF_XB5_LVL,
+ AR5K_RF_PWD_ICLOBUF_2G,
+ AR5K_RF_PWD_84,
+ AR5K_RF_PWD_90,
+ AR5K_RF_PWD_130,
+ AR5K_RF_PWD_131,
+ AR5K_RF_PWD_132,
+ AR5K_RF_PWD_136,
+ AR5K_RF_PWD_137,
+ AR5K_RF_PWD_138,
+ AR5K_RF_PWD_166,
+ AR5K_RF_PWD_167,
+ AR5K_RF_DERBY_CHAN_SEL_MODE,
+ /* BANK 7 */
+ AR5K_RF_GAIN_I,
+ AR5K_RF_PLO_SEL,
+ AR5K_RF_RFGAIN_SEL,
+ AR5K_RF_RFGAIN_STEP,
+ AR5K_RF_WAIT_S,
+ AR5K_RF_WAIT_I,
+ AR5K_RF_MAX_TIME,
+ AR5K_RF_MIXVGA_OVR,
+ AR5K_RF_MIXGAIN_OVR,
+ AR5K_RF_MIXGAIN_STEP,
+ AR5K_RF_PD_DELAY_A,
+ AR5K_RF_PD_DELAY_B,
+ AR5K_RF_PD_DELAY_XR,
+ AR5K_RF_PD_PERIOD_A,
+ AR5K_RF_PD_PERIOD_B,
+ AR5K_RF_PD_PERIOD_XR,
+};
+
+
+/*******************\
+* RF5111 (Sombrero) *
+\*******************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 }
+#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 }
+
+#define AR5K_RF5111_OB_5GHZ { 3, 104, 0 }
+#define AR5K_RF5111_DB_5GHZ { 3, 107, 0 }
+
+#define AR5K_RF5111_PWD_XPD { 1, 95, 0 }
+#define AR5K_RF5111_XPD_GAIN { 4, 96, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5111_PWD(_n) { 1, (135 - _n), 3 }
+
+/* BANK 7 len pos col */
+#define AR5K_RF5111_GAIN_I { 6, 29, 0 }
+#define AR5K_RF5111_PLO_SEL { 1, 4, 0 }
+#define AR5K_RF5111_RFGAIN_SEL { 1, 36, 0 }
+#define AR5K_RF5111_RFGAIN_STEP { 6, 37, 0 }
+/* Only on AR5212 BaseBand and up */
+#define AR5K_RF5111_WAIT_S { 5, 19, 0 }
+#define AR5K_RF5111_WAIT_I { 5, 24, 0 }
+#define AR5K_RF5111_MAX_TIME { 2, 49, 0 }
+
+static const struct ath5k_rf_reg rf_regs_5111[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5111_DB_5GHZ},
+ {6, AR5K_RF_PWD_XPD, AR5K_RF5111_PWD_XPD},
+ {6, AR5K_RF_XPD_GAIN, AR5K_RF5111_XPD_GAIN},
+ {6, AR5K_RF_PWD_84, AR5K_RF5111_PWD(84)},
+ {6, AR5K_RF_PWD_90, AR5K_RF5111_PWD(90)},
+ {7, AR5K_RF_GAIN_I, AR5K_RF5111_GAIN_I},
+ {7, AR5K_RF_PLO_SEL, AR5K_RF5111_PLO_SEL},
+ {7, AR5K_RF_RFGAIN_SEL, AR5K_RF5111_RFGAIN_SEL},
+ {7, AR5K_RF_RFGAIN_STEP, AR5K_RF5111_RFGAIN_STEP},
+ {7, AR5K_RF_WAIT_S, AR5K_RF5111_WAIT_S},
+ {7, AR5K_RF_WAIT_I, AR5K_RF5111_WAIT_I},
+ {7, AR5K_RF_MAX_TIME, AR5K_RF5111_MAX_TIME}
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5111[] = {
+ { 0, 0x989c,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
+ { 0, 0x989c,
+ { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
+ { 0, 0x98d4,
+ { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
+ { 1, 0x98d4,
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d4,
+ { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
+ { 3, 0x98d8,
+ { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
+ { 6, 0x989c,
+ { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
+ { 6, 0x989c,
+ { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
+ { 6, 0x989c,
+ { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
+ { 6, 0x989c,
+ { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
+ { 6, 0x98d4,
+ { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
+ { 7, 0x989c,
+ { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
+ { 7, 0x989c,
+ { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
+ { 7, 0x989c,
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+ { 7, 0x989c,
+ { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
+ { 7, 0x989c,
+ { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
+ { 7, 0x989c,
+ { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
+ { 7, 0x989c,
+ { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***********************\
+* RF5112/RF2112 (Derby) *
+\***********************/
+
+/* BANK 7 (Common) len pos col */
+#define AR5K_RF5112X_GAIN_I { 6, 14, 0 }
+#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 }
+#define AR5K_RF5112X_MIXGAIN_OVR { 2, 37, 0 }
+#define AR5K_RF5112X_MIXGAIN_STEP { 4, 32, 0 }
+#define AR5K_RF5112X_PD_DELAY_A { 4, 58, 0 }
+#define AR5K_RF5112X_PD_DELAY_B { 4, 62, 0 }
+#define AR5K_RF5112X_PD_DELAY_XR { 4, 66, 0 }
+#define AR5K_RF5112X_PD_PERIOD_A { 4, 70, 0 }
+#define AR5K_RF5112X_PD_PERIOD_B { 4, 74, 0 }
+#define AR5K_RF5112X_PD_PERIOD_XR { 4, 78, 0 }
+
+/* RFX112 (Derby 1) */
+
+/* BANK 6 len pos col */
+#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 }
+#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 }
+
+#define AR5K_RF5112_OB_5GHZ { 3, 261, 0 }
+#define AR5K_RF5112_DB_5GHZ { 3, 264, 0 }
+
+#define AR5K_RF5112_FIXED_BIAS_A { 1, 260, 0 }
+#define AR5K_RF5112_FIXED_BIAS_B { 1, 259, 0 }
+
+#define AR5K_RF5112_XPD_SEL { 1, 284, 0 }
+#define AR5K_RF5112_XPD_GAIN { 2, 252, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 }
+
+static const struct ath5k_rf_reg rf_regs_5112[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5112_DB_5GHZ},
+ {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112_FIXED_BIAS_A},
+ {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112_FIXED_BIAS_B},
+ {6, AR5K_RF_XPD_SEL, AR5K_RF5112_XPD_SEL},
+ {6, AR5K_RF_XPD_GAIN, AR5K_RF5112_XPD_GAIN},
+ {6, AR5K_RF_PWD_130, AR5K_RF5112_PWD(130)},
+ {6, AR5K_RF_PWD_131, AR5K_RF5112_PWD(131)},
+ {6, AR5K_RF_PWD_132, AR5K_RF5112_PWD(132)},
+ {6, AR5K_RF_PWD_136, AR5K_RF5112_PWD(136)},
+ {6, AR5K_RF_PWD_137, AR5K_RF5112_PWD(137)},
+ {6, AR5K_RF_PWD_138, AR5K_RF5112_PWD(138)},
+ {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I},
+ {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR},
+ {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR},
+ {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP},
+ {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A},
+ {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B},
+ {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR},
+ {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A},
+ {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B},
+ {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5112[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, 0x98dc,
+ { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+ { 6, 0x989c,
+ { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
+ { 6, 0x989c,
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
+ { 6, 0x989c,
+ { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
+ { 6, 0x989c,
+ { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
+ { 6, 0x989c,
+ { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c,
+ { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
+ { 6, 0x989c,
+ { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
+ { 6, 0x989c,
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c,
+ { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
+ { 6, 0x989c,
+ { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
+ { 6, 0x989c,
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c,
+ { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
+ { 6, 0x989c,
+ { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
+ { 6, 0x989c,
+ { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
+ { 6, 0x989c,
+ { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
+ { 6, 0x989c,
+ { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
+ { 6, 0x989c,
+ { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
+ { 6, 0x989c,
+ { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
+ { 6, 0x989c,
+ { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
+ { 6, 0x989c,
+ { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
+ { 6, 0x989c,
+ { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
+ { 6, 0x98d0,
+ { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
+ { 7, 0x989c,
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c,
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c,
+ { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c,
+ { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
+ { 7, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c,
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c,
+ { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
+ { 7, 0x989c,
+ { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
+ { 7, 0x989c,
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c,
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c,
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+/* RFX112A (Derby 2) */
+
+/* BANK 6 len pos col */
+#define AR5K_RF5112A_OB_2GHZ { 3, 287, 0 }
+#define AR5K_RF5112A_DB_2GHZ { 3, 290, 0 }
+
+#define AR5K_RF5112A_OB_5GHZ { 3, 279, 0 }
+#define AR5K_RF5112A_DB_5GHZ { 3, 282, 0 }
+
+#define AR5K_RF5112A_FIXED_BIAS_A { 1, 278, 0 }
+#define AR5K_RF5112A_FIXED_BIAS_B { 1, 277, 0 }
+
+#define AR5K_RF5112A_XPD_SEL { 1, 302, 0 }
+#define AR5K_RF5112A_PDGAINLO { 2, 270, 0 }
+#define AR5K_RF5112A_PDGAINHI { 2, 257, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5112A_PWD(_n) { 1, (306 - _n), 3 }
+
+/* Voltage regulators */
+#define AR5K_RF5112A_HIGH_VC_CP { 2, 90, 2 }
+#define AR5K_RF5112A_MID_VC_CP { 2, 92, 2 }
+#define AR5K_RF5112A_LOW_VC_CP { 2, 94, 2 }
+#define AR5K_RF5112A_PUSH_UP { 1, 254, 2 }
+
+/* Power consumption */
+#define AR5K_RF5112A_PAD2GND { 1, 281, 1 }
+#define AR5K_RF5112A_XB2_LVL { 2, 1, 3 }
+#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 }
+
+static const struct ath5k_rf_reg rf_regs_5112a[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5112A_DB_5GHZ},
+ {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112A_FIXED_BIAS_A},
+ {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112A_FIXED_BIAS_B},
+ {6, AR5K_RF_XPD_SEL, AR5K_RF5112A_XPD_SEL},
+ {6, AR5K_RF_PD_GAIN_LO, AR5K_RF5112A_PDGAINLO},
+ {6, AR5K_RF_PD_GAIN_HI, AR5K_RF5112A_PDGAINHI},
+ {6, AR5K_RF_PWD_130, AR5K_RF5112A_PWD(130)},
+ {6, AR5K_RF_PWD_131, AR5K_RF5112A_PWD(131)},
+ {6, AR5K_RF_PWD_132, AR5K_RF5112A_PWD(132)},
+ {6, AR5K_RF_PWD_136, AR5K_RF5112A_PWD(136)},
+ {6, AR5K_RF_PWD_137, AR5K_RF5112A_PWD(137)},
+ {6, AR5K_RF_PWD_138, AR5K_RF5112A_PWD(138)},
+ {6, AR5K_RF_PWD_166, AR5K_RF5112A_PWD(166)},
+ {6, AR5K_RF_PWD_167, AR5K_RF5112A_PWD(167)},
+ {6, AR5K_RF_HIGH_VC_CP, AR5K_RF5112A_HIGH_VC_CP},
+ {6, AR5K_RF_MID_VC_CP, AR5K_RF5112A_MID_VC_CP},
+ {6, AR5K_RF_LOW_VC_CP, AR5K_RF5112A_LOW_VC_CP},
+ {6, AR5K_RF_PUSH_UP, AR5K_RF5112A_PUSH_UP},
+ {6, AR5K_RF_PAD2GND, AR5K_RF5112A_PAD2GND},
+ {6, AR5K_RF_XB2_LVL, AR5K_RF5112A_XB2_LVL},
+ {6, AR5K_RF_XB5_LVL, AR5K_RF5112A_XB5_LVL},
+ {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I},
+ {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR},
+ {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR},
+ {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP},
+ {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A},
+ {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B},
+ {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR},
+ {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A},
+ {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B},
+ {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
+ { 6, 0x989c,
+ { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
+ { 6, 0x989c,
+ { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
+ { 6, 0x989c,
+ { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
+ { 6, 0x989c,
+ { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
+ { 6, 0x989c,
+ { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
+ { 6, 0x989c,
+ { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
+ { 6, 0x989c,
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c,
+ { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
+ { 6, 0x989c,
+ { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
+ { 6, 0x989c,
+ { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
+ { 6, 0x989c,
+ { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
+ { 6, 0x989c,
+ { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
+ { 6, 0x989c,
+ { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
+ { 6, 0x989c,
+ { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
+ { 6, 0x989c,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
+ { 6, 0x989c,
+ { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
+ { 6, 0x989c,
+ { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
+ { 6, 0x989c,
+ { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
+ { 6, 0x989c,
+ { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
+ { 6, 0x98d8,
+ { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
+ { 7, 0x989c,
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c,
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c,
+ { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c,
+ { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
+ { 7, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c,
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c,
+ { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
+ { 7, 0x989c,
+ { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
+ { 7, 0x989c,
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c,
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c,
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+
+
+/******************\
+* RF2413 (Griffin) *
+\******************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 }
+#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2413[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ},
+};
+
+/* Default mode specific settings
+ * XXX: a/aTurbo ???
+ */
+static const struct ath5k_ini_rfbuffer rfb_2413[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
+ { 6, 0x989c,
+ { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
+ { 6, 0x989c,
+ { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
+ { 6, 0x989c,
+ { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
+ { 6, 0x989c,
+ { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
+ { 6, 0x989c,
+ { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
+ { 6, 0x989c,
+ { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
+ { 6, 0x989c,
+ { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
+ { 6, 0x989c,
+ { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
+ { 6, 0x989c,
+ { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
+ { 6, 0x989c,
+ { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
+ { 6, 0x989c,
+ { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
+ { 6, 0x989c,
+ { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
+ { 6, 0x98d8,
+ { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***************************\
+* RF2315/RF2316 (Cobra SoC) *
+\***************************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 }
+#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2316[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_2316[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
+ { 6, 0x989c,
+ { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c,
+ { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
+ { 6, 0x989c,
+ { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
+ { 6, 0x989c,
+ { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
+ { 6, 0x989c,
+ { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
+ { 6, 0x989c,
+ { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
+ { 6, 0x989c,
+ { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c,
+ { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
+ { 6, 0x989c,
+ { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
+ { 6, 0x989c,
+ { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
+ { 6, 0x989c,
+ { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
+ { 6, 0x989c,
+ { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
+ { 6, 0x989c,
+ { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
+ { 6, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 6, 0x989c,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 6, 0x989c,
+ { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
+ { 6, 0x989c,
+ { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
+ { 6, 0x98c0,
+ { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/******************************\
+* RF5413/RF5424 (Eagle/Condor) *
+\******************************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF5413_OB_2GHZ { 3, 241, 0 }
+#define AR5K_RF5413_DB_2GHZ { 3, 238, 0 }
+
+#define AR5K_RF5413_OB_5GHZ { 3, 247, 0 }
+#define AR5K_RF5413_DB_5GHZ { 3, 244, 0 }
+
+#define AR5K_RF5413_PWD_ICLOBUF2G { 3, 131, 3 }
+#define AR5K_RF5413_DERBY_CHAN_SEL_MODE { 1, 291, 2 }
+
+static const struct ath5k_rf_reg rf_regs_5413[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF5413_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF5413_DB_2GHZ},
+ {6, AR5K_RF_OB_5GHZ, AR5K_RF5413_OB_5GHZ},
+ {6, AR5K_RF_DB_5GHZ, AR5K_RF5413_DB_5GHZ},
+ {6, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF5413_PWD_ICLOBUF2G},
+ {6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5413[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+ { 3, 0x98dc,
+ { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
+ { 6, 0x989c,
+ { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
+ { 6, 0x989c,
+ { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
+ { 6, 0x989c,
+ { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
+ { 6, 0x989c,
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c,
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c,
+ { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
+ { 6, 0x989c,
+ { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
+ { 6, 0x989c,
+ { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
+ { 6, 0x989c,
+ { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
+ { 6, 0x989c,
+ { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
+ { 6, 0x989c,
+ { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
+ { 6, 0x989c,
+ { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c,
+ { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
+ { 6, 0x989c,
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c,
+ { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
+ { 6, 0x989c,
+ { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
+ { 6, 0x989c,
+ { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
+ { 6, 0x989c,
+ { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
+ { 6, 0x989c,
+ { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
+ { 6, 0x989c,
+ { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
+ { 6, 0x989c,
+ { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
+ { 6, 0x98c8,
+ { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***************************\
+* RF2425/RF2417 (Swan/Nala) *
+* AR2317 (Spider SoC) *
+\***************************/
+
+/* BANK 6 len pos col */
+#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 }
+#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2425[] = {
+ {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ},
+ {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ},
+};
+
+/* Default mode specific settings
+ * XXX: a/aTurbo ?
+ */
+static const struct ath5k_ini_rfbuffer rfb_2425[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c,
+ { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c,
+ { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
+ { 6, 0x989c,
+ { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
+ { 6, 0x989c,
+ { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c,
+ { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
+ { 6, 0x989c,
+ { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c,
+ { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+ { 6, 0x989c,
+ { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c,
+ { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
+ { 6, 0x98c4,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+/*
+ * TODO: Handle the few differences with swan during
+ * bank modification and get rid of this
+ */
+static const struct ath5k_ini_rfbuffer rfb_2317[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c,
+ { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c,
+ { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
+ { 6, 0x989c,
+ { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
+ { 6, 0x989c,
+ { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c,
+ { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
+ { 6, 0x989c,
+ { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c,
+ { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+ { 6, 0x989c,
+ { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c,
+ { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
+ { 6, 0x98c4,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+/*
+ * TODO: Handle the few differences with swan during
+ * bank modification and get rid of this
+ * XXX: a/aTurbo ?
+ */
+static const struct ath5k_ini_rfbuffer rfb_2417[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc,
+ { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c,
+ { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c,
+ { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
+ { 6, 0x989c,
+ { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
+ { 6, 0x989c,
+ { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c,
+ { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
+ { 6, 0x989c,
+ { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c,
+ { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+ { 6, 0x989c,
+ { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c,
+ { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
+ { 6, 0x98c4,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfgain.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfgain.h
new file mode 100644
index 0000000..1354d8c
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/rfgain.h
@@ -0,0 +1,516 @@
+/*
+ * RF Gain optimization
+ *
+ * Copyright (c) 2004-2009 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Mode-specific RF Gain table (64bytes) for RF5111/5112
+ * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
+ * RF Gain values are included in AR5K_AR5210_INI)
+ */
+struct ath5k_ini_rfgain {
+ u16 rfg_register; /* RF Gain register address */
+ u32 rfg_value[2]; /* [freq (see below)] */
+};
+
+/* Initial RF Gain settings for RF5111 */
+static const struct ath5k_ini_rfgain rfgain_5111[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } },
+ { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } },
+ { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } },
+ { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } },
+ { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } },
+ { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } },
+ { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } },
+ { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } },
+ { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } },
+ { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } },
+ { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } },
+ { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } },
+ { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } },
+ { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } },
+ { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } },
+ { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } },
+ { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } },
+ { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } },
+ { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } },
+ { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } },
+ { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } },
+ { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } },
+ { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } },
+ { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } },
+ { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } },
+ { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } },
+ { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } },
+ { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } },
+ { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } },
+ { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } },
+ { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } },
+ { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } },
+ { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } },
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } },
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } },
+ { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } },
+ { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } },
+ { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } },
+ { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } },
+ { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } },
+ { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } },
+ { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } },
+ { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } },
+ { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } },
+ { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } },
+ { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } },
+ { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } },
+};
+
+/* Initial RF Gain settings for RF5112 */
+static const struct ath5k_ini_rfgain rfgain_5112[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
+ { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
+ { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
+ { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } },
+ { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } },
+ { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } },
+ { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } },
+ { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } },
+ { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } },
+ { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } },
+ { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } },
+ { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } },
+ { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } },
+ { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } },
+ { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } },
+ { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } },
+ { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } },
+ { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } },
+ { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } },
+ { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } },
+ { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } },
+ { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } },
+ { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } },
+ { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } },
+ { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } },
+ { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } },
+ { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } },
+ { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } },
+ { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } },
+ { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } },
+ { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } },
+ { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } },
+ { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } },
+ { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } },
+ { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } },
+ { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } },
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } },
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } },
+ { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } },
+ { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } },
+ { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } },
+ { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } },
+ { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } },
+ { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } },
+ { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } },
+ { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } },
+ { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } },
+ { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } },
+ { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } },
+ { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } },
+ { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } },
+ { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } },
+ { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } },
+ { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } },
+ { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } },
+};
+
+/* Initial RF Gain settings for RF2413 */
+static const struct ath5k_ini_rfgain rfgain_2413[] = {
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } },
+ { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } },
+ { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } },
+ { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } },
+ { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } },
+ { AR5K_RF_GAIN(8), { 0x00000000, 0x00000168 } },
+ { AR5K_RF_GAIN(9), { 0x00000000, 0x000001a8 } },
+ { AR5K_RF_GAIN(10), { 0x00000000, 0x000001e8 } },
+ { AR5K_RF_GAIN(11), { 0x00000000, 0x00000028 } },
+ { AR5K_RF_GAIN(12), { 0x00000000, 0x00000068 } },
+ { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } },
+ { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } },
+ { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } },
+ { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } },
+ { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } },
+ { AR5K_RF_GAIN(18), { 0x00000000, 0x00000190 } },
+ { AR5K_RF_GAIN(19), { 0x00000000, 0x000001d0 } },
+ { AR5K_RF_GAIN(20), { 0x00000000, 0x00000010 } },
+ { AR5K_RF_GAIN(21), { 0x00000000, 0x00000050 } },
+ { AR5K_RF_GAIN(22), { 0x00000000, 0x00000090 } },
+ { AR5K_RF_GAIN(23), { 0x00000000, 0x00000191 } },
+ { AR5K_RF_GAIN(24), { 0x00000000, 0x000001d1 } },
+ { AR5K_RF_GAIN(25), { 0x00000000, 0x00000011 } },
+ { AR5K_RF_GAIN(26), { 0x00000000, 0x00000051 } },
+ { AR5K_RF_GAIN(27), { 0x00000000, 0x00000091 } },
+ { AR5K_RF_GAIN(28), { 0x00000000, 0x00000178 } },
+ { AR5K_RF_GAIN(29), { 0x00000000, 0x000001b8 } },
+ { AR5K_RF_GAIN(30), { 0x00000000, 0x000001f8 } },
+ { AR5K_RF_GAIN(31), { 0x00000000, 0x00000038 } },
+ { AR5K_RF_GAIN(32), { 0x00000000, 0x00000078 } },
+ { AR5K_RF_GAIN(33), { 0x00000000, 0x00000199 } },
+ { AR5K_RF_GAIN(34), { 0x00000000, 0x000001d9 } },
+ { AR5K_RF_GAIN(35), { 0x00000000, 0x00000019 } },
+ { AR5K_RF_GAIN(36), { 0x00000000, 0x00000059 } },
+ { AR5K_RF_GAIN(37), { 0x00000000, 0x00000099 } },
+ { AR5K_RF_GAIN(38), { 0x00000000, 0x000000d9 } },
+ { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } },
+};
+
+/* Initial RF Gain settings for AR2316 */
+static const struct ath5k_ini_rfgain rfgain_2316[] = {
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000000, 0x000000c0 } },
+ { AR5K_RF_GAIN(4), { 0x00000000, 0x000000e0 } },
+ { AR5K_RF_GAIN(5), { 0x00000000, 0x000000e0 } },
+ { AR5K_RF_GAIN(6), { 0x00000000, 0x00000128 } },
+ { AR5K_RF_GAIN(7), { 0x00000000, 0x00000128 } },
+ { AR5K_RF_GAIN(8), { 0x00000000, 0x00000128 } },
+ { AR5K_RF_GAIN(9), { 0x00000000, 0x00000168 } },
+ { AR5K_RF_GAIN(10), { 0x00000000, 0x000001a8 } },
+ { AR5K_RF_GAIN(11), { 0x00000000, 0x000001e8 } },
+ { AR5K_RF_GAIN(12), { 0x00000000, 0x00000028 } },
+ { AR5K_RF_GAIN(13), { 0x00000000, 0x00000068 } },
+ { AR5K_RF_GAIN(14), { 0x00000000, 0x000000a8 } },
+ { AR5K_RF_GAIN(15), { 0x00000000, 0x000000e8 } },
+ { AR5K_RF_GAIN(16), { 0x00000000, 0x000000e8 } },
+ { AR5K_RF_GAIN(17), { 0x00000000, 0x00000130 } },
+ { AR5K_RF_GAIN(18), { 0x00000000, 0x00000130 } },
+ { AR5K_RF_GAIN(19), { 0x00000000, 0x00000170 } },
+ { AR5K_RF_GAIN(20), { 0x00000000, 0x000001b0 } },
+ { AR5K_RF_GAIN(21), { 0x00000000, 0x000001f0 } },
+ { AR5K_RF_GAIN(22), { 0x00000000, 0x00000030 } },
+ { AR5K_RF_GAIN(23), { 0x00000000, 0x00000070 } },
+ { AR5K_RF_GAIN(24), { 0x00000000, 0x000000b0 } },
+ { AR5K_RF_GAIN(25), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(26), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(27), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(28), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(29), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(30), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(31), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(32), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(33), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(34), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(35), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(36), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f0 } },
+ { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f0 } },
+};
+
+
+/* Initial RF Gain settings for RF5413 */
+static const struct ath5k_ini_rfgain rfgain_5413[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } },
+ { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } },
+ { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } },
+ { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } },
+ { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } },
+ { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } },
+ { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } },
+ { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } },
+ { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } },
+ { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } },
+ { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } },
+ { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } },
+ { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } },
+ { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } },
+ { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } },
+ { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } },
+ { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } },
+ { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } },
+ { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } },
+ { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } },
+ { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } },
+ { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } },
+ { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } },
+ { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } },
+ { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } },
+ { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } },
+ { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } },
+ { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } },
+ { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } },
+ { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } },
+ { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } },
+ { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } },
+ { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } },
+ { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } },
+ { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } },
+ { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } },
+ { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
+};
+
+
+/* Initial RF Gain settings for RF2425 */
+static const struct ath5k_ini_rfgain rfgain_2425[] = {
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } },
+ { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } },
+ { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } },
+ { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } },
+ { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } },
+ { AR5K_RF_GAIN(8), { 0x00000000, 0x00000188 } },
+ { AR5K_RF_GAIN(9), { 0x00000000, 0x000001c8 } },
+ { AR5K_RF_GAIN(10), { 0x00000000, 0x00000008 } },
+ { AR5K_RF_GAIN(11), { 0x00000000, 0x00000048 } },
+ { AR5K_RF_GAIN(12), { 0x00000000, 0x00000088 } },
+ { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } },
+ { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } },
+ { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } },
+ { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } },
+ { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } },
+ { AR5K_RF_GAIN(18), { 0x00000000, 0x000001b0 } },
+ { AR5K_RF_GAIN(19), { 0x00000000, 0x000001f0 } },
+ { AR5K_RF_GAIN(20), { 0x00000000, 0x00000030 } },
+ { AR5K_RF_GAIN(21), { 0x00000000, 0x00000070 } },
+ { AR5K_RF_GAIN(22), { 0x00000000, 0x00000171 } },
+ { AR5K_RF_GAIN(23), { 0x00000000, 0x000001b1 } },
+ { AR5K_RF_GAIN(24), { 0x00000000, 0x000001f1 } },
+ { AR5K_RF_GAIN(25), { 0x00000000, 0x00000031 } },
+ { AR5K_RF_GAIN(26), { 0x00000000, 0x00000071 } },
+ { AR5K_RF_GAIN(27), { 0x00000000, 0x000001b8 } },
+ { AR5K_RF_GAIN(28), { 0x00000000, 0x000001f8 } },
+ { AR5K_RF_GAIN(29), { 0x00000000, 0x00000038 } },
+ { AR5K_RF_GAIN(30), { 0x00000000, 0x00000078 } },
+ { AR5K_RF_GAIN(31), { 0x00000000, 0x000000b8 } },
+ { AR5K_RF_GAIN(32), { 0x00000000, 0x000001b9 } },
+ { AR5K_RF_GAIN(33), { 0x00000000, 0x000001f9 } },
+ { AR5K_RF_GAIN(34), { 0x00000000, 0x00000039 } },
+ { AR5K_RF_GAIN(35), { 0x00000000, 0x00000079 } },
+ { AR5K_RF_GAIN(36), { 0x00000000, 0x000000b9 } },
+ { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } },
+};
+
+#define AR5K_GAIN_CRN_FIX_BITS_5111 4
+#define AR5K_GAIN_CRN_FIX_BITS_5112 7
+#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
+#define AR5K_GAIN_CCK_PROBE_CORR 5
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
+#define AR5K_GAIN_STEP_COUNT 10
+
+/* Check if our current measurement is inside our
+ * current variable attenuation window */
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
+ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
+
+struct ath5k_gain_opt_step {
+ s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
+ s8 gos_gain;
+};
+
+struct ath5k_gain_opt {
+ u8 go_default;
+ u8 go_steps_count;
+ const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
+};
+
+/*
+ * Parameters on gos_param:
+ * 1) Tx clip PHY register
+ * 2) PWD 90 RF register
+ * 3) PWD 84 RF register
+ * 4) RFGainSel RF register
+ */
+static const struct ath5k_gain_opt rfgain_opt_5111 = {
+ 4,
+ 9,
+ {
+ { { 4, 1, 1, 1 }, 6 },
+ { { 4, 0, 1, 1 }, 4 },
+ { { 3, 1, 1, 1 }, 3 },
+ { { 4, 0, 0, 1 }, 1 },
+ { { 4, 1, 1, 0 }, 0 },
+ { { 4, 0, 1, 0 }, -2 },
+ { { 3, 1, 1, 0 }, -3 },
+ { { 4, 0, 0, 0 }, -4 },
+ { { 2, 1, 1, 0 }, -6 }
+ }
+};
+
+/*
+ * Parameters on gos_param:
+ * 1) Mixgain ovr RF register
+ * 2) PWD 138 RF register
+ * 3) PWD 137 RF register
+ * 4) PWD 136 RF register
+ * 5) PWD 132 RF register
+ * 6) PWD 131 RF register
+ * 7) PWD 130 RF register
+ */
+static const struct ath5k_gain_opt rfgain_opt_5112 = {
+ 1,
+ 8,
+ {
+ { { 3, 0, 0, 0, 0, 0, 0 }, 6 },
+ { { 2, 0, 0, 0, 0, 0, 0 }, 0 },
+ { { 1, 0, 0, 0, 0, 0, 0 }, -3 },
+ { { 0, 0, 0, 0, 0, 0, 0 }, -6 },
+ { { 0, 1, 1, 0, 0, 0, 0 }, -8 },
+ { { 0, 1, 1, 0, 1, 1, 0 }, -10 },
+ { { 0, 1, 0, 1, 1, 1, 0 }, -13 },
+ { { 0, 1, 0, 1, 1, 0, 1 }, -16 },
+ }
+};
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/atl1e.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/atl1e.c
new file mode 100644
index 0000000..664eba0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/atl1e.c
@@ -0,0 +1,1757 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * Modified for gPXE, October 2009 by Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "atl1e.h"
+
+/* User-tweakable parameters: */
+#define TX_DESC_COUNT 32 /* TX descriptors, minimum 32 */
+#define RX_MEM_SIZE 8192 /* RX area size, minimum 8kb */
+#define MAX_FRAME_SIZE 1500 /* Maximum MTU supported, minimum 1500 */
+
+/* Arcane parameters: */
+#define PREAMBLE_LEN 7
+#define RX_JUMBO_THRESH ((MAX_FRAME_SIZE + ETH_HLEN + \
+ VLAN_HLEN + ETH_FCS_LEN + 7) >> 3)
+#define IMT_VAL 100 /* interrupt moderator timer, us */
+#define ICT_VAL 50000 /* interrupt clear timer, us */
+#define SMB_TIMER 200000
+#define RRD_THRESH 1 /* packets to queue before interrupt */
+#define TPD_BURST 5
+#define TPD_THRESH (TX_DESC_COUNT / 2)
+#define RX_COUNT_DOWN 4
+#define TX_COUNT_DOWN (IMT_VAL * 4 / 3)
+#define DMAR_DLY_CNT 15
+#define DMAW_DLY_CNT 4
+
+#define PCI_DEVICE_ID_ATTANSIC_L1E 0x1026
+
+/*
+ * atl1e_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ * Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1e_pci_tbl[] = {
+ PCI_ROM(0x1969, 0x1026, "atl1e_26", "Attansic L1E 0x1026", 0),
+ PCI_ROM(0x1969, 0x1066, "atl1e_66", "Attansic L1E 0x1066", 0),
+};
+
+static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
+
+static const u16
+atl1e_rx_page_vld_regs[AT_PAGE_NUM_PER_QUEUE] =
+{
+ REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD
+};
+
+static const u16
+atl1e_rx_page_lo_addr_regs[AT_PAGE_NUM_PER_QUEUE] =
+{
+ REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO
+};
+
+static const u16
+atl1e_rx_page_write_offset_regs[AT_PAGE_NUM_PER_QUEUE] =
+{
+ REG_HOST_RXF0_MB0_LO, REG_HOST_RXF0_MB1_LO
+};
+
+static const u16 atl1e_pay_load_size[] = {
+ 128, 256, 512, 1024, 2048, 4096,
+};
+
+/*
+ * atl1e_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
+{
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
+{
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
+{
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+static void atl1e_reset(struct atl1e_adapter *adapter)
+{
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+}
+
+static int atl1e_check_link(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u16 speed, duplex, phy_data;
+
+ /* MII_BMSR must read twise */
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+
+ if ((phy_data & BMSR_LSTATUS) == 0) {
+ /* link down */
+ if (netdev_link_ok(netdev)) { /* old link state: Up */
+ u32 value;
+ /* disable rx */
+ value = AT_READ_REG(hw, REG_MAC_CTRL);
+ value &= ~MAC_CTRL_RX_EN;
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+ adapter->link_speed = SPEED_0;
+
+ DBG("atl1e: %s link is down\n", netdev->name);
+ netdev_link_down(netdev);
+ }
+ } else {
+ /* Link Up */
+ err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
+ if (err)
+ return err;
+
+ /* link result is our setting */
+ if (adapter->link_speed != speed ||
+ adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl1e_setup_mac_ctrl(adapter);
+
+ DBG("atl1e: %s link is up, %d Mbps, %s duplex\n",
+ netdev->name, adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
+ "full" : "half");
+ netdev_link_up(netdev);
+ }
+ }
+ return 0;
+}
+
+static int atl1e_mdio_read(struct net_device *netdev, int phy_id __unused,
+ int reg_num)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+ return result;
+}
+
+static void atl1e_mdio_write(struct net_device *netdev, int phy_id __unused,
+ int reg_num, int val)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+static void atl1e_setup_pcicmd(struct pci_device *pdev)
+{
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd |= (PCI_COMMAND_MEM | PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ /*
+ * some motherboards BIOS(PXE/EFI) driver may set PME
+ * while they transfer control to OS (Windows/Linux)
+ * so we should clear this bit before NIC work normally
+ */
+ pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+ mdelay(1);
+}
+
+/*
+ * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1e_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int atl1e_sw_init(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct pci_device *pdev = adapter->pdev;
+ u32 phy_status_data = 0;
+ u8 rev_id = 0;
+
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+
+ /* PCI config space info */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+ /* nic type */
+ if (rev_id >= 0xF0) {
+ hw->nic_type = athr_l2e_revB;
+ } else {
+ if (phy_status_data & PHY_STATUS_100M)
+ hw->nic_type = athr_l1e;
+ else
+ hw->nic_type = athr_l2e_revA;
+ }
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+
+ hw->emi_ca = !!(phy_status_data & PHY_STATUS_EMI_CA);
+
+ hw->phy_configured = 0;
+
+ /* need confirm */
+
+ hw->dmar_block = atl1e_dma_req_1024;
+ hw->dmaw_block = atl1e_dma_req_1024;
+
+ netdev_link_down(adapter->netdev);
+
+ return 0;
+}
+
+/*
+ * atl1e_clean_tx_ring - free all Tx buffers for device close
+ * @adapter: board private structure
+ */
+static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 index, ring_count = tx_ring->count;
+
+ if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
+ return;
+
+ for (index = 0; index < ring_count; index++) {
+ tx_buffer = &tx_ring->tx_buffer[index];
+ if (tx_buffer->iob) {
+ netdev_tx_complete(adapter->netdev, tx_buffer->iob);
+ tx_buffer->dma = 0;
+ tx_buffer->iob = NULL;
+ }
+ }
+
+ /* Zero out Tx-buffers */
+ memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
+ ring_count);
+ memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
+ ring_count);
+}
+
+/*
+ * atl1e_clean_rx_ring - Free rx-reservation iobs
+ * @adapter: board private structure
+ */
+static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = &rx_ring->rx_page_desc;
+ u16 j;
+
+ if (adapter->ring_vir_addr == NULL)
+ return;
+
+ /* Zero out the descriptor ring */
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ if (rx_page_desc->rx_page[j].addr != NULL) {
+ memset(rx_page_desc->rx_page[j].addr, 0,
+ rx_ring->real_page_size);
+ }
+ }
+}
+
+static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
+{
+ *ring_size = ((u32)(adapter->tx_ring.count *
+ sizeof(struct atl1e_tpd_desc) + 7
+ /* tx ring, qword align */
+ + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE
+ + 31
+ /* rx ring, 32 bytes align */
+ + (1 + AT_PAGE_NUM_PER_QUEUE) *
+ sizeof(u32) + 3));
+ /* tx, rx cmd, dword align */
+}
+
+static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ rx_ring->real_page_size = adapter->rx_ring.page_size
+ + MAX_FRAME_SIZE
+ + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ rx_ring->real_page_size = (rx_ring->real_page_size + 31) & ~31;
+ atl1e_cal_ring_size(adapter, &adapter->ring_size);
+
+ adapter->ring_vir_addr = NULL;
+ adapter->rx_ring.desc = NULL;
+
+ return;
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int j;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+ rx_page_desc = &rx_ring->rx_page_desc;
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+
+ rx_page_desc->rx_using = 0;
+ rx_page_desc->rx_nxseq = 0;
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ *rx_page_desc->rx_page[j].write_offset_addr = 0;
+ rx_page_desc->rx_page[j].read_offset = 0;
+ }
+}
+
+/*
+ * atl1e_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1e_free_ring_resources(struct atl1e_adapter *adapter)
+{
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+
+ if (adapter->ring_vir_addr) {
+ free_dma(adapter->ring_vir_addr, adapter->ring_size);
+ adapter->ring_vir_addr = NULL;
+ adapter->ring_dma = 0;
+ }
+
+ if (adapter->tx_ring.tx_buffer) {
+ free(adapter->tx_ring.tx_buffer);
+ adapter->tx_ring.tx_buffer = NULL;
+ }
+}
+
+/*
+ * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring;
+ struct atl1e_rx_ring *rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc;
+ int size, j;
+ u32 offset = 0;
+ int err = 0;
+
+ if (adapter->ring_vir_addr != NULL)
+ return 0; /* alloced already */
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ /* real ring DMA buffer */
+
+ size = adapter->ring_size;
+ adapter->ring_vir_addr = malloc_dma(adapter->ring_size, 32);
+
+ if (adapter->ring_vir_addr == NULL) {
+ DBG("atl1e: out of memory allocating %d bytes for %s ring\n",
+ adapter->ring_size, adapter->netdev->name);
+ return -ENOMEM;
+ }
+
+ adapter->ring_dma = virt_to_bus(adapter->ring_vir_addr);
+ memset(adapter->ring_vir_addr, 0, adapter->ring_size);
+
+ rx_page_desc = &rx_ring->rx_page_desc;
+
+ /* Init TPD Ring */
+ tx_ring->dma = (adapter->ring_dma + 7) & ~7;
+ offset = tx_ring->dma - adapter->ring_dma;
+ tx_ring->desc = (struct atl1e_tpd_desc *)
+ (adapter->ring_vir_addr + offset);
+ size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
+ tx_ring->tx_buffer = zalloc(size);
+ if (tx_ring->tx_buffer == NULL) {
+ DBG("atl1e: out of memory allocating %d bytes for %s txbuf\n",
+ size, adapter->netdev->name);
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ /* Init RXF-Pages */
+ offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count);
+ offset = (offset + 31) & ~31;
+
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc->rx_page[j].dma =
+ adapter->ring_dma + offset;
+ rx_page_desc->rx_page[j].addr =
+ adapter->ring_vir_addr + offset;
+ offset += rx_ring->real_page_size;
+ }
+
+ /* Init CMB dma address */
+ tx_ring->cmb_dma = adapter->ring_dma + offset;
+ tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset);
+ offset += sizeof(u32);
+
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc->rx_page[j].write_offset_dma =
+ adapter->ring_dma + offset;
+ rx_page_desc->rx_page[j].write_offset_addr =
+ adapter->ring_vir_addr + offset;
+ offset += sizeof(u32);
+ }
+
+ if (offset > adapter->ring_size) {
+ DBG("atl1e: ring miscalculation! need %d > %d bytes\n",
+ offset, adapter->ring_size);
+ err = -EINVAL;
+ goto failed;
+ }
+
+ return 0;
+failed:
+ atl1e_free_ring_resources(adapter);
+ return err;
+}
+
+static inline void atl1e_configure_des_ring(const struct atl1e_adapter *adapter)
+{
+
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_tx_ring *tx_ring =
+ (struct atl1e_tx_ring *)&adapter->tx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int j;
+
+ AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI, 0);
+ AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO, tx_ring->dma);
+ AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count));
+ AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO, tx_ring->cmb_dma);
+
+ rx_page_desc = &rx_ring->rx_page_desc;
+
+ /* RXF Page Physical address / Page Length */
+ AT_WRITE_REG(hw, REG_RXF0_BASE_ADDR_HI, 0);
+
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ u32 page_phy_addr;
+ u32 offset_phy_addr;
+
+ page_phy_addr = rx_page_desc->rx_page[j].dma;
+ offset_phy_addr = rx_page_desc->rx_page[j].write_offset_dma;
+
+ AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[j], page_phy_addr);
+ AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[j],
+ offset_phy_addr);
+ AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[j], 1);
+ }
+
+ /* Page Length */
+ AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size);
+ /* Load all of base address above */
+ AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+
+ return;
+}
+
+static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 dev_ctrl_data = 0;
+ u32 max_pay_load = 0;
+ u32 jumbo_thresh = 0;
+ u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
+
+ /* configure TXQ param */
+ if (hw->nic_type != athr_l2e_revB) {
+ extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ jumbo_thresh = MAX_FRAME_SIZE + extra_size;
+ AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3);
+ }
+
+ dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL);
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
+ DEVICE_CTRL_MAX_PAYLOAD_MASK;
+ if (max_pay_load < hw->dmaw_block)
+ hw->dmaw_block = max_pay_load;
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
+ DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+ if (max_pay_load < hw->dmar_block)
+ hw->dmar_block = max_pay_load;
+
+ if (hw->nic_type != athr_l2e_revB)
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
+ atl1e_pay_load_size[hw->dmar_block]);
+ /* enable TXQ */
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL,
+ ((TPD_BURST & TXQ_CTRL_NUM_TPD_BURST_MASK)
+ << TXQ_CTRL_NUM_TPD_BURST_SHIFT)
+ | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN);
+ return;
+}
+
+static inline void atl1e_configure_rx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 rxf_len = 0;
+ u32 rxf_low = 0;
+ u32 rxf_high = 0;
+ u32 rxf_thresh_data = 0;
+ u32 rxq_ctrl_data = 0;
+
+ if (hw->nic_type != athr_l2e_revB) {
+ AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM,
+ (u16)((RX_JUMBO_THRESH & RXQ_JMBOSZ_TH_MASK) <<
+ RXQ_JMBOSZ_TH_SHIFT |
+ (1 & RXQ_JMBO_LKAH_MASK) <<
+ RXQ_JMBO_LKAH_SHIFT));
+
+ rxf_len = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+ rxf_high = rxf_len * 4 / 5;
+ rxf_low = rxf_len / 5;
+ rxf_thresh_data = ((rxf_high & RXQ_RXF_PAUSE_TH_HI_MASK)
+ << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK)
+ << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+
+ AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data);
+ }
+
+ /* RRS */
+ AT_WRITE_REG(hw, REG_IDT_TABLE, 0);
+ AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, 0);
+
+ rxq_ctrl_data |= RXQ_CTRL_PBA_ALIGN_32 |
+ RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+
+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+ return;
+}
+
+static inline void atl1e_configure_dma(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 dma_ctrl_data = 0;
+
+ dma_ctrl_data = DMA_CTRL_RXCMB_EN;
+ dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+ dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+ << DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+ dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER;
+ dma_ctrl_data |= (DMAR_DLY_CNT & DMA_CTRL_DMAR_DLY_CNT_MASK)
+ << DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+ dma_ctrl_data |= (DMAW_DLY_CNT & DMA_CTRL_DMAW_DLY_CNT_MASK)
+ << DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+ AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+ return;
+}
+
+static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
+{
+ u32 value;
+ struct atl1e_hw *hw = &adapter->hw;
+
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN |
+ MAC_CTRL_RX_EN ;
+
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+
+ value |= ((u32)((SPEED_1000 == adapter->link_speed) ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+ MAC_CTRL_SPEED_SHIFT);
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ value |= ((PREAMBLE_LEN & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+
+ value |= MAC_CTRL_BC_EN;
+ value |= MAC_CTRL_MC_ALL_EN;
+
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+}
+
+/*
+ * atl1e_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1e_configure(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 intr_status_data = 0;
+
+ /* clear interrupt status */
+ AT_WRITE_REG(hw, REG_ISR, ~0);
+
+ /* 1. set MAC Address */
+ atl1e_hw_set_mac_addr(hw);
+
+ /* 2. Init the Multicast HASH table (clear) */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ /* 3. Clear any WOL status */
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr
+ * TPD Ring/SMB/RXF0 Page CMBs, they use the same
+ * High 32bits memory */
+ atl1e_configure_des_ring(adapter);
+
+ /* 5. set Interrupt Moderator Timer */
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, IMT_VAL);
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, IMT_VAL);
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE |
+ MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN);
+
+ /* 6. rx/tx threshold to trig interrupt */
+ AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, RRD_THRESH);
+ AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, TPD_THRESH);
+ AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, RX_COUNT_DOWN);
+ AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, TX_COUNT_DOWN);
+
+ /* 7. set Interrupt Clear Timer */
+ AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, ICT_VAL);
+
+ /* 8. set MTU */
+ AT_WRITE_REG(hw, REG_MTU, MAX_FRAME_SIZE + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN);
+
+ /* 9. config TXQ early tx threshold */
+ atl1e_configure_tx(adapter);
+
+ /* 10. config RXQ */
+ atl1e_configure_rx(adapter);
+
+ /* 11. config DMA Engine */
+ atl1e_configure_dma(adapter);
+
+ /* 12. smb timer to trig interrupt */
+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, SMB_TIMER);
+
+ intr_status_data = AT_READ_REG(hw, REG_ISR);
+ if ((intr_status_data & ISR_PHY_LINKDOWN) != 0) {
+ DBG("atl1e: configure failed, PCIE phy link down\n");
+ return -1;
+ }
+
+ AT_WRITE_REG(hw, REG_ISR, 0x7fffffff);
+ return 0;
+}
+
+static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter)
+{
+ u16 phy_data;
+
+ atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data);
+}
+
+static int atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
+ u16 next_to_clean = tx_ring->next_to_clean;
+
+ while (next_to_clean != hw_next_to_clean) {
+ tx_buffer = &tx_ring->tx_buffer[next_to_clean];
+
+ tx_buffer->dma = 0;
+ if (tx_buffer->iob) {
+ netdev_tx_complete(adapter->netdev, tx_buffer->iob);
+ tx_buffer->iob = NULL;
+ }
+
+ if (++next_to_clean == tx_ring->count)
+ next_to_clean = 0;
+ }
+
+ tx_ring->next_to_clean = next_to_clean;
+
+ return 1;
+}
+
+static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) &adapter->rx_ring.rx_page_desc;
+ u8 rx_using = rx_page_desc->rx_using;
+
+ return (struct atl1e_rx_page *)&(rx_page_desc->rx_page[rx_using]);
+}
+
+static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *)
+ &adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) &rx_ring->rx_page_desc;
+ struct io_buffer *iob = NULL;
+ struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter);
+ u32 packet_size, write_offset;
+ struct atl1e_recv_ret_status *prrs;
+
+ write_offset = *(rx_page->write_offset_addr);
+ if (rx_page->read_offset >= write_offset)
+ return;
+
+ do {
+ /* get new packet's rrs */
+ prrs = (struct atl1e_recv_ret_status *) (rx_page->addr +
+ rx_page->read_offset);
+ /* check sequence number */
+ if (prrs->seq_num != rx_page_desc->rx_nxseq) {
+ DBG("atl1e %s: RX sequence number error (%d != %d)\n",
+ netdev->name, prrs->seq_num,
+ rx_page_desc->rx_nxseq);
+ rx_page_desc->rx_nxseq++;
+ goto fatal_err;
+ }
+
+ rx_page_desc->rx_nxseq++;
+
+ /* error packet */
+ if (prrs->pkt_flag & RRS_IS_ERR_FRAME) {
+ if (prrs->err_flag & (RRS_ERR_BAD_CRC |
+ RRS_ERR_DRIBBLE | RRS_ERR_CODE |
+ RRS_ERR_TRUNC)) {
+ /* hardware error, discard this
+ packet */
+ netdev_rx_err(netdev, NULL, EIO);
+ goto skip_pkt;
+ }
+ }
+
+ packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) - ETH_FCS_LEN;
+ iob = alloc_iob(packet_size + NET_IP_ALIGN);
+ if (iob == NULL) {
+ DBG("atl1e %s: dropping packet under memory pressure\n",
+ netdev->name);
+ goto skip_pkt;
+ }
+ iob_reserve(iob, NET_IP_ALIGN);
+ memcpy(iob->data, (u8 *)(prrs + 1), packet_size);
+ iob_put(iob, packet_size);
+
+ netdev_rx(netdev, iob);
+
+skip_pkt:
+ /* skip current packet whether it's ok or not. */
+ rx_page->read_offset +=
+ (((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) +
+ sizeof(struct atl1e_recv_ret_status) + 31) &
+ 0xFFFFFFE0);
+
+ if (rx_page->read_offset >= rx_ring->page_size) {
+ /* mark this page clean */
+ u16 reg_addr;
+ u8 rx_using;
+
+ rx_page->read_offset =
+ *(rx_page->write_offset_addr) = 0;
+ rx_using = rx_page_desc->rx_using;
+ reg_addr =
+ atl1e_rx_page_vld_regs[rx_using];
+ AT_WRITE_REGB(&adapter->hw, reg_addr, 1);
+ rx_page_desc->rx_using ^= 1;
+ rx_page = atl1e_get_rx_page(adapter);
+ }
+ write_offset = *(rx_page->write_offset_addr);
+ } while (rx_page->read_offset < write_offset);
+
+ return;
+
+fatal_err:
+ if (!netdev_link_ok(adapter->netdev))
+ atl1e_reset(adapter);
+}
+
+/*
+ * atl1e_poll - poll for completed transmissions and received packets
+ * @netdev: network device
+ */
+static void atl1e_poll(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ int max_ints = 64;
+ u32 status;
+
+ do {
+ status = AT_READ_REG(hw, REG_ISR);
+ if ((status & IMR_NORMAL_MASK) == 0)
+ break;
+
+ /* link event */
+ if (status & ISR_GPHY)
+ atl1e_clear_phy_int(adapter);
+ /* Ack ISR */
+ AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ DBG("atl1e: PCI-E PHY link down: %x\n", status);
+ if (netdev_link_ok(adapter->netdev)) {
+ /* reset MAC */
+ atl1e_irq_reset(adapter);
+ atl1e_reset(adapter);
+ break;
+ }
+ }
+
+ /* check if DMA read/write error */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ DBG("atl1e: PCI-E DMA RW error: %x\n", status);
+ atl1e_irq_reset(adapter);
+ atl1e_reset(adapter);
+ break;
+ }
+
+ /* link event */
+ if (status & (ISR_GPHY | ISR_MANUAL)) {
+ atl1e_check_link(adapter);
+ break;
+ }
+
+ /* transmit event */
+ if (status & ISR_TX_EVENT)
+ atl1e_clean_tx_irq(adapter);
+
+ if (status & ISR_RX_EVENT)
+ atl1e_clean_rx_irq(adapter);
+ } while (--max_ints > 0);
+
+ /* re-enable Interrupt*/
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+
+ return;
+}
+
+static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+ u16 next_to_clean = 0;
+
+ next_to_clean = tx_ring->next_to_clean;
+ next_to_use = tx_ring->next_to_use;
+
+ return (u16)(next_to_clean > next_to_use) ?
+ (next_to_clean - next_to_use - 1) :
+ (tx_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1e_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+
+ next_to_use = tx_ring->next_to_use;
+ if (++tx_ring->next_to_use == tx_ring->count)
+ tx_ring->next_to_use = 0;
+
+ memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc));
+ return (struct atl1e_tpd_desc *)&tx_ring->desc[next_to_use];
+}
+
+static struct atl1e_tx_buffer *
+atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+
+ return &tx_ring->tx_buffer[tpd - tx_ring->desc];
+}
+
+static void atl1e_tx_map(struct atl1e_adapter *adapter,
+ struct io_buffer *iob, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 buf_len = iob_len(iob);
+
+ tx_buffer = atl1e_get_tx_buffer(adapter, tpd);
+ tx_buffer->iob = iob;
+ tx_buffer->length = buf_len;
+ tx_buffer->dma = virt_to_bus(iob->data);
+ tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ tpd->word2 = ((tpd->word2 & ~TPD_BUFLEN_MASK) |
+ ((cpu_to_le32(buf_len) & TPD_BUFLEN_MASK) <<
+ TPD_BUFLEN_SHIFT));
+ tpd->word3 |= 1 << TPD_EOP_SHIFT;
+}
+
+static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count __unused,
+ struct atl1e_tpd_desc *tpd __unused)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ wmb();
+ AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use);
+}
+
+static int atl1e_xmit_frame(struct net_device *netdev, struct io_buffer *iob)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u16 tpd_req = 1;
+ struct atl1e_tpd_desc *tpd;
+
+ if (!netdev_link_ok(netdev)) {
+ return -EINVAL;
+ }
+
+ if (atl1e_tpd_avail(adapter) < tpd_req) {
+ return -EBUSY;
+ }
+
+ tpd = atl1e_get_tpd(adapter);
+
+ atl1e_tx_map(adapter, iob, tpd);
+ atl1e_tx_queue(adapter, tpd_req, tpd);
+
+ return 0;
+}
+
+int atl1e_up(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u32 val;
+
+ /* hardware has been reset, we need to reload some things */
+ err = atl1e_init_hw(&adapter->hw);
+ if (err) {
+ return -EIO;
+ }
+ atl1e_init_ring_ptrs(adapter);
+
+ memcpy(adapter->hw.mac_addr, netdev->ll_addr, ETH_ALEN);
+
+ if (atl1e_configure(adapter) != 0) {
+ return -EIO;
+ }
+
+ atl1e_irq_disable(adapter);
+
+ val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+ AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
+ val | MASTER_CTRL_MANUAL_INT);
+
+ return err;
+}
+
+void atl1e_irq(struct net_device *netdev, int enable)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ if (enable)
+ atl1e_irq_enable(adapter);
+ else
+ atl1e_irq_disable(adapter);
+}
+
+void atl1e_down(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* reset MAC to disable all RX/TX */
+ atl1e_reset_hw(&adapter->hw);
+ mdelay(1);
+
+ netdev_link_down(netdev);
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1e_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1e_open(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ /* allocate rx/tx dma buffer & descriptors */
+ atl1e_init_ring_resources(adapter);
+ err = atl1e_setup_ring_resources(adapter);
+ if (err)
+ return err;
+
+ err = atl1e_up(adapter);
+ if (err)
+ goto err_up;
+
+ return 0;
+
+err_up:
+ atl1e_free_ring_resources(adapter);
+ atl1e_reset_hw(&adapter->hw);
+
+ return err;
+}
+
+/*
+ * atl1e_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static void atl1e_close(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ atl1e_down(adapter);
+ atl1e_free_ring_resources(adapter);
+}
+
+static struct net_device_operations atl1e_netdev_ops = {
+ .open = atl1e_open,
+ .close = atl1e_close,
+ .transmit = atl1e_xmit_frame,
+ .poll = atl1e_poll,
+ .irq = atl1e_irq,
+};
+
+static void atl1e_init_netdev(struct net_device *netdev, struct pci_device *pdev)
+{
+ netdev_init(netdev, &atl1e_netdev_ops);
+
+ netdev->dev = &pdev->dev;
+ pci_set_drvdata(pdev, netdev);
+}
+
+/*
+ * atl1e_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1e_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1e_probe initializes an adapter identified by a pci_device structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int atl1e_probe(struct pci_device *pdev,
+ const struct pci_device_id *ent __unused)
+{
+ struct net_device *netdev;
+ struct atl1e_adapter *adapter = NULL;
+ static int cards_found;
+
+ int err = 0;
+
+ adjust_pci_device(pdev);
+
+ netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
+ if (netdev == NULL) {
+ err = -ENOMEM;
+ DBG("atl1e: out of memory allocating net_device\n");
+ goto err;
+ }
+
+ atl1e_init_netdev(netdev, pdev);
+
+ adapter = netdev_priv(netdev);
+ adapter->bd_number = cards_found;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.adapter = adapter;
+ if (!pdev->membase) {
+ err = -EIO;
+ DBG("atl1e: cannot map device registers\n");
+ goto err_free_netdev;
+ }
+ adapter->hw.hw_addr = bus_to_virt(pdev->membase);
+
+ /* init mii data */
+ adapter->mii.dev = netdev;
+ adapter->mii.mdio_read = atl1e_mdio_read;
+ adapter->mii.mdio_write = atl1e_mdio_write;
+ adapter->mii.phy_id_mask = 0x1f;
+ adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+
+ /* get user settings */
+ adapter->tx_ring.count = TX_DESC_COUNT;
+ adapter->rx_ring.page_size = RX_MEM_SIZE;
+
+ atl1e_setup_pcicmd(pdev);
+
+ /* setup the private structure */
+ err = atl1e_sw_init(adapter);
+ if (err) {
+ DBG("atl1e: private data init failed\n");
+ goto err_free_netdev;
+ }
+
+ /* Init GPHY as early as possible due to power saving issue */
+ atl1e_phy_init(&adapter->hw);
+
+ /* reset the controller to
+ * put the device in a known good starting state */
+ err = atl1e_reset_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_free_netdev;
+ }
+
+ /* This may have been run by a zero-wait timer around
+ now... unclear. */
+ atl1e_restart_autoneg(&adapter->hw);
+
+ if (atl1e_read_mac_addr(&adapter->hw) != 0) {
+ DBG("atl1e: cannot read MAC address from EEPROM\n");
+ err = -EIO;
+ goto err_free_netdev;
+ }
+
+ memcpy(netdev->hw_addr, adapter->hw.perm_mac_addr, ETH_ALEN);
+ memcpy(netdev->ll_addr, adapter->hw.mac_addr, ETH_ALEN);
+ DBG("atl1e: Attansic L1E Ethernet controller on %s, "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n", adapter->netdev->name,
+ adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+ adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+ adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+ err = register_netdev(netdev);
+ if (err) {
+ DBG("atl1e: cannot register network device\n");
+ goto err_free_netdev;
+ }
+
+ netdev_link_down(netdev);
+
+ cards_found++;
+ return 0;
+
+err_free_netdev:
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+err:
+ return err;
+}
+
+/*
+ * atl1e_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1e_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void atl1e_remove(struct pci_device *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ unregister_netdev(netdev);
+ atl1e_free_ring_resources(adapter);
+ atl1e_force_ps(&adapter->hw);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+struct pci_driver atl1e_driver __pci_driver = {
+ .ids = atl1e_pci_tbl,
+ .id_count = (sizeof(atl1e_pci_tbl) / sizeof(atl1e_pci_tbl[0])),
+ .probe = atl1e_probe,
+ .remove = atl1e_remove,
+};
+
+/********** Hardware-level functions: **********/
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
+{
+ u32 value;
+
+ value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+ }
+ value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
+{
+ u32 value;
+ /*
+ * 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword
+ */
+ value = (((u32)hw->mac_addr[2]) << 24) |
+ (((u32)hw->mac_addr[3]) << 16) |
+ (((u32)hw->mac_addr[4]) << 8) |
+ (((u32)hw->mac_addr[5])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+ /* hight dword */
+ value = (((u32)hw->mac_addr[0]) << 8) |
+ (((u32)hw->mac_addr[1])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1e_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1e_get_permanent_address(struct atl1e_hw *hw)
+{
+ u32 addr[2];
+ u32 i;
+ u32 twsi_ctrl_data;
+ u8 eth_addr[ETH_ALEN];
+
+ /* init */
+ addr[0] = addr[1] = 0;
+
+ if (!atl1e_check_eeprom_exist(hw)) {
+ /* eeprom exist */
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+ AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+ for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+ mdelay(10);
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+ break;
+ }
+ if (i >= AT_TWSI_EEPROM_TIMEOUT)
+ return AT_ERR_TIMEOUT;
+ }
+
+ /* maybe MAC-address is from BIOS */
+ addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+ addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+ *(u32 *) &eth_addr[2] = swap32(addr[0]);
+ *(u16 *) &eth_addr[0] = swap16(*(u16 *)&addr[1]);
+
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+}
+
+void atl1e_force_ps(struct atl1e_hw *hw)
+{
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+ GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1e_read_mac_addr(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_get_permanent_address(hw);
+ if (err)
+ return AT_ERR_EEPROM;
+ memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+ return 0;
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ u32 val;
+ int i;
+
+ val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16)val;
+ return 0;
+ }
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
+{
+ int i;
+ u32 val;
+
+ val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return 0;
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * atl1e_init_pcie - init PCIE module
+ */
+static void atl1e_init_pcie(struct atl1e_hw *hw)
+{
+ u32 value;
+ /* comment 2lines below to save more power when sususpend
+ value = LTSSM_TEST_MODE_DEF;
+ AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+ */
+
+ /* pcie flow control mode change */
+ value = AT_READ_REG(hw, 0x1008);
+ value |= 0x8000;
+ AT_WRITE_REG(hw, 0x1008, value);
+}
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
+{
+ s32 ret_val;
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ if (0 != hw->mii_autoneg_adv_reg)
+ return 0;
+ /* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+ mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+ /*
+ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+ /* Assume auto-detect media type */
+ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS |
+ MII_AR_100TX_FD_CAPS);
+ if (hw->nic_type == athr_l1e) {
+ mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
+ */
+int atl1e_phy_commit(struct atl1e_hw *hw)
+{
+ int ret_val;
+ u16 phy_data;
+
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /**************************************
+ * pcie serdes link may be down !
+ **************************************/
+ for (i = 0; i < 25; i++) {
+ mdelay(1);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+ DBG("atl1e: PCI-E link down for at least 25ms\n");
+ return ret_val;
+ }
+
+ DBG("atl1e: PCI-E link up after %d ms\n", i);
+ }
+ return 0;
+}
+
+int atl1e_phy_init(struct atl1e_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_val;
+
+ if (hw->phy_configured) {
+ if (hw->re_autoneg) {
+ hw->re_autoneg = 0;
+ return atl1e_restart_autoneg(hw);
+ }
+ return 0;
+ }
+
+ /* RESET GPHY Core */
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+ mdelay(2);
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+ GPHY_CTRL_EXT_RESET);
+ mdelay(2);
+
+ /* patches */
+ /* p1. eable hibernation mode */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
+ if (ret_val)
+ return ret_val;
+ /* p2. set Class A/B for all modes */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
+ if (ret_val)
+ return ret_val;
+ phy_val = 0x02ef;
+ /* remove Class AB */
+ /* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+ if (ret_val)
+ return ret_val;
+ /* p3. 10B ??? */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
+ if (ret_val)
+ return ret_val;
+ /* p4. 1000T power */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
+ if (ret_val)
+ return ret_val;
+
+ mdelay(1);
+
+ /*Enable PHY LinkChange Interrupt */
+ ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
+ if (ret_val) {
+ DBG("atl1e: Error enable PHY linkChange Interrupt\n");
+ return ret_val;
+ }
+ /* setup AutoNeg parameters */
+ ret_val = atl1e_phy_setup_autoneg_adv(hw);
+ if (ret_val) {
+ DBG("atl1e: Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
+ DBG("atl1e: Restarting Auto-Neg");
+ ret_val = atl1e_phy_commit(hw);
+ if (ret_val) {
+ DBG("atl1e: Error Resetting the phy");
+ return ret_val;
+ }
+
+ hw->phy_configured = 1;
+
+ return 0;
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0 or idle status (if error)
+ */
+int atl1e_reset_hw(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = hw->adapter;
+ struct pci_device *pdev = adapter->pdev;
+ int timeout = 0;
+ u32 idle_status_data = 0;
+ u16 pci_cfg_cmd_word = 0;
+
+ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_cfg_cmd_word);
+ if ((pci_cfg_cmd_word & (PCI_COMMAND_IO | PCI_COMMAND_MEM |
+ PCI_COMMAND_MASTER))
+ != (PCI_COMMAND_IO | PCI_COMMAND_MEM |
+ PCI_COMMAND_MASTER)) {
+ pci_cfg_cmd_word |= (PCI_COMMAND_IO | PCI_COMMAND_MEM |
+ PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, PCI_COMMAND, pci_cfg_cmd_word);
+ }
+
+ /*
+ * Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ AT_WRITE_REG(hw, REG_MASTER_CTRL,
+ MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
+ wmb();
+ mdelay(1);
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+ idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
+ if (idle_status_data == 0)
+ break;
+ mdelay(1);
+ }
+
+ if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+ DBG("atl1e: MAC reset timeout\n");
+ return AT_ERR_TIMEOUT;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+int atl1e_init_hw(struct atl1e_hw *hw)
+{
+ s32 ret_val = 0;
+
+ atl1e_init_pcie(hw);
+
+ /* Zero out the Multicast HASH table */
+ /* clear the old settings from the multicast hash table */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ ret_val = atl1e_phy_init(hw);
+
+ return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
+{
+ int err;
+ u16 phy_data;
+
+ /* Read PHY Specific Status Register (17) */
+ err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+ if (err)
+ return err;
+
+ if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+ return AT_ERR_PHY_RES;
+
+ switch (phy_data & MII_AT001_PSSR_SPEED) {
+ case MII_AT001_PSSR_1000MBS:
+ *speed = SPEED_1000;
+ break;
+ case MII_AT001_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_AT001_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ return AT_ERR_PHY_SPEED;
+ break;
+ }
+
+ if (phy_data & MII_AT001_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return 0;
+}
+
+int atl1e_restart_autoneg(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ if (err)
+ return err;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ hw->mii_1000t_ctrl_reg);
+ if (err)
+ return err;
+ }
+
+ err = atl1e_write_phy_reg(hw, MII_BMCR,
+ MII_CR_RESET | MII_CR_AUTO_NEG_EN |
+ MII_CR_RESTART_AUTO_NEG);
+ return err;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/b44.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/b44.c
new file mode 100644
index 0000000..c48b314
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/b44.c
@@ -0,0 +1,951 @@
+/*
+ * Copyright (c) 2008 Stefan Hajnoczi <stefanha@gmail.com>
+ * Copyright (c) 2008 Pantelis Koukousoulas <pktoss@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is a port of the b44 linux driver version 1.01
+ *
+ * Copyright (c) 2002 David S. Miller <davem@redhat.com>
+ * Copyright (c) Pekka Pietikainen <pp@ee.oulu.fi>
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Some ssb bits copied from version 2.0 of the b44 driver
+ * Copyright (c) Michael Buesch
+ *
+ * Copyright (c) a lot of people too. Please respect their work.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <gpxe/io.h>
+#include <mii.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/malloc.h>
+#include <gpxe/pci.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/memmap.h>
+#include "b44.h"
+
+
+static inline int ring_next(int index)
+{
+ /* B44_RING_SIZE is a power of 2 :) */
+ return (index + 1) & (B44_RING_SIZE - 1);
+}
+
+
+/* Memory-mapped I/O wrappers */
+
+static inline u32 br32(const struct b44_private *bp, u32 reg)
+{
+ return readl(bp->regs + reg);
+}
+
+
+static inline void bw32(const struct b44_private *bp, u32 reg, u32 val)
+{
+ writel(val, bp->regs + reg);
+}
+
+
+static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout)
+{
+ readl(bp->regs + reg);
+ udelay(timeout);
+}
+
+
+#define VIRT_TO_B44(addr) ( virt_to_bus(addr) + SB_PCI_DMA )
+
+
+/**
+ * Return non-zero if the installed RAM is within
+ * the limit given and zero if it is outside.
+ * Hopefully will be removed soon.
+ */
+int phys_ram_within_limit(u64 limit)
+{
+ struct memory_map memmap;
+ struct memory_region *highest = NULL;
+ get_memmap(&memmap);
+
+ highest = &memmap.regions[memmap.count - 1];
+
+ return (highest->end < limit);
+}
+
+
+/**
+ * Ring cells waiting to be processed are between 'tx_cur' and 'pending'
+ * indexes in the ring.
+ */
+static u32 pending_tx_index(struct b44_private *bp)
+{
+ u32 pending = br32(bp, B44_DMATX_STAT);
+ pending &= DMATX_STAT_CDMASK;
+
+ pending /= sizeof(struct dma_desc);
+ return pending & (B44_RING_SIZE - 1);
+}
+
+
+/**
+ * Ring cells waiting to be processed are between 'rx_cur' and 'pending'
+ * indexes in the ring.
+ */
+static u32 pending_rx_index(struct b44_private *bp)
+{
+ u32 pending = br32(bp, B44_DMARX_STAT);
+ pending &= DMARX_STAT_CDMASK;
+
+ pending /= sizeof(struct dma_desc);
+ return pending & (B44_RING_SIZE - 1);
+}
+
+
+/**
+ * Wait until the given bit is set/cleared.
+ */
+static int b44_wait_bit(struct b44_private *bp, unsigned long reg, u32 bit,
+ unsigned long timeout, const int clear)
+{
+ unsigned long i;
+
+ for (i = 0; i < timeout; i++) {
+ u32 val = br32(bp, reg);
+
+ if (clear && !(val & bit))
+ break;
+
+ if (!clear && (val & bit))
+ break;
+
+ udelay(10);
+ }
+ if (i == timeout) {
+ return -ENODEV;
+ }
+ return 0;
+}
+
+
+/*
+ * Sonics Silicon Backplane support. SSB is a mini-bus interconnecting
+ * so-called IP Cores. One of those cores implements the Fast Ethernet
+ * functionality and another one the PCI engine.
+ *
+ * You need to switch to the core you want to talk to before actually
+ * sending commands.
+ *
+ * See: http://bcm-v4.sipsolutions.net/Backplane for (reverse-engineered)
+ * specs.
+ */
+
+static inline u32 ssb_get_core_rev(struct b44_private *bp)
+{
+ return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
+}
+
+
+static inline int ssb_is_core_up(struct b44_private *bp)
+{
+ return ((br32(bp, B44_SBTMSLOW) & (SSB_CORE_DOWN | SBTMSLOW_CLOCK))
+ == SBTMSLOW_CLOCK);
+}
+
+
+static u32 ssb_pci_setup(struct b44_private *bp, u32 cores)
+{
+ u32 bar_orig, pci_rev, val;
+
+ pci_read_config_dword(bp->pci, SSB_BAR0_WIN, &bar_orig);
+ pci_write_config_dword(bp->pci, SSB_BAR0_WIN,
+ BCM4400_PCI_CORE_ADDR);
+ pci_rev = ssb_get_core_rev(bp);
+
+ val = br32(bp, B44_SBINTVEC);
+ val |= cores;
+ bw32(bp, B44_SBINTVEC, val);
+
+ val = br32(bp, SSB_PCI_TRANS_2);
+ val |= SSB_PCI_PREF | SSB_PCI_BURST;
+ bw32(bp, SSB_PCI_TRANS_2, val);
+
+ pci_write_config_dword(bp->pci, SSB_BAR0_WIN, bar_orig);
+
+ return pci_rev;
+}
+
+
+static void ssb_core_disable(struct b44_private *bp)
+{
+ if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
+ return;
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
+ b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
+ b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
+ SSB_CORE_DOWN));
+ bflush(bp, B44_SBTMSLOW, 1);
+
+ bw32(bp, B44_SBTMSLOW, SSB_CORE_DOWN);
+ bflush(bp, B44_SBTMSLOW, 1);
+}
+
+
+static void ssb_core_reset(struct b44_private *bp)
+{
+ u32 val;
+ const u32 mask = (SBTMSLOW_CLOCK | SBTMSLOW_FGC | SBTMSLOW_RESET);
+
+ ssb_core_disable(bp);
+
+ bw32(bp, B44_SBTMSLOW, mask);
+ bflush(bp, B44_SBTMSLOW, 1);
+
+ /* Clear SERR if set, this is a hw bug workaround. */
+ if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
+ bw32(bp, B44_SBTMSHIGH, 0);
+
+ val = br32(bp, B44_SBIMSTATE);
+ if (val & (SBIMSTATE_BAD)) {
+ bw32(bp, B44_SBIMSTATE, val & ~SBIMSTATE_BAD);
+ }
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
+ bflush(bp, B44_SBTMSLOW, 1);
+
+ bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
+ bflush(bp, B44_SBTMSLOW, 1);
+}
+
+
+/*
+ * Driver helper functions
+ */
+
+/*
+ * Chip reset provides power to the b44 MAC & PCI cores, which
+ * is necessary for MAC register access. We only do a partial
+ * reset in case of transmit/receive errors (ISTAT_ERRORS) to
+ * avoid the chip being hung for an unnecessary long time in
+ * this case.
+ *
+ * Called-by: b44_close, b44_halt, b44_inithw(b44_open), b44_probe
+ */
+static void b44_chip_reset(struct b44_private *bp, int reset_kind)
+{
+ if (ssb_is_core_up(bp)) {
+ bw32(bp, B44_RCV_LAZY, 0);
+
+ bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
+
+ b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
+
+ bw32(bp, B44_DMATX_CTRL, 0);
+
+ bp->tx_dirty = bp->tx_cur = 0;
+
+ if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK)
+ b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
+ 100, 0);
+
+ bw32(bp, B44_DMARX_CTRL, 0);
+
+ bp->rx_cur = 0;
+ } else {
+ ssb_pci_setup(bp, SBINTVEC_ENET0);
+ }
+
+ ssb_core_reset(bp);
+
+ /* Don't enable PHY if we are only doing a partial reset. */
+ if (reset_kind == B44_CHIP_RESET_PARTIAL)
+ return;
+
+ /* Make PHY accessible. */
+ bw32(bp, B44_MDIO_CTRL,
+ (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK)));
+ bflush(bp, B44_MDIO_CTRL, 1);
+
+ /* Enable internal or external PHY */
+ if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
+ bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
+ bflush(bp, B44_ENET_CTRL, 1);
+ } else {
+ u32 val = br32(bp, B44_DEVCTRL);
+ if (val & DEVCTRL_EPR) {
+ bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
+ bflush(bp, B44_DEVCTRL, 100);
+ }
+ }
+}
+
+
+/**
+ * called by b44_poll in the error path
+ */
+static void b44_halt(struct b44_private *bp)
+{
+ /* disable ints */
+ bw32(bp, B44_IMASK, 0);
+ bflush(bp, B44_IMASK, 1);
+
+ DBG("b44: powering down PHY\n");
+ bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
+
+ /*
+ * Now reset the chip, but without enabling
+ * the MAC&PHY part of it.
+ * This has to be done _after_ we shut down the PHY
+ */
+ b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
+}
+
+
+
+/*
+ * Called at device open time to get the chip ready for
+ * packet processing.
+ *
+ * Called-by: b44_open
+ */
+static void b44_init_hw(struct b44_private *bp, int reset_kind)
+{
+ u32 val;
+#define CTRL_MASK (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))
+
+ b44_chip_reset(bp, B44_CHIP_RESET_FULL);
+ if (reset_kind == B44_FULL_RESET) {
+ b44_phy_reset(bp);
+ }
+
+ /* Enable CRC32, set proper LED modes and power on PHY */
+ bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
+ bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
+
+ /* This sets the MAC address too. */
+ b44_set_rx_mode(bp->netdev);
+
+ /* MTU + eth header + possible VLAN tag + struct rx_header */
+ bw32(bp, B44_RXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
+ bw32(bp, B44_TXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
+
+ bw32(bp, B44_TX_HIWMARK, TX_HIWMARK_DEFLT);
+ if (reset_kind == B44_PARTIAL_RESET) {
+ bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
+ } else {
+ bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+ bw32(bp, B44_DMATX_ADDR, VIRT_TO_B44(bp->tx));
+
+ bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
+ bw32(bp, B44_DMARX_ADDR, VIRT_TO_B44(bp->rx));
+ bw32(bp, B44_DMARX_PTR, B44_RX_RING_LEN_BYTES);
+
+ bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+ }
+
+ val = br32(bp, B44_ENET_CTRL);
+ bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
+#undef CTRL_MASK
+}
+
+
+/*** Management of ring descriptors ***/
+
+
+static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx)
+{
+ struct rx_header *rh;
+ u32 ctrl, addr;
+
+ rh = bp->rx_iobuf[idx]->data;
+ rh->len = 0;
+ rh->flags = 0;
+ ctrl = DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET);
+ if (idx == B44_RING_LAST) {
+ ctrl |= DESC_CTRL_EOT;
+ }
+ addr = VIRT_TO_B44(bp->rx_iobuf[idx]->data);
+
+ bp->rx[idx].ctrl = cpu_to_le32(ctrl);
+ bp->rx[idx].addr = cpu_to_le32(addr);
+ bw32(bp, B44_DMARX_PTR, idx * sizeof(struct dma_desc));
+}
+
+
+/*
+ * Refill RX ring descriptors with buffers. This is needed
+ * because during rx we are passing ownership of descriptor
+ * buffers to the network stack.
+ */
+static void b44_rx_refill(struct b44_private *bp, u32 pending)
+{
+ u32 i;
+
+ // skip pending
+ for (i = pending + 1; i != bp->rx_cur; i = ring_next(i)) {
+ if (bp->rx_iobuf[i] != NULL)
+ continue;
+
+ bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ);
+ if (!bp->rx_iobuf[i]) {
+ DBG("Refill rx ring failed!!\n");
+ break;
+ }
+
+ b44_populate_rx_descriptor(bp, i);
+ }
+}
+
+
+static void b44_free_rx_ring(struct b44_private *bp)
+{
+ u32 i;
+
+ if (bp->rx) {
+ for (i = 0; i < B44_RING_SIZE; i++) {
+ free_iob(bp->rx_iobuf[i]);
+ bp->rx_iobuf[i] = NULL;
+ }
+ free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
+ bp->rx = NULL;
+ }
+}
+
+
+static int b44_init_rx_ring(struct b44_private *bp)
+{
+ b44_free_rx_ring(bp);
+
+ bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
+ if (!bp->rx)
+ return -ENOMEM;
+
+ memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf));
+
+ bp->rx_iobuf[0] = alloc_iob(RX_PKT_BUF_SZ);
+ b44_populate_rx_descriptor(bp, 0);
+ b44_rx_refill(bp, 0);
+
+ DBG("Init RX rings: rx=0x%08lx\n", VIRT_TO_B44(bp->rx));
+ return 0;
+}
+
+
+static void b44_free_tx_ring(struct b44_private *bp)
+{
+ if (bp->tx) {
+ free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
+ bp->tx = NULL;
+ }
+}
+
+
+static int b44_init_tx_ring(struct b44_private *bp)
+{
+ b44_free_tx_ring(bp);
+
+ bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
+ if (!bp->tx)
+ return -ENOMEM;
+
+ memset(bp->tx, 0, B44_TX_RING_LEN_BYTES);
+ memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf));
+
+ DBG("Init TX rings: tx=0x%08lx\n", VIRT_TO_B44(bp->tx));
+ return 0;
+}
+
+
+/*** Interaction with the PHY ***/
+
+
+static int b44_phy_read(struct b44_private *bp, int reg, u32 * val)
+{
+ int err;
+
+ u32 arg1 = (MDIO_OP_READ << MDIO_DATA_OP_SHIFT);
+ u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
+ u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
+ u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
+ u32 argv = arg1 | arg2 | arg3 | arg4;
+
+ bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
+ err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+ *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
+
+ return err;
+}
+
+
+static int b44_phy_write(struct b44_private *bp, int reg, u32 val)
+{
+ u32 arg1 = (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT);
+ u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
+ u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
+ u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
+ u32 arg5 = (val & MDIO_DATA_DATA);
+ u32 argv = arg1 | arg2 | arg3 | arg4 | arg5;
+
+
+ bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+ bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
+ return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+}
+
+
+static int b44_phy_reset(struct b44_private *bp)
+{
+ u32 val;
+ int err;
+
+ err = b44_phy_write(bp, MII_BMCR, BMCR_RESET);
+ if (err)
+ return err;
+
+ udelay(100);
+ err = b44_phy_read(bp, MII_BMCR, &val);
+ if (!err) {
+ if (val & BMCR_RESET) {
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * The BCM44xx CAM (Content Addressable Memory) stores the MAC
+ * and PHY address.
+ */
+static void b44_cam_write(struct b44_private *bp, unsigned char *data,
+ int index)
+{
+ u32 val;
+
+ val = ((u32) data[2]) << 24;
+ val |= ((u32) data[3]) << 16;
+ val |= ((u32) data[4]) << 8;
+ val |= ((u32) data[5]) << 0;
+ bw32(bp, B44_CAM_DATA_LO, val);
+
+
+ val = (CAM_DATA_HI_VALID |
+ (((u32) data[0]) << 8) | (((u32) data[1]) << 0));
+
+ bw32(bp, B44_CAM_DATA_HI, val);
+
+ val = CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT);
+ bw32(bp, B44_CAM_CTRL, val);
+
+ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
+}
+
+
+static void b44_set_mac_addr(struct b44_private *bp)
+{
+ u32 val;
+ bw32(bp, B44_CAM_CTRL, 0);
+ b44_cam_write(bp, bp->netdev->ll_addr, 0);
+ val = br32(bp, B44_CAM_CTRL);
+ bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+}
+
+
+/* Read 128-bytes of EEPROM. */
+static void b44_read_eeprom(struct b44_private *bp, u8 * data)
+{
+ long i;
+ u16 *ptr = (u16 *) data;
+
+ for (i = 0; i < 128; i += 2)
+ ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
+}
+
+
+static void b44_load_mac_and_phy_addr(struct b44_private *bp)
+{
+ u8 eeprom[128];
+
+ /* Load MAC address, note byteswapping */
+ b44_read_eeprom(bp, &eeprom[0]);
+ bp->netdev->hw_addr[0] = eeprom[79];
+ bp->netdev->hw_addr[1] = eeprom[78];
+ bp->netdev->hw_addr[2] = eeprom[81];
+ bp->netdev->hw_addr[3] = eeprom[80];
+ bp->netdev->hw_addr[4] = eeprom[83];
+ bp->netdev->hw_addr[5] = eeprom[82];
+
+ /* Load PHY address */
+ bp->phy_addr = eeprom[90] & 0x1f;
+}
+
+
+static void b44_set_rx_mode(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
+ u32 val;
+ int i;
+
+ val = br32(bp, B44_RXCONFIG);
+ val &= ~RXCONFIG_PROMISC;
+ val |= RXCONFIG_ALLMULTI;
+
+ b44_set_mac_addr(bp);
+
+ for (i = 1; i < 64; i++)
+ b44_cam_write(bp, zero, i);
+
+ bw32(bp, B44_RXCONFIG, val);
+ val = br32(bp, B44_CAM_CTRL);
+ bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+}
+
+
+/*** Implementation of gPXE driver callbacks ***/
+
+/**
+ * Probe device
+ *
+ * @v pci PCI device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+static int b44_probe(struct pci_device *pci, const struct pci_device_id *id)
+{
+ struct net_device *netdev;
+ struct b44_private *bp;
+ int rc;
+
+ /*
+ * Bail out if more than 1GB of physical RAM is installed.
+ * This limitation will be removed later when dma mapping
+ * is merged into mainline.
+ */
+ if (!phys_ram_within_limit(B44_30BIT_DMA_MASK)) {
+ DBG("Sorry, this version of the driver does not\n"
+ "support systems with more than 1GB of RAM.\n");
+ return -ENOMEM;
+ }
+
+ /* Set up netdev */
+ netdev = alloc_etherdev(sizeof(*bp));
+ if (!netdev)
+ return -ENOMEM;
+
+ netdev_init(netdev, &b44_operations);
+ pci_set_drvdata(pci, netdev);
+ netdev->dev = &pci->dev;
+
+ /* Set up private data */
+ bp = netdev_priv(netdev);
+ memset(bp, 0, sizeof(*bp));
+ bp->netdev = netdev;
+ bp->pci = pci;
+
+ /* Map device registers */
+ bp->regs = ioremap(pci->membase, B44_REGS_SIZE);
+ if (!bp->regs) {
+ netdev_put(netdev);
+ return -ENOMEM;
+ }
+
+ /* Enable PCI bus mastering */
+ adjust_pci_device(pci);
+
+ b44_load_mac_and_phy_addr(bp);
+
+ /* Link management currently not implemented */
+ netdev_link_up(netdev);
+
+ rc = register_netdev(netdev);
+ if (rc != 0) {
+ iounmap(bp->regs);
+ netdev_put(netdev);
+ return rc;
+ }
+
+ b44_chip_reset(bp, B44_CHIP_RESET_FULL);
+
+ DBG("b44 %s (%04x:%04x) regs=%p MAC=%s\n", id->name, id->vendor,
+ id->device, bp->regs, eth_ntoa(netdev->ll_addr));
+
+ return 0;
+}
+
+
+/**
+ * Remove device
+ *
+ * @v pci PCI device
+ */
+static void b44_remove(struct pci_device *pci)
+{
+ struct net_device *netdev = pci_get_drvdata(pci);
+ struct b44_private *bp = netdev_priv(netdev);
+
+ ssb_core_disable(bp);
+ unregister_netdev(netdev);
+ iounmap(bp->regs);
+ netdev_nullify(netdev);
+ netdev_put(netdev);
+}
+
+
+/** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void b44_irq(struct net_device *netdev, int enable)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+
+ /* Interrupt mask specifies which events generate interrupts */
+ bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
+}
+
+
+/** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int b44_open(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ int rc;
+
+ rc = b44_init_tx_ring(bp);
+ if (rc != 0)
+ return rc;
+
+ rc = b44_init_rx_ring(bp);
+ if (rc != 0)
+ return rc;
+
+ b44_init_hw(bp, B44_FULL_RESET);
+
+ /* Disable interrupts */
+ b44_irq(netdev, 0);
+
+ return 0;
+}
+
+
+/** Close network device
+ *
+ * @v netdev Network device
+ */
+static void b44_close(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+
+ b44_chip_reset(bp, B44_FULL_RESET);
+ b44_free_tx_ring(bp);
+ b44_free_rx_ring(bp);
+}
+
+
+/** Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ u32 cur = bp->tx_cur;
+ u32 ctrl;
+
+ /* Check for TX ring overflow */
+ if (bp->tx[cur].ctrl) {
+ DBG("tx overflow\n");
+ return -ENOBUFS;
+ }
+
+ /* Will call netdev_tx_complete() on the iobuf later */
+ bp->tx_iobuf[cur] = iobuf;
+
+ /* Set up TX descriptor */
+ ctrl = (iob_len(iobuf) & DESC_CTRL_LEN) |
+ DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;
+
+ if (cur == B44_RING_LAST)
+ ctrl |= DESC_CTRL_EOT;
+
+ bp->tx[cur].ctrl = cpu_to_le32(ctrl);
+ bp->tx[cur].addr = cpu_to_le32(VIRT_TO_B44(iobuf->data));
+
+ /* Update next available descriptor index */
+ cur = ring_next(cur);
+ bp->tx_cur = cur;
+ wmb();
+
+ /* Tell card that a new TX descriptor is ready */
+ bw32(bp, B44_DMATX_PTR, cur * sizeof(struct dma_desc));
+ return 0;
+}
+
+
+/** Recycles sent TX descriptors and notifies network stack
+ *
+ * @v bp Driver state
+ */
+static void b44_tx_complete(struct b44_private *bp)
+{
+ u32 cur, i;
+
+ cur = pending_tx_index(bp);
+
+ for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
+ /* Free finished frame */
+ netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
+ bp->tx_iobuf[i] = NULL;
+
+ /* Clear TX descriptor */
+ bp->tx[i].ctrl = 0;
+ bp->tx[i].addr = 0;
+ }
+ bp->tx_dirty = cur;
+}
+
+
+static void b44_process_rx_packets(struct b44_private *bp)
+{
+ struct io_buffer *iob; /* received data */
+ struct rx_header *rh;
+ u32 pending, i;
+ u16 len;
+
+ pending = pending_rx_index(bp);
+
+ for (i = bp->rx_cur; i != pending; i = ring_next(i)) {
+ iob = bp->rx_iobuf[i];
+ if (iob == NULL)
+ break;
+
+ rh = iob->data;
+ len = le16_to_cpu(rh->len);
+
+ /*
+ * Guard against incompletely written RX descriptors.
+ * Without this, things can get really slow!
+ */
+ if (len == 0)
+ break;
+
+ /* Discard CRC that is generated by the card */
+ len -= 4;
+
+ /* Check for invalid packets and errors */
+ if (len > RX_PKT_BUF_SZ - RX_PKT_OFFSET ||
+ (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
+ DBG("rx error len=%d flags=%04x\n", len,
+ cpu_to_le16(rh->flags));
+ rh->len = 0;
+ rh->flags = 0;
+ netdev_rx_err(bp->netdev, iob, -EINVAL);
+ continue;
+ }
+
+ /* Clear RX descriptor */
+ rh->len = 0;
+ rh->flags = 0;
+ bp->rx_iobuf[i] = NULL;
+
+ /* Hand off the IO buffer to the network stack */
+ iob_reserve(iob, RX_PKT_OFFSET);
+ iob_put(iob, len);
+ netdev_rx(bp->netdev, iob);
+ }
+ bp->rx_cur = i;
+ b44_rx_refill(bp, pending_rx_index(bp));
+}
+
+
+/** Poll for completed and received packets
+ *
+ * @v netdev Network device
+ */
+static void b44_poll(struct net_device *netdev)
+{
+ struct b44_private *bp = netdev_priv(netdev);
+ u32 istat;
+
+ /* Interrupt status */
+ istat = br32(bp, B44_ISTAT);
+ istat &= IMASK_DEF; /* only the events we care about */
+
+ if (!istat)
+ return;
+ if (istat & ISTAT_TX)
+ b44_tx_complete(bp);
+ if (istat & ISTAT_RX)
+ b44_process_rx_packets(bp);
+ if (istat & ISTAT_ERRORS) {
+ DBG("b44 error istat=0x%08x\n", istat);
+
+ /* Reset B44 core partially to avoid long waits */
+ b44_irq(bp->netdev, 0);
+ b44_halt(bp);
+ b44_init_tx_ring(bp);
+ b44_init_rx_ring(bp);
+ b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
+ }
+
+ /* Acknowledge interrupt */
+ bw32(bp, B44_ISTAT, 0);
+ bflush(bp, B44_ISTAT, 1);
+}
+
+
+static struct net_device_operations b44_operations = {
+ .open = b44_open,
+ .close = b44_close,
+ .transmit = b44_transmit,
+ .poll = b44_poll,
+ .irq = b44_irq,
+};
+
+
+static struct pci_device_id b44_nics[] = {
+ PCI_ROM(0x14e4, 0x4401, "BCM4401", "BCM4401", 0),
+ PCI_ROM(0x14e4, 0x170c, "BCM4401-B0", "BCM4401-B0", 0),
+ PCI_ROM(0x14e4, 0x4402, "BCM4401-B1", "BCM4401-B1", 0),
+};
+
+
+struct pci_driver b44_driver __pci_driver = {
+ .ids = b44_nics,
+ .id_count = sizeof b44_nics / sizeof b44_nics[0],
+ .probe = b44_probe,
+ .remove = b44_remove,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/b44.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/b44.h
new file mode 100644
index 0000000..b5afcbd
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/b44.h
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2008 Stefan Hajnoczi <stefanha@gmail.com>
+ * Copyright (c) 2008 Pantelis Koukousoulas <pktoss@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is a port of the b44 linux driver version 1.01
+ *
+ * Copyright (c) 2002 David S. Miller <davem@redhat.com>
+ * Copyright (c) Pekka Pietikainen <pp@ee.oulu.fi>
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Some ssb bits copied from version 2.0 of the b44 driver
+ * Copyright (c) Michael Buesch
+ *
+ * Copyright (c) a lot of people too. Please respect their work.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _B44_H
+#define _B44_H
+
+/* BCM44xx Register layout */
+#define B44_DEVCTRL 0x0000UL /* Device Control */
+#define DEVCTRL_MPM 0x00000040 /* MP PME Enable (B0 only) */
+#define DEVCTRL_PFE 0x00000080 /* Pattern Filtering Enable */
+#define DEVCTRL_IPP 0x00000400 /* Internal EPHY Present */
+#define DEVCTRL_EPR 0x00008000 /* EPHY Reset */
+#define DEVCTRL_PME 0x00001000 /* PHY Mode Enable */
+#define DEVCTRL_PMCE 0x00002000 /* PHY Mode Clocks Enable */
+#define DEVCTRL_PADDR 0x0007c000 /* PHY Address */
+#define DEVCTRL_PADDR_SHIFT 18
+#define B44_BIST_STAT 0x000CUL /* Built-In Self-Test Status */
+#define B44_WKUP_LEN 0x0010UL /* Wakeup Length */
+#define WKUP_LEN_P0_MASK 0x0000007f /* Pattern 0 */
+#define WKUP_LEN_D0 0x00000080
+#define WKUP_LEN_P1_MASK 0x00007f00 /* Pattern 1 */
+#define WKUP_LEN_P1_SHIFT 8
+#define WKUP_LEN_D1 0x00008000
+#define WKUP_LEN_P2_MASK 0x007f0000 /* Pattern 2 */
+#define WKUP_LEN_P2_SHIFT 16
+#define WKUP_LEN_D2 0x00000000
+#define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */
+#define WKUP_LEN_P3_SHIFT 24
+#define WKUP_LEN_D3 0x80000000
+#define WKUP_LEN_DISABLE 0x80808080
+#define WKUP_LEN_ENABLE_TWO 0x80800000
+#define WKUP_LEN_ENABLE_THREE 0x80000000
+#define B44_ISTAT 0x0020UL /* Interrupt Status */
+#define ISTAT_LS 0x00000020 /* Link Change (B0 only) */
+#define ISTAT_PME 0x00000040 /* Power Management Event */
+#define ISTAT_TO 0x00000080 /* General Purpose Timeout */
+#define ISTAT_DSCE 0x00000400 /* Descriptor Error */
+#define ISTAT_DATAE 0x00000800 /* Data Error */
+#define ISTAT_DPE 0x00001000 /* Descr. Protocol Error */
+#define ISTAT_RDU 0x00002000 /* Receive Descr. Underflow */
+#define ISTAT_RFO 0x00004000 /* Receive FIFO Overflow */
+#define ISTAT_TFU 0x00008000 /* Transmit FIFO Underflow */
+#define ISTAT_RX 0x00010000 /* RX Interrupt */
+#define ISTAT_TX 0x01000000 /* TX Interrupt */
+#define ISTAT_EMAC 0x04000000 /* EMAC Interrupt */
+#define ISTAT_MII_WRITE 0x08000000 /* MII Write Interrupt */
+#define ISTAT_MII_READ 0x10000000 /* MII Read Interrupt */
+#define ISTAT_ERRORS (ISTAT_DSCE|ISTAT_DATAE|ISTAT_DPE|\
+ ISTAT_RDU|ISTAT_RFO|ISTAT_TFU)
+#define B44_IMASK 0x0024UL /* Interrupt Mask */
+#define IMASK_DEF (ISTAT_ERRORS | ISTAT_RX | ISTAT_TX)
+#define IMASK_DISABLE 0
+#define B44_GPTIMER 0x0028UL /* General Purpose Timer */
+#define B44_ADDR_LO 0x0088UL /* ENET Address Lo (B0 only) */
+#define B44_ADDR_HI 0x008CUL /* ENET Address Hi (B0 only) */
+#define B44_FILT_ADDR 0x0090UL /* ENET Filter Address */
+#define B44_FILT_DATA 0x0094UL /* ENET Filter Data */
+#define B44_TXBURST 0x00A0UL /* TX Max Burst Length */
+#define B44_RXBURST 0x00A4UL /* RX Max Burst Length */
+#define B44_MAC_CTRL 0x00A8UL /* MAC Control */
+#define MAC_CTRL_CRC32_ENAB 0x00000001 /* CRC32 Generation Enable */
+#define MAC_CTRL_PHY_PDOWN 0x00000004 /* Onchip EPHY Powerdown */
+#define MAC_CTRL_PHY_EDET 0x00000008 /* Onchip EPHY Energy Detected*/
+#define MAC_CTRL_PHY_LEDCTRL 0x000000e0 /* Onchip EPHY LED Control */
+#define MAC_CTRL_PHY_LEDCTRL_SHIFT 5
+#define B44_MAC_FLOW 0x00ACUL /* MAC Flow Control */
+#define MAC_FLOW_RX_HI_WATER 0x000000ff /* Receive FIFO HI Water Mark */
+#define MAC_FLOW_PAUSE_ENAB 0x00008000 /* Enbl Pause Frm Generation */
+#define B44_RCV_LAZY 0x0100UL /* Lazy Interrupt Control */
+#define RCV_LAZY_TO_MASK 0x00ffffff /* Timeout */
+#define RCV_LAZY_FC_MASK 0xff000000 /* Frame Count */
+#define RCV_LAZY_FC_SHIFT 24
+#define B44_DMATX_CTRL 0x0200UL /* DMA TX Control */
+#define DMATX_CTRL_ENABLE 0x00000001 /* Enable */
+#define DMATX_CTRL_SUSPEND 0x00000002 /* Suepend Request */
+#define DMATX_CTRL_LPBACK 0x00000004 /* Loopback Enable */
+#define DMATX_CTRL_FAIRPRIOR 0x00000008 /* Fair Priority */
+#define DMATX_CTRL_FLUSH 0x00000010 /* Flush Request */
+#define B44_DMATX_ADDR 0x0204UL /* DMA TX Descriptor Ring Addr */
+#define B44_DMATX_PTR 0x0208UL /* DMA TX Last Posted Desc. */
+#define B44_DMATX_STAT 0x020CUL /* DMA TX Cur Actve Desc. + Sts */
+#define DMATX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */
+#define DMATX_STAT_SMASK 0x0000f000 /* State Mask */
+#define DMATX_STAT_SDISABLED 0x00000000 /* State Disabled */
+#define DMATX_STAT_SACTIVE 0x00001000 /* State Active */
+#define DMATX_STAT_SIDLE 0x00002000 /* State Idle Wait */
+#define DMATX_STAT_SSTOPPED 0x00003000 /* State Stopped */
+#define DMATX_STAT_SSUSP 0x00004000 /* State Suspend Pending */
+#define DMATX_STAT_EMASK 0x000f0000 /* Error Mask */
+#define DMATX_STAT_ENONE 0x00000000 /* Error None */
+#define DMATX_STAT_EDPE 0x00010000 /* Error Desc. Protocol Error */
+#define DMATX_STAT_EDFU 0x00020000 /* Error Data FIFO Underrun */
+#define DMATX_STAT_EBEBR 0x00030000 /* Bus Error on Buffer Read */
+#define DMATX_STAT_EBEDA 0x00040000 /* Bus Error on Desc. Access */
+#define DMATX_STAT_FLUSHED 0x00100000 /* Flushed */
+#define B44_DMARX_CTRL 0x0210UL /* DMA RX Control */
+#define DMARX_CTRL_ENABLE 0x00000001 /* Enable */
+#define DMARX_CTRL_ROMASK 0x000000fe /* Receive Offset Mask */
+#define DMARX_CTRL_ROSHIFT 1 /* Receive Offset Shift */
+#define B44_DMARX_ADDR 0x0214UL /* DMA RX Descriptor Ring Addr */
+#define B44_DMARX_PTR 0x0218UL /* DMA RX Last Posted Desc */
+#define B44_DMARX_STAT 0x021CUL /* Cur Active Desc. + Status */
+#define DMARX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */
+#define DMARX_STAT_SMASK 0x0000f000 /* State Mask */
+#define DMARX_STAT_SDISABLED 0x00000000 /* State Disbaled */
+#define DMARX_STAT_SACTIVE 0x00001000 /* State Active */
+#define DMARX_STAT_SIDLE 0x00002000 /* State Idle Wait */
+#define DMARX_STAT_SSTOPPED 0x00003000 /* State Stopped */
+#define DMARX_STAT_EMASK 0x000f0000 /* Error Mask */
+#define DMARX_STAT_ENONE 0x00000000 /* Error None */
+#define DMARX_STAT_EDPE 0x00010000 /* Error Desc. Protocol Error */
+#define DMARX_STAT_EDFO 0x00020000 /* Error Data FIFO Overflow */
+#define DMARX_STAT_EBEBW 0x00030000 /* Error on Buffer Write */
+#define DMARX_STAT_EBEDA 0x00040000 /* Bus Error on Desc. Access */
+#define B44_DMAFIFO_AD 0x0220UL /* DMA FIFO Diag Address */
+#define DMAFIFO_AD_OMASK 0x0000ffff /* Offset Mask */
+#define DMAFIFO_AD_SMASK 0x000f0000 /* Select Mask */
+#define DMAFIFO_AD_SXDD 0x00000000 /* Select Transmit DMA Data */
+#define DMAFIFO_AD_SXDP 0x00010000 /* Sel Transmit DMA Pointers */
+#define DMAFIFO_AD_SRDD 0x00040000 /* Select Receive DMA Data */
+#define DMAFIFO_AD_SRDP 0x00050000 /* Sel Receive DMA Pointers */
+#define DMAFIFO_AD_SXFD 0x00080000 /* Select Transmit FIFO Data */
+#define DMAFIFO_AD_SXFP 0x00090000 /* Sel Transmit FIFO Pointers */
+#define DMAFIFO_AD_SRFD 0x000c0000 /* Select Receive FIFO Data */
+#define DMAFIFO_AD_SRFP 0x000c0000 /* Sel Receive FIFO Pointers */
+#define B44_DMAFIFO_LO 0x0224UL /* DMA FIFO Diag Low Data */
+#define B44_DMAFIFO_HI 0x0228UL /* DMA FIFO Diag High Data */
+#define B44_RXCONFIG 0x0400UL /* EMAC RX Config */
+#define RXCONFIG_DBCAST 0x00000001 /* Disable Broadcast */
+#define RXCONFIG_ALLMULTI 0x00000002 /* Accept All Multicast */
+#define RXCONFIG_NORX_WHILE_TX 0x00000004 /* Rcv Disble While TX */
+#define RXCONFIG_PROMISC 0x00000008 /* Promiscuous Enable */
+#define RXCONFIG_LPBACK 0x00000010 /* Loopback Enable */
+#define RXCONFIG_FLOW 0x00000020 /* Flow Control Enable */
+#define RXCONFIG_FLOW_ACCEPT 0x00000040 /* Accept UFC Frame */
+#define RXCONFIG_RFILT 0x00000080 /* Reject Filter */
+#define B44_RXMAXLEN 0x0404UL /* EMAC RX Max Packet Length */
+#define B44_TXMAXLEN 0x0408UL /* EMAC TX Max Packet Length */
+#define B44_MDIO_CTRL 0x0410UL /* EMAC MDIO Control */
+#define MDIO_CTRL_MAXF_MASK 0x0000007f /* MDC Frequency */
+#define MDIO_CTRL_PREAMBLE 0x00000080 /* MII Preamble Enable */
+#define B44_MDIO_DATA 0x0414UL /* EMAC MDIO Data */
+#define MDIO_DATA_DATA 0x0000ffff /* R/W Data */
+#define MDIO_DATA_TA_MASK 0x00030000 /* Turnaround Value */
+#define MDIO_DATA_TA_SHIFT 16
+#define MDIO_TA_VALID 2
+#define MDIO_DATA_RA_MASK 0x007c0000 /* Register Address */
+#define MDIO_DATA_RA_SHIFT 18
+#define MDIO_DATA_PMD_MASK 0x0f800000 /* Physical Media Device */
+#define MDIO_DATA_PMD_SHIFT 23
+#define MDIO_DATA_OP_MASK 0x30000000 /* Opcode */
+#define MDIO_DATA_OP_SHIFT 28
+#define MDIO_OP_WRITE 1
+#define MDIO_OP_READ 2
+#define MDIO_DATA_SB_MASK 0xc0000000 /* Start Bits */
+#define MDIO_DATA_SB_SHIFT 30
+#define MDIO_DATA_SB_START 0x40000000 /* Start Of Frame */
+#define B44_EMAC_IMASK 0x0418UL /* EMAC Interrupt Mask */
+#define B44_EMAC_ISTAT 0x041CUL /* EMAC Interrupt Status */
+#define EMAC_INT_MII 0x00000001 /* MII MDIO Interrupt */
+#define EMAC_INT_MIB 0x00000002 /* MIB Interrupt */
+#define EMAC_INT_FLOW 0x00000003 /* Flow Control Interrupt */
+#define B44_CAM_DATA_LO 0x0420UL /* EMAC CAM Data Low */
+#define B44_CAM_DATA_HI 0x0424UL /* EMAC CAM Data High */
+#define CAM_DATA_HI_VALID 0x00010000 /* Valid Bit */
+#define B44_CAM_CTRL 0x0428UL /* EMAC CAM Control */
+#define CAM_CTRL_ENABLE 0x00000001 /* CAM Enable */
+#define CAM_CTRL_MSEL 0x00000002 /* Mask Select */
+#define CAM_CTRL_READ 0x00000004 /* Read */
+#define CAM_CTRL_WRITE 0x00000008 /* Read */
+#define CAM_CTRL_INDEX_MASK 0x003f0000 /* Index Mask */
+#define CAM_CTRL_INDEX_SHIFT 16
+#define CAM_CTRL_BUSY 0x80000000 /* CAM Busy */
+#define B44_ENET_CTRL 0x042CUL /* EMAC ENET Control */
+#define ENET_CTRL_ENABLE 0x00000001 /* EMAC Enable */
+#define ENET_CTRL_DISABLE 0x00000002 /* EMAC Disable */
+#define ENET_CTRL_SRST 0x00000004 /* EMAC Soft Reset */
+#define ENET_CTRL_EPSEL 0x00000008 /* External PHY Select */
+#define B44_TX_CTRL 0x0430UL /* EMAC TX Control */
+#define TX_CTRL_DUPLEX 0x00000001 /* Full Duplex */
+#define TX_CTRL_FMODE 0x00000002 /* Flow Mode */
+#define TX_CTRL_SBENAB 0x00000004 /* Single Backoff Enable */
+#define TX_CTRL_SMALL_SLOT 0x00000008 /* Small Slottime */
+#define B44_TX_HIWMARK 0x0434UL /* EMAC TX High Watermark */
+#define TX_HIWMARK_DEFLT 56 /* Default used in all drivers */
+#define B44_MIB_CTRL 0x0438UL /* EMAC MIB Control */
+#define MIB_CTRL_CLR_ON_READ 0x00000001 /* Autoclear on Read */
+#define B44_TX_GOOD_O 0x0500UL /* MIB TX Good Octets */
+#define B44_TX_GOOD_P 0x0504UL /* MIB TX Good Packets */
+#define B44_TX_O 0x0508UL /* MIB TX Octets */
+#define B44_TX_P 0x050CUL /* MIB TX Packets */
+#define B44_TX_BCAST 0x0510UL /* MIB TX Broadcast Packets */
+#define B44_TX_MCAST 0x0514UL /* MIB TX Multicast Packets */
+#define B44_TX_64 0x0518UL /* MIB TX <= 64 byte Packets */
+#define B44_TX_65_127 0x051CUL /* MIB TX 65 to 127 byte Pkts */
+#define B44_TX_128_255 0x0520UL /* MIB TX 128 to 255 byte Pkts */
+#define B44_TX_256_511 0x0524UL /* MIB TX 256 to 511 byte Pkts */
+#define B44_TX_512_1023 0x0528UL /* MIB TX 512 to 1023 byte Pkts */
+#define B44_TX_1024_MAX 0x052CUL /* MIB TX 1024 to max byte Pkts */
+#define B44_TX_JABBER 0x0530UL /* MIB TX Jabber Packets */
+#define B44_TX_OSIZE 0x0534UL /* MIB TX Oversize Packets */
+#define B44_TX_FRAG 0x0538UL /* MIB TX Fragment Packets */
+#define B44_TX_URUNS 0x053CUL /* MIB TX Underruns */
+#define B44_TX_TCOLS 0x0540UL /* MIB TX Total Collisions */
+#define B44_TX_SCOLS 0x0544UL /* MIB TX Single Collisions */
+#define B44_TX_MCOLS 0x0548UL /* MIB TX Multiple Collisions */
+#define B44_TX_ECOLS 0x054CUL /* MIB TX Excessive Collisions */
+#define B44_TX_LCOLS 0x0550UL /* MIB TX Late Collisions */
+#define B44_TX_DEFERED 0x0554UL /* MIB TX Defered Packets */
+#define B44_TX_CLOST 0x0558UL /* MIB TX Carrier Lost */
+#define B44_TX_PAUSE 0x055CUL /* MIB TX Pause Packets */
+#define B44_RX_GOOD_O 0x0580UL /* MIB RX Good Octets */
+#define B44_RX_GOOD_P 0x0584UL /* MIB RX Good Packets */
+#define B44_RX_O 0x0588UL /* MIB RX Octets */
+#define B44_RX_P 0x058CUL /* MIB RX Packets */
+#define B44_RX_BCAST 0x0590UL /* MIB RX Broadcast Packets */
+#define B44_RX_MCAST 0x0594UL /* MIB RX Multicast Packets */
+#define B44_RX_64 0x0598UL /* MIB RX <= 64 byte Packets */
+#define B44_RX_65_127 0x059CUL /* MIB RX 65 to 127 byte Pkts */
+#define B44_RX_128_255 0x05A0UL /* MIB RX 128 to 255 byte Pkts */
+#define B44_RX_256_511 0x05A4UL /* MIB RX 256 to 511 byte Pkts */
+#define B44_RX_512_1023 0x05A8UL /* MIB RX 512 to 1023 byte Pkts */
+#define B44_RX_1024_MAX 0x05ACUL /* MIB RX 1024 to max byte Pkts */
+#define B44_RX_JABBER 0x05B0UL /* MIB RX Jabber Packets */
+#define B44_RX_OSIZE 0x05B4UL /* MIB RX Oversize Packets */
+#define B44_RX_FRAG 0x05B8UL /* MIB RX Fragment Packets */
+#define B44_RX_MISS 0x05BCUL /* MIB RX Missed Packets */
+#define B44_RX_CRCA 0x05C0UL /* MIB RX CRC Align Errors */
+#define B44_RX_USIZE 0x05C4UL /* MIB RX Undersize Packets */
+#define B44_RX_CRC 0x05C8UL /* MIB RX CRC Errors */
+#define B44_RX_ALIGN 0x05CCUL /* MIB RX Align Errors */
+#define B44_RX_SYM 0x05D0UL /* MIB RX Symbol Errors */
+#define B44_RX_PAUSE 0x05D4UL /* MIB RX Pause Packets */
+#define B44_RX_NPAUSE 0x05D8UL /* MIB RX Non-Pause Packets */
+
+/* Sonics Silicon backplane register definitions */
+#define B44_SBIMSTATE 0x0F90UL /* SB Initiator Agent State */
+#define SBIMSTATE_PC 0x0000000f /* Pipe Count */
+#define SBIMSTATE_AP_MASK 0x00000030 /* Arbitration Priority */
+#define SBIMSTATE_AP_BOTH 0x00000000 /* both timeslices and token */
+#define SBIMSTATE_AP_TS 0x00000010 /* Use timeslices only */
+#define SBIMSTATE_AP_TK 0x00000020 /* Use token only */
+#define SBIMSTATE_AP_RSV 0x00000030 /* Reserved */
+#define SBIMSTATE_IBE 0x00020000 /* In Band Error */
+#define SBIMSTATE_TO 0x00040000 /* Timeout */
+#define SBIMSTATE_BAD ( SBIMSTATE_IBE | SBIMSTATE_TO )
+#define B44_SBINTVEC 0x0F94UL /* SB Interrupt Mask */
+#define SBINTVEC_PCI 0x00000001 /* Enable interrupts for PCI */
+#define SBINTVEC_ENET0 0x00000002 /* Enable ints for enet 0 */
+#define SBINTVEC_ILINE20 0x00000004 /* Enable ints for iline20 */
+#define SBINTVEC_CODEC 0x00000008 /* Enable ints for v90 codec */
+#define SBINTVEC_USB 0x00000010 /* Enable intts for usb */
+#define SBINTVEC_EXTIF 0x00000020 /* Enable ints for ext i/f */
+#define SBINTVEC_ENET1 0x00000040 /* Enable ints for enet 1 */
+#define B44_SBTMSLOW 0x0F98UL /* SB Target State Low */
+#define SBTMSLOW_RESET 0x00000001 /* Reset */
+#define SBTMSLOW_REJECT 0x00000002 /* Reject */
+#define SBTMSLOW_CLOCK 0x00010000 /* Clock Enable */
+#define SBTMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
+#define SBTMSLOW_PE 0x40000000 /* Power Management Enable */
+#define SBTMSLOW_BE 0x80000000 /* BIST Enable */
+#define B44_SBTMSHIGH 0x0F9CUL /* SB Target State High */
+#define SBTMSHIGH_SERR 0x00000001 /* S-error */
+#define SBTMSHIGH_INT 0x00000002 /* Interrupt */
+#define SBTMSHIGH_BUSY 0x00000004 /* Busy */
+#define SBTMSHIGH_GCR 0x20000000 /* Gated Clock Request */
+#define SBTMSHIGH_BISTF 0x40000000 /* BIST Failed */
+#define SBTMSHIGH_BISTD 0x80000000 /* BIST Done */
+#define B44_SBIDHIGH 0x0FFCUL /* SB Identification High */
+#define SBIDHIGH_RC_MASK 0x0000000f /* Revision Code */
+#define SBIDHIGH_CC_MASK 0x0000fff0 /* Core Code */
+#define SBIDHIGH_CC_SHIFT 4
+#define SBIDHIGH_VC_MASK 0xffff0000 /* Vendor Code */
+#define SBIDHIGH_VC_SHIFT 16
+
+/* SSB PCI config space registers. */
+#define SSB_PMCSR 0x44
+#define SSB_PE 0x100
+#define SSB_BAR0_WIN 0x80
+#define SSB_BAR1_WIN 0x84
+#define SSB_SPROM_CONTROL 0x88
+#define SSB_BAR1_CONTROL 0x8c
+
+/* SSB core and host control registers. */
+#define SSB_CONTROL 0x0000UL
+#define SSB_ARBCONTROL 0x0010UL
+#define SSB_ISTAT 0x0020UL
+#define SSB_IMASK 0x0024UL
+#define SSB_MBOX 0x0028UL
+#define SSB_BCAST_ADDR 0x0050UL
+#define SSB_BCAST_DATA 0x0054UL
+#define SSB_PCI_TRANS_0 0x0100UL
+#define SSB_PCI_TRANS_1 0x0104UL
+#define SSB_PCI_TRANS_2 0x0108UL
+#define SSB_SPROM 0x0800UL
+
+#define SSB_PCI_MEM 0x00000000
+#define SSB_PCI_IO 0x00000001
+#define SSB_PCI_CFG0 0x00000002
+#define SSB_PCI_CFG1 0x00000003
+#define SSB_PCI_PREF 0x00000004
+#define SSB_PCI_BURST 0x00000008
+#define SSB_PCI_MASK0 0xfc000000
+#define SSB_PCI_MASK1 0xfc000000
+#define SSB_PCI_MASK2 0xc0000000
+
+/* 4400 PHY registers */
+#define B44_MII_AUXCTRL 24 /* Auxiliary Control */
+#define MII_AUXCTRL_DUPLEX 0x0001 /* Full Duplex */
+#define MII_AUXCTRL_SPEED 0x0002 /* 1=100Mbps, 0=10Mbps */
+#define MII_AUXCTRL_FORCED 0x0004 /* Forced 10/100 */
+#define B44_MII_ALEDCTRL 26 /* Activity LED */
+#define MII_ALEDCTRL_ALLMSK 0x7fff
+#define B44_MII_TLEDCTRL 27 /* Traffic Meter LED */
+#define MII_TLEDCTRL_ENABLE 0x0040
+
+/* RX/TX descriptor */
+struct dma_desc {
+ u32 ctrl; /* length of data and flags */
+ u32 addr; /* address of data */
+};
+
+/* There are only 12 bits in the DMA engine for descriptor offsetting
+ * so the table must be aligned on a boundary of this.
+ */
+#define B44_DMA_ALIGNMENT 4096
+
+/* The DMA engine can only address the first gigabyte of address space
+ */
+#define B44_30BIT_DMA_MASK 0x3fffffff
+
+#define DESC_CTRL_LEN 0x00001fff
+#define DESC_CTRL_CMASK 0x0ff00000 /* Core specific bits */
+#define DESC_CTRL_EOT 0x10000000 /* End of Table */
+#define DESC_CTRL_IOC 0x20000000 /* Interrupt On Completion */
+#define DESC_CTRL_EOF 0x40000000 /* End of Frame */
+#define DESC_CTRL_SOF 0x80000000 /* Start of Frame */
+
+struct rx_header {
+ u16 len;
+ u16 flags;
+ u16 pad[12];
+};
+#define RX_HEADER_LEN 28
+
+#define RX_FLAG_OFIFO 0x00000001 /* FIFO Overflow */
+#define RX_FLAG_CRCERR 0x00000002 /* CRC Error */
+#define RX_FLAG_SERR 0x00000004 /* Receive Symbol Error */
+#define RX_FLAG_ODD 0x00000008 /* Frame has odd number of nibbles */
+#define RX_FLAG_LARGE 0x00000010 /* Frame is > RX MAX Length */
+#define RX_FLAG_MCAST 0x00000020 /* Dest is Multicast Address */
+#define RX_FLAG_BCAST 0x00000040 /* Dest is Broadcast Address */
+#define RX_FLAG_MISS 0x00000080 /* Received due to promisc mode */
+#define RX_FLAG_LAST 0x00000800 /* Last buffer in frame */
+#define RX_FLAG_ERRORS (RX_FLAG_ODD | RX_FLAG_SERR |\
+ RX_FLAG_CRCERR | RX_FLAG_OFIFO)
+
+/* Client Mode PCI memory access space (1 GB) */
+#define SB_PCI_DMA 0x40000000
+
+ /* Address of PCI core on BCM4400 cards */
+#define BCM4400_PCI_CORE_ADDR 0x18002000
+
+/* Hardware minimum and maximum for a single frame's data payload */
+#define B44_MIN_MTU 60
+#define B44_MAX_MTU 1500
+
+#define B44_RING_SIZE 8
+#define B44_RING_LAST ( B44_RING_SIZE - 1 )
+
+#define B44_RX_RING_LEN_BYTES ( sizeof bp->rx[0] * B44_RING_SIZE )
+#define B44_TX_RING_LEN_BYTES ( sizeof bp->tx[0] * B44_RING_SIZE )
+
+#define RX_PKT_OFFSET 30
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
+
+#define B44_FULL_RESET 1
+#define B44_FULL_RESET_SKIP_PHY 2
+#define B44_PARTIAL_RESET 3
+#define B44_CHIP_RESET_FULL 4
+#define B44_CHIP_RESET_PARTIAL 5
+
+#define SSB_CORE_DOWN ( SBTMSLOW_RESET | SBTMSLOW_REJECT )
+
+#define B44_REGS_SIZE 8192
+
+/** Driver private state */
+struct b44_private {
+ struct net_device *netdev;
+ struct pci_device *pci;
+ u8 *regs; /* memory-mapped registers */
+ u8 phy_addr;
+
+ struct dma_desc *tx;
+ struct io_buffer *tx_iobuf[B44_RING_SIZE];
+ u32 tx_cur; /* next available descriptor */
+ u32 tx_dirty; /* oldest pending descriptor */
+
+ struct dma_desc *rx;
+ struct io_buffer *rx_iobuf[B44_RING_SIZE];
+ u32 rx_cur; /* next descriptor to read */
+};
+
+
+static void ssb_core_reset ( struct b44_private *bp );
+static void ssb_core_disable ( struct b44_private *bp );
+static u32 ssb_pci_setup ( struct b44_private *bp, u32 cores );
+
+static void b44_chip_reset ( struct b44_private *bp, int reset_kind );
+static void b44_init_hw ( struct b44_private *bp, int reset_kind );
+static void b44_cam_write ( struct b44_private *bp, u8 *data, int index );
+static void b44_set_mac_addr ( struct b44_private *bp );
+static void b44_set_rx_mode ( struct net_device *netdev );
+static void b44_halt(struct b44_private *);
+
+static int b44_phy_reset ( struct b44_private *bp );
+static int b44_phy_write ( struct b44_private *bp, int reg, u32 val );
+static int b44_phy_read ( struct b44_private *bp, int reg, u32 *val );
+
+static int b44_init_tx_ring ( struct b44_private *bp );
+static void b44_free_tx_ring ( struct b44_private *bp );
+static int b44_init_rx_ring ( struct b44_private *bp );
+static void b44_free_rx_ring ( struct b44_private *bp );
+static void b44_rx_refill ( struct b44_private *bp, u32 pending );
+static void b44_populate_rx_descriptor (struct b44_private *bp, u32 index);
+
+static int b44_probe ( struct pci_device *pci,
+ const struct pci_device_id *id );
+static void b44_remove ( struct pci_device *pci );
+
+static int b44_open ( struct net_device *netdev );
+static void b44_close ( struct net_device *netdev );
+static void b44_irq ( struct net_device *netdev, int enable );
+static void b44_poll ( struct net_device *netdev );
+static void b44_process_rx_packets ( struct b44_private *bp );
+static int b44_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+
+static struct net_device_operations b44_operations;
+
+#endif /* _B44_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.c
new file mode 100644
index 0000000..c385dd8
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.c
@@ -0,0 +1,2697 @@
+/* bnx2.c: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ *
+ * Etherboot port by Ryan Jackson (rjackson@lnxi.com), based on driver
+ * version 1.4.40 from linux 2.6.17
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#include "etherboot.h"
+#include "nic.h"
+#include <errno.h>
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include "string.h"
+#include <mii.h>
+#include "bnx2.h"
+#include "bnx2_fw.h"
+
+#if 0
+/* Dummy defines for error handling */
+#define EBUSY 1
+#define ENODEV 2
+#define EINVAL 3
+#define ENOMEM 4
+#define EIO 5
+#endif
+
+/* The bnx2 seems to be picky about the alignment of the receive buffers
+ * and possibly the status block.
+ */
+static struct bss {
+ struct tx_bd tx_desc_ring[TX_DESC_CNT];
+ struct rx_bd rx_desc_ring[RX_DESC_CNT];
+ unsigned char rx_buf[RX_BUF_CNT][RX_BUF_SIZE];
+ struct status_block status_blk;
+ struct statistics_block stats_blk;
+} bnx2_bss;
+
+static struct bnx2 bnx2;
+
+static struct flash_spec flash_table[] =
+{
+ /* Slow EEPROM */
+ {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - slow"},
+ /* Expansion entry 0001 */
+ {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 0001"},
+ /* Saifun SA25F010 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
+ "Non-buffered flash (128kB)"},
+ /* Saifun SA25F020 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
+ "Non-buffered flash (256kB)"},
+ /* Expansion entry 0100 */
+ {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 0100"},
+ /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
+ {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
+ 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+ ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
+ "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
+ /* Entry 0110: ST M45PE20 (non-buffered flash)*/
+ {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
+ 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+ ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
+ "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
+ /* Saifun SA25F005 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
+ "Non-buffered flash (64kB)"},
+ /* Fast EEPROM */
+ {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - fast"},
+ /* Expansion entry 1001 */
+ {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1001"},
+ /* Expansion entry 1010 */
+ {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1010"},
+ /* ATMEL AT45DB011B (buffered flash) */
+ {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
+ "Buffered flash (128kB)"},
+ /* Expansion entry 1100 */
+ {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1100"},
+ /* Expansion entry 1101 */
+ {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1101"},
+ /* Ateml Expansion entry 1110 */
+ {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1110 (Atmel)"},
+ /* ATMEL AT45DB021B (buffered flash) */
+ {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
+ "Buffered flash (256kB)"},
+};
+
+static u32
+bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
+{
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW));
+}
+
+static void
+bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
+{
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+}
+
+static void
+bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
+{
+ offset += cid_addr;
+ REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
+ REG_WR(bp, BNX2_CTX_DATA, val);
+}
+
+static int
+bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
+{
+ u32 val1;
+ int i, ret;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ val1 = (bp->phy_addr << 21) | (reg << 16) |
+ BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
+ BNX2_EMAC_MDIO_COMM_START_BUSY;
+ REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ val1 &= BNX2_EMAC_MDIO_COMM_DATA;
+
+ break;
+ }
+ }
+
+ if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) {
+ *val = 0x0;
+ ret = -EBUSY;
+ }
+ else {
+ *val = val1;
+ ret = 0;
+ }
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ return ret;
+}
+
+static int
+bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
+{
+ u32 val1;
+ int i, ret;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ val1 = (bp->phy_addr << 21) | (reg << 16) | val |
+ BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
+ BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
+ REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+
+ if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)
+ ret = -EBUSY;
+ else
+ ret = 0;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ return ret;
+}
+
+static void
+bnx2_disable_int(struct bnx2 *bp)
+{
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+ REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+
+}
+
+static int
+bnx2_alloc_mem(struct bnx2 *bp)
+{
+ bp->tx_desc_ring = bnx2_bss.tx_desc_ring;
+ bp->tx_desc_mapping = virt_to_bus(bp->tx_desc_ring);
+
+ bp->rx_desc_ring = bnx2_bss.rx_desc_ring;
+ memset(bp->rx_desc_ring, 0, sizeof(struct rx_bd) * RX_DESC_CNT);
+ bp->rx_desc_mapping = virt_to_bus(bp->rx_desc_ring);
+
+ memset(&bnx2_bss.status_blk, 0, sizeof(struct status_block));
+ bp->status_blk = &bnx2_bss.status_blk;
+ bp->status_blk_mapping = virt_to_bus(&bnx2_bss.status_blk);
+
+ bp->stats_blk = &bnx2_bss.stats_blk;
+ memset(&bnx2_bss.stats_blk, 0, sizeof(struct statistics_block));
+ bp->stats_blk_mapping = virt_to_bus(&bnx2_bss.stats_blk);
+
+ return 0;
+}
+
+static void
+bnx2_report_fw_link(struct bnx2 *bp)
+{
+ u32 fw_link_status = 0;
+
+ if (bp->link_up) {
+ u32 bmsr;
+
+ switch (bp->line_speed) {
+ case SPEED_10:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_10HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_10FULL;
+ break;
+ case SPEED_100:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_100HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_100FULL;
+ break;
+ case SPEED_1000:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_1000HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_1000FULL;
+ break;
+ case SPEED_2500:
+ if (bp->duplex == DUPLEX_HALF)
+ fw_link_status = BNX2_LINK_STATUS_2500HALF;
+ else
+ fw_link_status = BNX2_LINK_STATUS_2500FULL;
+ break;
+ }
+
+ fw_link_status |= BNX2_LINK_STATUS_LINK_UP;
+
+ if (bp->autoneg) {
+ fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if (!(bmsr & BMSR_ANEGCOMPLETE) ||
+ bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)
+ fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET;
+ else
+ fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE;
+ }
+ }
+ else
+ fw_link_status = BNX2_LINK_STATUS_LINK_DOWN;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
+}
+
+static void
+bnx2_report_link(struct bnx2 *bp)
+{
+ if (bp->link_up) {
+ printf("NIC Link is Up, ");
+
+ printf("%d Mbps ", bp->line_speed);
+
+ if (bp->duplex == DUPLEX_FULL)
+ printf("full duplex");
+ else
+ printf("half duplex");
+
+ if (bp->flow_ctrl) {
+ if (bp->flow_ctrl & FLOW_CTRL_RX) {
+ printf(", receive ");
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ printf("& transmit ");
+ }
+ else {
+ printf(", transmit ");
+ }
+ printf("flow control ON");
+ }
+ printf("\n");
+ }
+ else {
+ printf("NIC Link is Down\n");
+ }
+
+ bnx2_report_fw_link(bp);
+}
+
+static void
+bnx2_resolve_flow_ctrl(struct bnx2 *bp)
+{
+ u32 local_adv, remote_adv;
+
+ bp->flow_ctrl = 0;
+ if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
+ (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
+
+ if (bp->duplex == DUPLEX_FULL) {
+ bp->flow_ctrl = bp->req_flow_ctrl;
+ }
+ return;
+ }
+
+ if (bp->duplex != DUPLEX_FULL) {
+ return;
+ }
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5708)) {
+ u32 val;
+
+ bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
+ if (val & BCM5708S_1000X_STAT1_TX_PAUSE)
+ bp->flow_ctrl |= FLOW_CTRL_TX;
+ if (val & BCM5708S_1000X_STAT1_RX_PAUSE)
+ bp->flow_ctrl |= FLOW_CTRL_RX;
+ return;
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ u32 new_local_adv = 0;
+ u32 new_remote_adv = 0;
+
+ if (local_adv & ADVERTISE_1000XPAUSE)
+ new_local_adv |= ADVERTISE_PAUSE_CAP;
+ if (local_adv & ADVERTISE_1000XPSE_ASYM)
+ new_local_adv |= ADVERTISE_PAUSE_ASYM;
+ if (remote_adv & ADVERTISE_1000XPAUSE)
+ new_remote_adv |= ADVERTISE_PAUSE_CAP;
+ if (remote_adv & ADVERTISE_1000XPSE_ASYM)
+ new_remote_adv |= ADVERTISE_PAUSE_ASYM;
+
+ local_adv = new_local_adv;
+ remote_adv = new_remote_adv;
+ }
+
+ /* See Table 28B-3 of 802.3ab-1999 spec. */
+ if (local_adv & ADVERTISE_PAUSE_CAP) {
+ if(local_adv & ADVERTISE_PAUSE_ASYM) {
+ if (remote_adv & ADVERTISE_PAUSE_CAP) {
+ bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ else if (remote_adv & ADVERTISE_PAUSE_ASYM) {
+ bp->flow_ctrl = FLOW_CTRL_RX;
+ }
+ }
+ else {
+ if (remote_adv & ADVERTISE_PAUSE_CAP) {
+ bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ }
+ }
+ else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+ if ((remote_adv & ADVERTISE_PAUSE_CAP) &&
+ (remote_adv & ADVERTISE_PAUSE_ASYM)) {
+
+ bp->flow_ctrl = FLOW_CTRL_TX;
+ }
+ }
+}
+
+static int
+bnx2_5708s_linkup(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->link_up = 1;
+ bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
+ switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) {
+ case BCM5708S_1000X_STAT1_SPEED_10:
+ bp->line_speed = SPEED_10;
+ break;
+ case BCM5708S_1000X_STAT1_SPEED_100:
+ bp->line_speed = SPEED_100;
+ break;
+ case BCM5708S_1000X_STAT1_SPEED_1G:
+ bp->line_speed = SPEED_1000;
+ break;
+ case BCM5708S_1000X_STAT1_SPEED_2G5:
+ bp->line_speed = SPEED_2500;
+ break;
+ }
+ if (val & BCM5708S_1000X_STAT1_FD)
+ bp->duplex = DUPLEX_FULL;
+ else
+ bp->duplex = DUPLEX_HALF;
+
+ return 0;
+}
+
+static int
+bnx2_5706s_linkup(struct bnx2 *bp)
+{
+ u32 bmcr, local_adv, remote_adv, common;
+
+ bp->link_up = 1;
+ bp->line_speed = SPEED_1000;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_FULLDPLX) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+
+ if (!(bmcr & BMCR_ANENABLE)) {
+ return 0;
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ common = local_adv & remote_adv;
+ if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
+
+ if (common & ADVERTISE_1000XFULL) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnx2_copper_linkup(struct bnx2 *bp)
+{
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_ANENABLE) {
+ u32 local_adv, remote_adv, common;
+
+ bnx2_read_phy(bp, MII_CTRL1000, &local_adv);
+ bnx2_read_phy(bp, MII_STAT1000, &remote_adv);
+
+ common = local_adv & (remote_adv >> 2);
+ if (common & ADVERTISE_1000FULL) {
+ bp->line_speed = SPEED_1000;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_1000HALF) {
+ bp->line_speed = SPEED_1000;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else {
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ common = local_adv & remote_adv;
+ if (common & ADVERTISE_100FULL) {
+ bp->line_speed = SPEED_100;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_100HALF) {
+ bp->line_speed = SPEED_100;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else if (common & ADVERTISE_10FULL) {
+ bp->line_speed = SPEED_10;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_10HALF) {
+ bp->line_speed = SPEED_10;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else {
+ bp->line_speed = 0;
+ bp->link_up = 0;
+ }
+ }
+ }
+ else {
+ if (bmcr & BMCR_SPEED100) {
+ bp->line_speed = SPEED_100;
+ }
+ else {
+ bp->line_speed = SPEED_10;
+ }
+ if (bmcr & BMCR_FULLDPLX) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnx2_set_mac_link(struct bnx2 *bp)
+{
+ u32 val;
+
+ REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
+ if (bp->link_up && (bp->line_speed == SPEED_1000) &&
+ (bp->duplex == DUPLEX_HALF)) {
+ REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
+ }
+
+ /* Configure the EMAC mode register. */
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+
+ val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
+ BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
+ BNX2_EMAC_MODE_25G);
+
+ if (bp->link_up) {
+ switch (bp->line_speed) {
+ case SPEED_10:
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ val |= BNX2_EMAC_MODE_PORT_MII_10;
+ break;
+ }
+ /* fall through */
+ case SPEED_100:
+ val |= BNX2_EMAC_MODE_PORT_MII;
+ break;
+ case SPEED_2500:
+ val |= BNX2_EMAC_MODE_25G;
+ /* fall through */
+ case SPEED_1000:
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ break;
+ }
+ }
+ else {
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ }
+
+ /* Set the MAC to operate in the appropriate duplex mode. */
+ if (bp->duplex == DUPLEX_HALF)
+ val |= BNX2_EMAC_MODE_HALF_DUPLEX;
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ /* Enable/disable rx PAUSE. */
+ bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
+
+ if (bp->flow_ctrl & FLOW_CTRL_RX)
+ bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
+ REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
+
+ /* Enable/disable tx PAUSE. */
+ val = REG_RD(bp, BNX2_EMAC_TX_MODE);
+ val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
+
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ val |= BNX2_EMAC_TX_MODE_FLOW_EN;
+ REG_WR(bp, BNX2_EMAC_TX_MODE, val);
+
+ /* Acknowledge the interrupt. */
+ REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+
+ return 0;
+}
+
+static int
+bnx2_set_link(struct bnx2 *bp)
+{
+ u32 bmsr;
+ u8 link_up;
+
+ if (bp->loopback == MAC_LOOPBACK) {
+ bp->link_up = 1;
+ return 0;
+ }
+
+ link_up = bp->link_up;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ u32 val;
+
+ val = REG_RD(bp, BNX2_EMAC_STATUS);
+ if (val & BNX2_EMAC_STATUS_LINK)
+ bmsr |= BMSR_LSTATUS;
+ else
+ bmsr &= ~BMSR_LSTATUS;
+ }
+
+ if (bmsr & BMSR_LSTATUS) {
+ bp->link_up = 1;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ bnx2_5706s_linkup(bp);
+ else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ bnx2_5708s_linkup(bp);
+ }
+ else {
+ bnx2_copper_linkup(bp);
+ }
+ bnx2_resolve_flow_ctrl(bp);
+ }
+ else {
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (bp->autoneg & AUTONEG_SPEED)) {
+
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (!(bmcr & BMCR_ANENABLE)) {
+ bnx2_write_phy(bp, MII_BMCR, bmcr |
+ BMCR_ANENABLE);
+ }
+ }
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+ bp->link_up = 0;
+ }
+
+ if (bp->link_up != link_up) {
+ bnx2_report_link(bp);
+ }
+
+ bnx2_set_mac_link(bp);
+
+ return 0;
+}
+
+static int
+bnx2_reset_phy(struct bnx2 *bp)
+{
+ int i;
+ u32 reg;
+
+ bnx2_write_phy(bp, MII_BMCR, BMCR_RESET);
+
+#define PHY_RESET_MAX_WAIT 100
+ for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
+ udelay(10);
+
+ bnx2_read_phy(bp, MII_BMCR, &reg);
+ if (!(reg & BMCR_RESET)) {
+ udelay(20);
+ break;
+ }
+ }
+ if (i == PHY_RESET_MAX_WAIT) {
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static u32
+bnx2_phy_get_pause_adv(struct bnx2 *bp)
+{
+ u32 adv = 0;
+
+ if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) ==
+ (FLOW_CTRL_RX | FLOW_CTRL_TX)) {
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPAUSE;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_CAP;
+ }
+ }
+ else if (bp->req_flow_ctrl & FLOW_CTRL_TX) {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPSE_ASYM;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_ASYM;
+ }
+ }
+ else if (bp->req_flow_ctrl & FLOW_CTRL_RX) {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ }
+ }
+ return adv;
+}
+
+static int
+bnx2_setup_serdes_phy(struct bnx2 *bp)
+{
+ u32 adv, bmcr, up1;
+ u32 new_adv = 0;
+
+ if (!(bp->autoneg & AUTONEG_SPEED)) {
+ u32 new_bmcr;
+ int force_link_down = 0;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ bnx2_read_phy(bp, BCM5708S_UP1, &up1);
+ if (up1 & BCM5708S_UP1_2G5) {
+ up1 &= ~BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, up1);
+ force_link_down = 1;
+ }
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ new_bmcr = bmcr & ~BMCR_ANENABLE;
+ new_bmcr |= BMCR_SPEED1000;
+ if (bp->req_duplex == DUPLEX_FULL) {
+ adv |= ADVERTISE_1000XFULL;
+ new_bmcr |= BMCR_FULLDPLX;
+ }
+ else {
+ adv |= ADVERTISE_1000XHALF;
+ new_bmcr &= ~BMCR_FULLDPLX;
+ }
+ if ((new_bmcr != bmcr) || (force_link_down)) {
+ /* Force a link down visible on the other side */
+ if (bp->link_up) {
+ bnx2_write_phy(bp, MII_ADVERTISE, adv &
+ ~(ADVERTISE_1000XFULL |
+ ADVERTISE_1000XHALF));
+ bnx2_write_phy(bp, MII_BMCR, bmcr |
+ BMCR_ANRESTART | BMCR_ANENABLE);
+
+ bp->link_up = 0;
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+ }
+ bnx2_write_phy(bp, MII_ADVERTISE, adv);
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+ }
+ return 0;
+ }
+
+ if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
+ bnx2_read_phy(bp, BCM5708S_UP1, &up1);
+ up1 |= BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, up1);
+ }
+
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ new_adv |= ADVERTISE_1000XFULL;
+
+ new_adv |= bnx2_phy_get_pause_adv(bp);
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ bp->serdes_an_pending = 0;
+ if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
+ /* Force a link down visible on the other side */
+ if (bp->link_up) {
+ int i;
+
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ for (i = 0; i < 110; i++) {
+ udelay(100);
+ }
+ }
+
+ bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
+ bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
+ BMCR_ANENABLE);
+#if 0
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ /* Speed up link-up time when the link partner
+ * does not autonegotiate which is very common
+ * in blade servers. Some blade servers use
+ * IPMI for kerboard input and it's important
+ * to minimize link disruptions. Autoneg. involves
+ * exchanging base pages plus 3 next pages and
+ * normally completes in about 120 msec.
+ */
+ bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->serdes_an_pending = 1;
+ mod_timer(&bp->timer, jiffies + bp->current_interval);
+ }
+#endif
+ }
+
+ return 0;
+}
+
+#define ETHTOOL_ALL_FIBRE_SPEED \
+ (ADVERTISED_1000baseT_Full)
+
+#define ETHTOOL_ALL_COPPER_SPEED \
+ (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+ ADVERTISED_1000baseT_Full)
+
+#define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA)
+
+#define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
+
+static int
+bnx2_setup_copper_phy(struct bnx2 *bp)
+{
+ u32 bmcr;
+ u32 new_bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ if (bp->autoneg & AUTONEG_SPEED) {
+ u32 adv_reg, adv1000_reg;
+ u32 new_adv_reg = 0;
+ u32 new_adv1000_reg = 0;
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg);
+ adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+
+ bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
+ adv1000_reg &= PHY_ALL_1000_SPEED;
+
+ if (bp->advertising & ADVERTISED_10baseT_Half)
+ new_adv_reg |= ADVERTISE_10HALF;
+ if (bp->advertising & ADVERTISED_10baseT_Full)
+ new_adv_reg |= ADVERTISE_10FULL;
+ if (bp->advertising & ADVERTISED_100baseT_Half)
+ new_adv_reg |= ADVERTISE_100HALF;
+ if (bp->advertising & ADVERTISED_100baseT_Full)
+ new_adv_reg |= ADVERTISE_100FULL;
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ new_adv1000_reg |= ADVERTISE_1000FULL;
+
+ new_adv_reg |= ADVERTISE_CSMA;
+
+ new_adv_reg |= bnx2_phy_get_pause_adv(bp);
+
+ if ((adv1000_reg != new_adv1000_reg) ||
+ (adv_reg != new_adv_reg) ||
+ ((bmcr & BMCR_ANENABLE) == 0)) {
+
+ bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg);
+ bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
+ bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART |
+ BMCR_ANENABLE);
+ }
+ else if (bp->link_up) {
+ /* Flow ctrl may have changed from auto to forced */
+ /* or vice-versa. */
+
+ bnx2_resolve_flow_ctrl(bp);
+ bnx2_set_mac_link(bp);
+ }
+ return 0;
+ }
+
+ new_bmcr = 0;
+ if (bp->req_line_speed == SPEED_100) {
+ new_bmcr |= BMCR_SPEED100;
+ }
+ if (bp->req_duplex == DUPLEX_FULL) {
+ new_bmcr |= BMCR_FULLDPLX;
+ }
+ if (new_bmcr != bmcr) {
+ u32 bmsr;
+ int i = 0;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if (bmsr & BMSR_LSTATUS) {
+ /* Force link down */
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ do {
+ udelay(100);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ i++;
+ } while ((bmsr & BMSR_LSTATUS) && (i < 620));
+ }
+
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+
+ /* Normally, the new speed is setup after the link has
+ * gone down and up again. In some cases, link will not go
+ * down so we need to set up the new speed here.
+ */
+ if (bmsr & BMSR_LSTATUS) {
+ bp->line_speed = bp->req_line_speed;
+ bp->duplex = bp->req_duplex;
+ bnx2_resolve_flow_ctrl(bp);
+ bnx2_set_mac_link(bp);
+ }
+ }
+ return 0;
+}
+
+static int
+bnx2_setup_phy(struct bnx2 *bp)
+{
+ if (bp->loopback == MAC_LOOPBACK)
+ return 0;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ return (bnx2_setup_serdes_phy(bp));
+ }
+ else {
+ return (bnx2_setup_copper_phy(bp));
+ }
+}
+
+static int
+bnx2_init_5708s_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
+ bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
+
+ bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val);
+ val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN;
+ bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val);
+
+ bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val);
+ val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN;
+ bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val);
+
+ if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
+ bnx2_read_phy(bp, BCM5708S_UP1, &val);
+ val |= BCM5708S_UP1_2G5;
+ bnx2_write_phy(bp, BCM5708S_UP1, val);
+ }
+
+ if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+ (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
+ /* increase tx signal amplitude */
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
+ BCM5708S_BLK_ADDR_TX_MISC);
+ bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val);
+ val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM;
+ bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val);
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
+ }
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG) &
+ BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK;
+
+ if (val) {
+ u32 is_backplane;
+
+ is_backplane = REG_RD_IND(bp, bp->shmem_base +
+ BNX2_SHARED_HW_CFG_CONFIG);
+ if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) {
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
+ BCM5708S_BLK_ADDR_TX_MISC);
+ bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val);
+ bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
+ BCM5708S_BLK_ADDR_DIG);
+ }
+ }
+ return 0;
+}
+
+static int
+bnx2_init_5706s_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ REG_WR(bp, BNX2_MISC_UNUSED0, 0x300);
+ }
+
+
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val & ~0x4007);
+
+ bnx2_write_phy(bp, 0x1c, 0x6c00);
+ bnx2_read_phy(bp, 0x1c, &val);
+ bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00);
+
+ return 0;
+}
+
+static int
+bnx2_init_copper_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->phy_flags |= PHY_CRC_FIX_FLAG;
+
+ if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
+ bnx2_write_phy(bp, 0x18, 0x0c00);
+ bnx2_write_phy(bp, 0x17, 0x000a);
+ bnx2_write_phy(bp, 0x15, 0x310b);
+ bnx2_write_phy(bp, 0x17, 0x201f);
+ bnx2_write_phy(bp, 0x15, 0x9506);
+ bnx2_write_phy(bp, 0x17, 0x401f);
+ bnx2_write_phy(bp, 0x15, 0x14e2);
+ bnx2_write_phy(bp, 0x18, 0x0400);
+ }
+
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val & ~0x4007);
+
+ bnx2_read_phy(bp, 0x10, &val);
+ bnx2_write_phy(bp, 0x10, val & ~0x1);
+
+ /* ethernet@wirespeed */
+ bnx2_write_phy(bp, 0x18, 0x7007);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4));
+ return 0;
+}
+
+static int
+bnx2_init_phy(struct bnx2 *bp)
+{
+ u32 val;
+ int rc = 0;
+
+ bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG;
+ bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG;
+
+ REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+
+ bnx2_reset_phy(bp);
+
+ bnx2_read_phy(bp, MII_PHYSID1, &val);
+ bp->phy_id = val << 16;
+ bnx2_read_phy(bp, MII_PHYSID2, &val);
+ bp->phy_id |= val & 0xffff;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ rc = bnx2_init_5706s_phy(bp);
+ else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ rc = bnx2_init_5708s_phy(bp);
+ }
+ else {
+ rc = bnx2_init_copper_phy(bp);
+ }
+
+ bnx2_setup_phy(bp);
+
+ return rc;
+}
+
+static int
+bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
+{
+ int i;
+ u32 val;
+
+ bp->fw_wr_seq++;
+ msg_data |= bp->fw_wr_seq;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
+
+ /* wait for an acknowledgement. */
+ for (i = 0; i < (FW_ACK_TIME_OUT_MS / 50); i++) {
+ mdelay(50);
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
+
+ if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
+ break;
+ }
+ if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
+ return 0;
+
+ /* If we timed out, inform the firmware that this is the case. */
+ if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
+ if (!silent)
+ printf("fw sync timeout, reset code = %x\n", (unsigned int) msg_data);
+
+ msg_data &= ~BNX2_DRV_MSG_CODE;
+ msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
+
+ return -EBUSY;
+ }
+
+ if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
+ return -EIO;
+
+ return 0;
+}
+
+static void
+bnx2_init_context(struct bnx2 *bp)
+{
+ u32 vcid;
+
+ vcid = 96;
+ while (vcid) {
+ u32 vcid_addr, pcid_addr, offset;
+
+ vcid--;
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ u32 new_vcid;
+
+ vcid_addr = GET_PCID_ADDR(vcid);
+ if (vcid & 0x8) {
+ new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7);
+ }
+ else {
+ new_vcid = vcid;
+ }
+ pcid_addr = GET_PCID_ADDR(new_vcid);
+ }
+ else {
+ vcid_addr = GET_CID_ADDR(vcid);
+ pcid_addr = vcid_addr;
+ }
+
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+
+ /* Zero out the context. */
+ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
+ CTX_WR(bp, 0x00, offset, 0);
+ }
+
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ }
+}
+
+static int
+bnx2_alloc_bad_rbuf(struct bnx2 *bp)
+{
+ u16 good_mbuf[512];
+ u32 good_mbuf_cnt;
+ u32 val;
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
+
+ good_mbuf_cnt = 0;
+
+ /* Allocate a bunch of mbufs and save the good ones in an array. */
+ val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+ while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
+ REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ);
+
+ val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC);
+
+ val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
+
+ /* The addresses with Bit 9 set are bad memory blocks. */
+ if (!(val & (1 << 9))) {
+ good_mbuf[good_mbuf_cnt] = (u16) val;
+ good_mbuf_cnt++;
+ }
+
+ val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+ }
+
+ /* Free the good ones back to the mbuf pool thus discarding
+ * all the bad ones. */
+ while (good_mbuf_cnt) {
+ good_mbuf_cnt--;
+
+ val = good_mbuf[good_mbuf_cnt];
+ val = (val << 9) | val | 1;
+
+ REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val);
+ }
+ return 0;
+}
+
+static void
+bnx2_set_mac_addr(struct bnx2 *bp)
+{
+ u32 val;
+ u8 *mac_addr = bp->nic->node_addr;
+
+ val = (mac_addr[0] << 8) | mac_addr[1];
+
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val);
+
+ val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
+ (mac_addr[4] << 8) | mac_addr[5];
+
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val);
+}
+
+static void
+bnx2_set_rx_mode(struct nic *nic __unused)
+{
+ struct bnx2 *bp = &bnx2;
+ u32 rx_mode, sort_mode;
+ int i;
+
+ rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
+ BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
+ sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
+
+ if (!(bp->flags & ASF_ENABLE_FLAG)) {
+ rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
+ }
+
+ /* Accept all multicasts */
+ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
+ REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ 0xffffffff);
+ }
+ sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
+
+ if (rx_mode != bp->rx_mode) {
+ bp->rx_mode = rx_mode;
+ REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
+ }
+
+ REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
+}
+
+static void
+load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, u32 rv2p_proc)
+{
+ unsigned int i;
+ u32 val;
+
+
+ for (i = 0; i < rv2p_code_len; i += 8) {
+ REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
+ rv2p_code++;
+ REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
+ rv2p_code++;
+
+ if (rv2p_proc == RV2P_PROC1) {
+ val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
+ REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val);
+ }
+ else {
+ val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
+ REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val);
+ }
+ }
+
+ /* Reset the processor, un-stall is done later. */
+ if (rv2p_proc == RV2P_PROC1) {
+ REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
+ }
+ else {
+ REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
+ }
+}
+
+static void
+load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
+{
+ u32 offset;
+ u32 val;
+
+ /* Halt the CPU. */
+ val = REG_RD_IND(bp, cpu_reg->mode);
+ val |= cpu_reg->mode_value_halt;
+ REG_WR_IND(bp, cpu_reg->mode, val);
+ REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+
+ /* Load the Text area. */
+ offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
+ if (fw->text) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->text[j]);
+ }
+ }
+
+ /* Load the Data area. */
+ offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
+ if (fw->data) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->data[j]);
+ }
+ }
+
+ /* Load the SBSS area. */
+ offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
+ if (fw->sbss) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->sbss[j]);
+ }
+ }
+
+ /* Load the BSS area. */
+ offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
+ if (fw->bss) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->bss[j]);
+ }
+ }
+
+ /* Load the Read-Only area. */
+ offset = cpu_reg->spad_base +
+ (fw->rodata_addr - cpu_reg->mips_view_base);
+ if (fw->rodata) {
+ unsigned int j;
+
+ for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->rodata[j]);
+ }
+ }
+
+ /* Clear the pre-fetch instruction. */
+ REG_WR_IND(bp, cpu_reg->inst, 0);
+ REG_WR_IND(bp, cpu_reg->pc, fw->start_addr);
+
+ /* Start the CPU. */
+ val = REG_RD_IND(bp, cpu_reg->mode);
+ val &= ~cpu_reg->mode_value_halt;
+ REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+ REG_WR_IND(bp, cpu_reg->mode, val);
+}
+
+static void
+bnx2_init_cpus(struct bnx2 *bp)
+{
+ struct cpu_reg cpu_reg;
+ struct fw_info fw;
+
+ /* Unfortunately, it looks like we need to load the firmware
+ * before the card will work properly. That means this driver
+ * will be huge by Etherboot standards (approx. 50K compressed).
+ */
+
+ /* Initialize the RV2P processor. */
+ load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
+ load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
+
+ /* Initialize the RX Processor. */
+ cpu_reg.mode = BNX2_RXP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_RXP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_RXP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_RXP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_RXP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_RXP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_RXP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_RXP_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_RXP_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_RXP_b06FwReleaseFix;
+ fw.start_addr = bnx2_RXP_b06FwStartAddr;
+
+ fw.text_addr = bnx2_RXP_b06FwTextAddr;
+ fw.text_len = bnx2_RXP_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_RXP_b06FwText;
+
+ fw.data_addr = bnx2_RXP_b06FwDataAddr;
+ fw.data_len = bnx2_RXP_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_RXP_b06FwData;
+
+ fw.sbss_addr = bnx2_RXP_b06FwSbssAddr;
+ fw.sbss_len = bnx2_RXP_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_RXP_b06FwSbss;
+
+ fw.bss_addr = bnx2_RXP_b06FwBssAddr;
+ fw.bss_len = bnx2_RXP_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_RXP_b06FwBss;
+
+ fw.rodata_addr = bnx2_RXP_b06FwRodataAddr;
+ fw.rodata_len = bnx2_RXP_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_RXP_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the TX Processor. */
+ cpu_reg.mode = BNX2_TXP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_TXP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_TXP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_TXP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_TXP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_TXP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_TXP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_TXP_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_TXP_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_TXP_b06FwReleaseFix;
+ fw.start_addr = bnx2_TXP_b06FwStartAddr;
+
+ fw.text_addr = bnx2_TXP_b06FwTextAddr;
+ fw.text_len = bnx2_TXP_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_TXP_b06FwText;
+
+ fw.data_addr = bnx2_TXP_b06FwDataAddr;
+ fw.data_len = bnx2_TXP_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_TXP_b06FwData;
+
+ fw.sbss_addr = bnx2_TXP_b06FwSbssAddr;
+ fw.sbss_len = bnx2_TXP_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_TXP_b06FwSbss;
+
+ fw.bss_addr = bnx2_TXP_b06FwBssAddr;
+ fw.bss_len = bnx2_TXP_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_TXP_b06FwBss;
+
+ fw.rodata_addr = bnx2_TXP_b06FwRodataAddr;
+ fw.rodata_len = bnx2_TXP_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_TXP_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the TX Patch-up Processor. */
+ cpu_reg.mode = BNX2_TPAT_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_TPAT_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_TPAT_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_TPAT_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_TPAT_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_TPAT_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_TPAT_b06FwReleaseFix;
+ fw.start_addr = bnx2_TPAT_b06FwStartAddr;
+
+ fw.text_addr = bnx2_TPAT_b06FwTextAddr;
+ fw.text_len = bnx2_TPAT_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_TPAT_b06FwText;
+
+ fw.data_addr = bnx2_TPAT_b06FwDataAddr;
+ fw.data_len = bnx2_TPAT_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_TPAT_b06FwData;
+
+ fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr;
+ fw.sbss_len = bnx2_TPAT_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_TPAT_b06FwSbss;
+
+ fw.bss_addr = bnx2_TPAT_b06FwBssAddr;
+ fw.bss_len = bnx2_TPAT_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_TPAT_b06FwBss;
+
+ fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr;
+ fw.rodata_len = bnx2_TPAT_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_TPAT_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the Completion Processor. */
+ cpu_reg.mode = BNX2_COM_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_COM_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_COM_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_COM_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_COM_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_COM_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_COM_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_COM_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_COM_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_COM_b06FwReleaseFix;
+ fw.start_addr = bnx2_COM_b06FwStartAddr;
+
+ fw.text_addr = bnx2_COM_b06FwTextAddr;
+ fw.text_len = bnx2_COM_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_COM_b06FwText;
+
+ fw.data_addr = bnx2_COM_b06FwDataAddr;
+ fw.data_len = bnx2_COM_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_COM_b06FwData;
+
+ fw.sbss_addr = bnx2_COM_b06FwSbssAddr;
+ fw.sbss_len = bnx2_COM_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_COM_b06FwSbss;
+
+ fw.bss_addr = bnx2_COM_b06FwBssAddr;
+ fw.bss_len = bnx2_COM_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_COM_b06FwBss;
+
+ fw.rodata_addr = bnx2_COM_b06FwRodataAddr;
+ fw.rodata_len = bnx2_COM_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_COM_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+}
+
+static int
+bnx2_set_power_state_0(struct bnx2 *bp)
+{
+ u16 pmcsr;
+ u32 val;
+
+ pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
+
+ pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+ (pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
+ PCI_PM_CTRL_PME_STATUS);
+
+ if (pmcsr & PCI_PM_CTRL_STATE_MASK)
+ /* delay required during transition out of D3hot */
+ mdelay(20);
+
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+ val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
+ val &= ~BNX2_EMAC_MODE_MPKT;
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ val = REG_RD(bp, BNX2_RPM_CONFIG);
+ val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
+ REG_WR(bp, BNX2_RPM_CONFIG, val);
+
+ return 0;
+}
+
+static void
+bnx2_enable_nvram_access(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ /* Enable both bits, even on read. */
+ REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
+}
+
+static void
+bnx2_disable_nvram_access(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ /* Disable both bits, even after read. */
+ REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
+ BNX2_NVM_ACCESS_ENABLE_WR_EN));
+}
+
+static int
+bnx2_init_nvram(struct bnx2 *bp)
+{
+ u32 val;
+ int j, entry_count, rc;
+ struct flash_spec *flash;
+
+ /* Determine the selected interface. */
+ val = REG_RD(bp, BNX2_NVM_CFG1);
+
+ entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
+
+ rc = 0;
+ if (val & 0x40000000) {
+ /* Flash interface has been reconfigured */
+ for (j = 0, flash = &flash_table[0]; j < entry_count;
+ j++, flash++) {
+ if ((val & FLASH_BACKUP_STRAP_MASK) ==
+ (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
+ bp->flash_info = flash;
+ break;
+ }
+ }
+ }
+ else {
+ u32 mask;
+ /* Not yet been reconfigured */
+
+ if (val & (1 << 23))
+ mask = FLASH_BACKUP_STRAP_MASK;
+ else
+ mask = FLASH_STRAP_MASK;
+
+ for (j = 0, flash = &flash_table[0]; j < entry_count;
+ j++, flash++) {
+
+ if ((val & mask) == (flash->strapping & mask)) {
+ bp->flash_info = flash;
+
+ /* Enable access to flash interface */
+ bnx2_enable_nvram_access(bp);
+
+ /* Reconfigure the flash interface */
+ REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
+ REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
+ REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
+ REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
+
+ /* Disable access to flash interface */
+ bnx2_disable_nvram_access(bp);
+
+ break;
+ }
+ }
+ } /* if (val & 0x40000000) */
+
+ if (j == entry_count) {
+ bp->flash_info = NULL;
+ printf("Unknown flash/EEPROM type.\n");
+ return -ENODEV;
+ }
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2);
+ val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
+ if (val) {
+ bp->flash_size = val;
+ }
+ else {
+ bp->flash_size = bp->flash_info->total_size;
+ }
+
+ return rc;
+}
+
+static int
+bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
+{
+ u32 val;
+ int i, rc = 0;
+
+ /* Wait for the current PCI transaction to complete before
+ * issuing a reset. */
+ REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+ BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+ val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+ udelay(5);
+
+
+ /* Wait for the firmware to tell us it is ok to issue a reset. */
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1);
+
+ /* Deposit a driver reset signature so the firmware knows that
+ * this is a soft reset. */
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE,
+ BNX2_DRV_RESET_SIGNATURE_MAGIC);
+
+ /* Do a dummy read to force the chip to complete all current transaction
+ * before we issue a reset. */
+ val = REG_RD(bp, BNX2_MISC_ID);
+
+ val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+
+ /* Chip reset. */
+ REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+
+ if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5706_A1))
+ mdelay(15);
+
+ /* Reset takes approximate 30 usec */
+ for (i = 0; i < 10; i++) {
+ val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
+ if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
+ break;
+ }
+ udelay(10);
+ }
+
+ if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
+ printf("Chip reset did not complete\n");
+ return -EBUSY;
+ }
+
+ /* Make sure byte swapping is properly configured. */
+ val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
+ if (val != 0x01020304) {
+ printf("Chip not in correct endian mode\n");
+ return -ENODEV;
+ }
+
+ /* Wait for the firmware to finish its initialization. */
+ rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0);
+ if (rc) {
+ return rc;
+ }
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ /* Adjust the voltage regular to two steps lower. The default
+ * of this register is 0x0000000e. */
+ REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
+
+ /* Remove bad rbuf memory from the free pool. */
+ rc = bnx2_alloc_bad_rbuf(bp);
+ }
+
+ return rc;
+}
+
+static void
+bnx2_disable(struct nic *nic __unused)
+{
+ struct bnx2* bp = &bnx2;
+
+ if (bp->regview) {
+ bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_UNLOAD);
+ iounmap(bp->regview);
+ }
+}
+
+static int
+bnx2_init_chip(struct bnx2 *bp)
+{
+ u32 val;
+ int rc;
+
+ /* Make sure the interrupt is not active. */
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+
+ val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
+ BNX2_DMA_CONFIG_DATA_WORD_SWAP |
+#if __BYTE_ORDER == __BIG_ENDIAN
+ BNX2_DMA_CONFIG_CNTL_BYTE_SWAP |
+#endif
+ BNX2_DMA_CONFIG_CNTL_WORD_SWAP |
+ DMA_READ_CHANS << 12 |
+ DMA_WRITE_CHANS << 16;
+
+ val |= (0x2 << 20) | (1 << 11);
+
+ if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz == 133))
+ val |= (1 << 23);
+
+ if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
+ (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & PCIX_FLAG))
+ val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
+
+ REG_WR(bp, BNX2_DMA_CONFIG, val);
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ val = REG_RD(bp, BNX2_TDMA_CONFIG);
+ val |= BNX2_TDMA_CONFIG_ONE_DMA;
+ REG_WR(bp, BNX2_TDMA_CONFIG, val);
+ }
+
+ if (bp->flags & PCIX_FLAG) {
+ u16 val16;
+
+ pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
+ &val16);
+ pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
+ val16 & ~PCI_X_CMD_ERO);
+ }
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
+
+ /* Initialize context mapping and zero out the quick contexts. The
+ * context block must have already been enabled. */
+ bnx2_init_context(bp);
+
+ bnx2_init_nvram(bp);
+ bnx2_init_cpus(bp);
+
+ bnx2_set_mac_addr(bp);
+
+ val = REG_RD(bp, BNX2_MQ_CONFIG);
+ val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
+ val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
+ REG_WR(bp, BNX2_MQ_CONFIG, val);
+
+ val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
+ REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
+ REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
+
+ val = (BCM_PAGE_BITS - 8) << 24;
+ REG_WR(bp, BNX2_RV2P_CONFIG, val);
+
+ /* Configure page size. */
+ val = REG_RD(bp, BNX2_TBDR_CONFIG);
+ val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
+ val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
+ REG_WR(bp, BNX2_TBDR_CONFIG, val);
+
+ val = bp->mac_addr[0] +
+ (bp->mac_addr[1] << 8) +
+ (bp->mac_addr[2] << 16) +
+ bp->mac_addr[3] +
+ (bp->mac_addr[4] << 8) +
+ (bp->mac_addr[5] << 16);
+ REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
+
+ /* Program the MTU. Also include 4 bytes for CRC32. */
+ val = ETH_MAX_MTU + ETH_HLEN + 4;
+ if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
+ val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
+ REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
+
+ bp->last_status_idx = 0;
+ bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
+
+ /* Set up how to generate a link change interrupt. */
+ REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+
+ REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
+ (u64) bp->status_blk_mapping & 0xffffffff);
+ REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
+
+ REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
+ (u64) bp->stats_blk_mapping & 0xffffffff);
+ REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
+ (u64) bp->stats_blk_mapping >> 32);
+
+ REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
+ (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
+
+ REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
+ (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
+
+ REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
+ (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
+
+ REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
+
+ REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
+
+ REG_WR(bp, BNX2_HC_COM_TICKS,
+ (bp->com_ticks_int << 16) | bp->com_ticks);
+
+ REG_WR(bp, BNX2_HC_CMD_TICKS,
+ (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
+
+ REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
+ REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A1)
+ REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS);
+ else {
+ REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE |
+ BNX2_HC_CONFIG_TX_TMR_MODE |
+ BNX2_HC_CONFIG_COLLECT_STATS);
+ }
+
+ /* Clear internal stats counters. */
+ REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
+
+ REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
+
+ if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
+ BNX2_PORT_FEATURE_ASF_ENABLED)
+ bp->flags |= ASF_ENABLE_FLAG;
+
+ /* Initialize the receive filter. */
+ bnx2_set_rx_mode(bp->nic);
+
+ rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
+ 0);
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
+ REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
+
+ udelay(20);
+
+ bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+
+ return rc;
+}
+
+static void
+bnx2_init_tx_ring(struct bnx2 *bp)
+{
+ struct tx_bd *txbd;
+ u32 val;
+
+ txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
+
+ /* Etherboot lives below 4GB, so hi is always 0 */
+ txbd->tx_bd_haddr_hi = 0;
+ txbd->tx_bd_haddr_lo = bp->tx_desc_mapping;
+
+ bp->tx_prod = 0;
+ bp->tx_cons = 0;
+ bp->hw_tx_cons = 0;
+ bp->tx_prod_bseq = 0;
+
+ val = BNX2_L2CTX_TYPE_TYPE_L2;
+ val |= BNX2_L2CTX_TYPE_SIZE_L2;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val);
+
+ val = BNX2_L2CTX_CMD_TYPE_TYPE_L2;
+ val |= 8 << 16;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val);
+
+ /* Etherboot lives below 4GB, so hi is always 0 */
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, 0);
+
+ val = (u64) bp->tx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val);
+}
+
+static void
+bnx2_init_rx_ring(struct bnx2 *bp)
+{
+ struct rx_bd *rxbd;
+ unsigned int i;
+ u16 prod, ring_prod;
+ u32 val;
+
+ bp->rx_buf_use_size = RX_BUF_USE_SIZE;
+ bp->rx_buf_size = RX_BUF_SIZE;
+
+ ring_prod = prod = bp->rx_prod = 0;
+ bp->rx_cons = 0;
+ bp->hw_rx_cons = 0;
+ bp->rx_prod_bseq = 0;
+
+ memset(bnx2_bss.rx_buf, 0, sizeof(bnx2_bss.rx_buf));
+
+ rxbd = &bp->rx_desc_ring[0];
+ for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
+ rxbd->rx_bd_len = bp->rx_buf_use_size;
+ rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
+ }
+ rxbd->rx_bd_haddr_hi = 0;
+ rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff;
+
+ val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
+ val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
+ val |= 0x02 << 8;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
+
+ /* Etherboot doesn't use memory above 4GB, so this is always 0 */
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, 0);
+
+ val = bp->rx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
+
+ for (i = 0; (int) i < bp->rx_ring_size; i++) {
+ rxbd = &bp->rx_desc_ring[RX_RING_IDX(ring_prod)];
+ rxbd->rx_bd_haddr_hi = 0;
+ rxbd->rx_bd_haddr_lo = virt_to_bus(&bnx2_bss.rx_buf[ring_prod][0]);
+ bp->rx_prod_bseq += bp->rx_buf_use_size;
+ prod = NEXT_RX_BD(prod);
+ ring_prod = RX_RING_IDX(prod);
+ }
+ bp->rx_prod = prod;
+
+ REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, bp->rx_prod);
+
+ REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
+}
+
+static int
+bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
+{
+ int rc;
+
+ rc = bnx2_reset_chip(bp, reset_code);
+ if (rc) {
+ return rc;
+ }
+
+ bnx2_init_chip(bp);
+ bnx2_init_tx_ring(bp);
+ bnx2_init_rx_ring(bp);
+ return 0;
+}
+
+static int
+bnx2_init_nic(struct bnx2 *bp)
+{
+ int rc;
+
+ if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
+ return rc;
+
+ bnx2_init_phy(bp);
+ bnx2_set_link(bp);
+ return 0;
+}
+
+static int
+bnx2_init_board(struct pci_device *pdev, struct nic *nic)
+{
+ unsigned long bnx2reg_base, bnx2reg_len;
+ struct bnx2 *bp = &bnx2;
+ int rc;
+ u32 reg;
+
+ bp->flags = 0;
+ bp->phy_flags = 0;
+
+ /* enable device (incl. PCI PM wakeup), and bus-mastering */
+ adjust_pci_device(pdev);
+
+ nic->ioaddr = pdev->ioaddr & ~3;
+ nic->irqno = 0;
+
+ rc = 0;
+ bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (bp->pm_cap == 0) {
+ printf("Cannot find power management capability, aborting.\n");
+ rc = -EIO;
+ goto err_out_disable;
+ }
+
+ bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
+ if (bp->pcix_cap == 0) {
+ printf("Cannot find PCIX capability, aborting.\n");
+ rc = -EIO;
+ goto err_out_disable;
+ }
+
+ bp->pdev = pdev;
+ bp->nic = nic;
+
+ bnx2reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+ bnx2reg_len = MB_GET_CID_ADDR(17);
+
+ bp->regview = ioremap(bnx2reg_base, bnx2reg_len);
+
+ if (!bp->regview) {
+ printf("Cannot map register space, aborting.\n");
+ rc = -EIO;
+ goto err_out_disable;
+ }
+
+ /* Configure byte swap and enable write to the reg_window registers.
+ * Rely on CPU to do target byte swapping on big endian systems
+ * The chip's target access swapping will not swap all accesses
+ */
+ pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
+
+ bnx2_set_power_state_0(bp);
+
+ bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+
+ /* Get bus information. */
+ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
+ if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
+ u32 clkreg;
+
+ bp->flags |= PCIX_FLAG;
+
+ clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
+
+ clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
+ switch (clkreg) {
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
+ bp->bus_speed_mhz = 133;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
+ bp->bus_speed_mhz = 100;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
+ bp->bus_speed_mhz = 66;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
+ bp->bus_speed_mhz = 50;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
+ bp->bus_speed_mhz = 33;
+ break;
+ }
+ }
+ else {
+ if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
+ bp->bus_speed_mhz = 66;
+ else
+ bp->bus_speed_mhz = 33;
+ }
+
+ if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
+ bp->flags |= PCI_32BIT_FLAG;
+
+ /* 5706A0 may falsely detect SERR and PERR. */
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ reg = REG_RD(bp, PCI_COMMAND);
+ reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+ REG_WR(bp, PCI_COMMAND, reg);
+ }
+ else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
+ !(bp->flags & PCIX_FLAG)) {
+
+ printf("5706 A1 can only be used in a PCIX bus, aborting.\n");
+ goto err_out_disable;
+ }
+
+ bnx2_init_nvram(bp);
+
+ reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE);
+
+ if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
+ BNX2_SHM_HDR_SIGNATURE_SIG)
+ bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0);
+ else
+ bp->shmem_base = HOST_VIEW_SHMEM_BASE;
+
+ /* Get the permanent MAC address. First we need to make sure the
+ * firmware is actually running.
+ */
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_SIGNATURE);
+
+ if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
+ BNX2_DEV_INFO_SIGNATURE_MAGIC) {
+ printf("Firmware not running, aborting.\n");
+ rc = -ENODEV;
+ goto err_out_disable;
+ }
+
+ bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
+ bp->mac_addr[0] = (u8) (reg >> 8);
+ bp->mac_addr[1] = (u8) reg;
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_LOWER);
+ bp->mac_addr[2] = (u8) (reg >> 24);
+ bp->mac_addr[3] = (u8) (reg >> 16);
+ bp->mac_addr[4] = (u8) (reg >> 8);
+ bp->mac_addr[5] = (u8) reg;
+
+ bp->tx_ring_size = MAX_TX_DESC_CNT;
+ bp->rx_ring_size = RX_BUF_CNT;
+ bp->rx_max_ring_idx = MAX_RX_DESC_CNT;
+
+ bp->rx_offset = RX_OFFSET;
+
+ bp->tx_quick_cons_trip_int = 20;
+ bp->tx_quick_cons_trip = 20;
+ bp->tx_ticks_int = 80;
+ bp->tx_ticks = 80;
+
+ bp->rx_quick_cons_trip_int = 6;
+ bp->rx_quick_cons_trip = 6;
+ bp->rx_ticks_int = 18;
+ bp->rx_ticks = 18;
+
+ bp->stats_ticks = 1000000 & 0xffff00;
+
+ bp->phy_addr = 1;
+
+ /* No need for WOL support in Etherboot */
+ bp->flags |= NO_WOL_FLAG;
+
+ /* Disable WOL support if we are running on a SERDES chip. */
+ if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ bp->phy_addr = 2;
+ reg = REG_RD_IND(bp, bp->shmem_base +
+ BNX2_SHARED_HW_CFG_CONFIG);
+ if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
+ bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
+ }
+ }
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ bp->tx_quick_cons_trip_int =
+ bp->tx_quick_cons_trip;
+ bp->tx_ticks_int = bp->tx_ticks;
+ bp->rx_quick_cons_trip_int =
+ bp->rx_quick_cons_trip;
+ bp->rx_ticks_int = bp->rx_ticks;
+ bp->comp_prod_trip_int = bp->comp_prod_trip;
+ bp->com_ticks_int = bp->com_ticks;
+ bp->cmd_ticks_int = bp->cmd_ticks;
+ }
+
+ bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
+ bp->req_line_speed = 0;
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
+ reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+ if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+ bp->autoneg = 0;
+ bp->req_line_speed = bp->line_speed = SPEED_1000;
+ bp->req_duplex = DUPLEX_FULL;
+ }
+ }
+ else {
+ bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
+ }
+
+ bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
+
+ /* Disable driver heartbeat checking */
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB,
+ BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE);
+ REG_RD_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB);
+
+ return 0;
+
+err_out_disable:
+ bnx2_disable(nic);
+
+ return rc;
+}
+
+static void
+bnx2_transmit(struct nic *nic, const char *dst_addr,
+ unsigned int type, unsigned int size, const char *packet)
+{
+ /* Sometimes the nic will be behind by a frame. Using two transmit
+ * buffers prevents us from timing out in that case.
+ */
+ static struct eth_frame {
+ uint8_t dst_addr[ETH_ALEN];
+ uint8_t src_addr[ETH_ALEN];
+ uint16_t type;
+ uint8_t data [ETH_FRAME_LEN - ETH_HLEN];
+ } frame[2];
+ static int frame_idx = 0;
+
+ /* send the packet to destination */
+ struct tx_bd *txbd;
+ struct bnx2 *bp = &bnx2;
+ u16 prod, ring_prod;
+ u16 hw_cons;
+ int i = 0;
+
+ prod = bp->tx_prod;
+ ring_prod = TX_RING_IDX(prod);
+ hw_cons = bp->status_blk->status_tx_quick_consumer_index0;
+ if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) {
+ hw_cons++;
+ }
+
+ while((hw_cons != prod) && (hw_cons != (PREV_TX_BD(prod)))) {
+ mdelay(10); /* give the nic a chance */
+ //poll_interruptions();
+ if (++i > 500) { /* timeout 5s for transmit */
+ printf("transmit timed out\n");
+ bnx2_disable(bp->nic);
+ bnx2_init_board(bp->pdev, bp->nic);
+ return;
+ }
+ }
+ if (i != 0) {
+ printf("#");
+ }
+
+ /* Copy the packet to the our local buffer */
+ memcpy(&frame[frame_idx].dst_addr, dst_addr, ETH_ALEN);
+ memcpy(&frame[frame_idx].src_addr, nic->node_addr, ETH_ALEN);
+ frame[frame_idx].type = htons(type);
+ memset(&frame[frame_idx].data, 0, sizeof(frame[frame_idx].data));
+ memcpy(&frame[frame_idx].data, packet, size);
+
+ /* Setup the ring buffer entry to transmit */
+ txbd = &bp->tx_desc_ring[ring_prod];
+ txbd->tx_bd_haddr_hi = 0; /* Etherboot runs under 4GB */
+ txbd->tx_bd_haddr_lo = virt_to_bus(&frame[frame_idx]);
+ txbd->tx_bd_mss_nbytes = (size + ETH_HLEN);
+ txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
+
+ /* Advance to the next entry */
+ prod = NEXT_TX_BD(prod);
+ frame_idx ^= 1;
+
+ bp->tx_prod_bseq += (size + ETH_HLEN);
+
+ REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
+ REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
+
+ wmb();
+
+ bp->tx_prod = prod;
+}
+
+static int
+bnx2_poll_link(struct bnx2 *bp)
+{
+ u32 new_link_state, old_link_state, emac_status;
+
+ new_link_state = bp->status_blk->status_attn_bits &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ old_link_state = bp->status_blk->status_attn_bits_ack &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ if (!new_link_state && !old_link_state) {
+ /* For some reason the card doesn't always update the link
+ * status bits properly. Kick the stupid thing and try again.
+ */
+ u32 bmsr;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ REG_RD(bp, BNX2_EMAC_STATUS);
+ }
+
+ new_link_state = bp->status_blk->status_attn_bits &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ old_link_state = bp->status_blk->status_attn_bits_ack &
+ STATUS_ATTN_BITS_LINK_STATE;
+
+ /* Okay, for some reason the above doesn't work with some
+ * switches (like HP ProCurve). If the above doesn't work,
+ * check the MAC directly to see if we have a link. Perhaps we
+ * should always check the MAC instead probing the MII.
+ */
+ if (!new_link_state && !old_link_state) {
+ emac_status = REG_RD(bp, BNX2_EMAC_STATUS);
+ if (emac_status & BNX2_EMAC_STATUS_LINK_CHANGE) {
+ /* Acknowledge the link change */
+ REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+ } else if (emac_status & BNX2_EMAC_STATUS_LINK) {
+ new_link_state = !old_link_state;
+ }
+ }
+
+ }
+
+ if (new_link_state != old_link_state) {
+ if (new_link_state) {
+ REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD,
+ STATUS_ATTN_BITS_LINK_STATE);
+ }
+ else {
+ REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD,
+ STATUS_ATTN_BITS_LINK_STATE);
+ }
+
+ bnx2_set_link(bp);
+
+ /* This is needed to take care of transient status
+ * during link changes.
+ */
+
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_RD(bp, BNX2_HC_COMMAND);
+
+ }
+
+ return bp->link_up;
+}
+
+static int
+bnx2_poll(struct nic* nic, int retrieve)
+{
+ struct bnx2 *bp = &bnx2;
+ struct rx_bd *cons_bd, *prod_bd;
+ u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
+ struct l2_fhdr *rx_hdr;
+ int result = 0;
+ unsigned int len;
+ unsigned char *data;
+ u32 status;
+
+#if 0
+ if ((bp->status_blk->status_idx == bp->last_status_idx) &&
+ (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
+ BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) {
+
+ bp->last_status_idx = bp->status_blk->status_idx;
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bp->last_status_idx);
+ return 0;
+ }
+#endif
+
+ if ((bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) && !retrieve)
+ return 1;
+
+ if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) {
+
+ hw_cons = bp->hw_rx_cons = bp->status_blk->status_rx_quick_consumer_index0;
+ if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) {
+ hw_cons++;
+ }
+ sw_cons = bp->rx_cons;
+ sw_prod = bp->rx_prod;
+
+ rmb();
+ if (sw_cons != hw_cons) {
+
+ sw_ring_cons = RX_RING_IDX(sw_cons);
+ sw_ring_prod = RX_RING_IDX(sw_prod);
+
+ data = bus_to_virt(bp->rx_desc_ring[sw_ring_cons].rx_bd_haddr_lo);
+
+ rx_hdr = (struct l2_fhdr *)data;
+ len = rx_hdr->l2_fhdr_pkt_len - 4;
+ if ((len > (ETH_MAX_MTU + ETH_HLEN)) ||
+ ((status = rx_hdr->l2_fhdr_status) &
+ (L2_FHDR_ERRORS_BAD_CRC |
+ L2_FHDR_ERRORS_PHY_DECODE |
+ L2_FHDR_ERRORS_ALIGNMENT |
+ L2_FHDR_ERRORS_TOO_SHORT |
+ L2_FHDR_ERRORS_GIANT_FRAME))) {
+ result = 0;
+ }
+ else
+ {
+ nic->packetlen = len;
+ memcpy(nic->packet, data + bp->rx_offset, len);
+ result = 1;
+ }
+
+ /* Reuse the buffer */
+ bp->rx_prod_bseq += bp->rx_buf_use_size;
+ if (sw_cons != sw_prod) {
+ cons_bd = &bp->rx_desc_ring[sw_ring_cons];
+ prod_bd = &bp->rx_desc_ring[sw_ring_prod];
+ prod_bd->rx_bd_haddr_hi = 0; /* Etherboot runs under 4GB */
+ prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
+ }
+
+ sw_cons = NEXT_RX_BD(sw_cons);
+ sw_prod = NEXT_RX_BD(sw_prod);
+
+ }
+
+ bp->rx_cons = sw_cons;
+ bp->rx_prod = sw_prod;
+
+ REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, bp->rx_prod);
+
+ REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
+
+ wmb();
+
+ }
+
+ bnx2_poll_link(bp);
+
+#if 0
+ bp->last_status_idx = bp->status_blk->status_idx;
+ rmb();
+
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+ bp->last_status_idx);
+
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+#endif
+
+ return result;
+}
+
+static void
+bnx2_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE: break;
+ case ENABLE: break;
+ case FORCE: break;
+ }
+}
+
+static struct nic_operations bnx2_operations = {
+ .connect = dummy_connect,
+ .poll = bnx2_poll,
+ .transmit = bnx2_transmit,
+ .irq = bnx2_irq,
+};
+
+static int
+bnx2_probe(struct nic *nic, struct pci_device *pdev)
+{
+ struct bnx2 *bp = &bnx2;
+ int i, rc;
+
+ if (pdev == 0)
+ return 0;
+
+ memset(bp, 0, sizeof(*bp));
+
+ rc = bnx2_init_board(pdev, nic);
+ if (rc < 0) {
+ return 0;
+ }
+
+ /*
+ nic->disable = bnx2_disable;
+ nic->transmit = bnx2_transmit;
+ nic->poll = bnx2_poll;
+ nic->irq = bnx2_irq;
+ */
+
+ nic->nic_op = &bnx2_operations;
+
+ memcpy(nic->node_addr, bp->mac_addr, ETH_ALEN);
+ printf("Ethernet addr: %s\n", eth_ntoa( nic->node_addr ) );
+ printf("Broadcom NetXtreme II (%c%d) PCI%s %s %dMHz\n",
+ (int) ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
+ (int) ((CHIP_ID(bp) & 0x0ff0) >> 4),
+ ((bp->flags & PCIX_FLAG) ? "-X" : ""),
+ ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
+ bp->bus_speed_mhz);
+
+ bnx2_set_power_state_0(bp);
+ bnx2_disable_int(bp);
+
+ bnx2_alloc_mem(bp);
+
+ rc = bnx2_init_nic(bp);
+ if (rc) {
+ return 0;
+ }
+
+ bnx2_poll_link(bp);
+ for(i = 0; !bp->link_up && (i < VALID_LINK_TIMEOUT*100); i++) {
+ mdelay(1);
+ bnx2_poll_link(bp);
+ }
+#if 1
+ if (!bp->link_up){
+ printf("Valid link not established\n");
+ goto err_out_disable;
+ }
+#endif
+
+ return 1;
+
+err_out_disable:
+ bnx2_disable(nic);
+ return 0;
+}
+
+static struct pci_device_id bnx2_nics[] = {
+ PCI_ROM(0x14e4, 0x164a, "bnx2-5706", "Broadcom NetXtreme II BCM5706", 0),
+ PCI_ROM(0x14e4, 0x164c, "bnx2-5708", "Broadcom NetXtreme II BCM5708", 0),
+ PCI_ROM(0x14e4, 0x16aa, "bnx2-5706S", "Broadcom NetXtreme II BCM5706S", 0),
+ PCI_ROM(0x14e4, 0x16ac, "bnx2-5708S", "Broadcom NetXtreme II BCM5708S", 0),
+};
+
+PCI_DRIVER ( bnx2_driver, bnx2_nics, PCI_NO_CLASS );
+
+DRIVER ( "BNX2", nic_driver, pci_driver, bnx2_driver, bnx2_probe, bnx2_disable );
+
+/*
+static struct pci_driver bnx2_driver __pci_driver = {
+ .type = NIC_DRIVER,
+ .name = "BNX2",
+ .probe = bnx2_probe,
+ .ids = bnx2_nics,
+ .id_count = sizeof(bnx2_nics)/sizeof(bnx2_nics[0]),
+ .class = 0,
+};
+*/
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.h
new file mode 100644
index 0000000..9267868
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/bnx2.h
@@ -0,0 +1,4598 @@
+/* bnx2.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef BNX2_H
+#define BNX2_H
+
+#define L1_CACHE_BYTES 128 /* Rough approximaition of the cache line size */
+#define L1_CACHE_ALIGN(X) (((X) + L1_CACHE_BYTES-1)&~(L1_CACHE_BYTES -1))
+
+typedef unsigned long dma_addr_t;
+
+/* From pci.h */
+typedef int pci_power_t;
+
+#define PCI_D0 ((pci_power_t) 0)
+#define PCI_D1 ((pci_power_t) 1)
+#define PCI_D2 ((pci_power_t) 2)
+#define PCI_D3hot ((pci_power_t) 3)
+#define PCI_D3cold ((pci_power_t) 4)
+#define PCI_UNKNOWN ((pci_power_t) 5)
+#define PCI_POWER_ERROR ((pci_power_t) -1)
+
+/* From pci_regs.h */
+
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define PCI_X_CMD 2 /* Modes & Features */
+#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+
+/* From mii.h */
+
+/* Indicates what features are advertised by the interface. */
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+#define ADVERTISED_Autoneg (1 << 6)
+#define ADVERTISED_TP (1 << 7)
+#define ADVERTISED_AUI (1 << 8)
+#define ADVERTISED_MII (1 << 9)
+#define ADVERTISED_FIBRE (1 << 10)
+#define ADVERTISED_BNC (1 << 11)
+
+/* The following are all involved in forcing a particular link
+ * mode for the device for setting things. When getting the
+ * devices settings, these indicate the current mode and whether
+ * it was foced up into this mode or autonegotiated.
+ */
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+#define DUPLEX_INVALID 0x02
+
+/* Which connector port. */
+#define PORT_TP 0x00
+#define PORT_AUI 0x01
+#define PORT_MII 0x02
+#define PORT_FIBRE 0x03
+#define PORT_BNC 0x04
+
+/* Which tranceiver to use. */
+#define XCVR_INTERNAL 0x00
+#define XCVR_EXTERNAL 0x01
+#define XCVR_DUMMY1 0x02
+#define XCVR_DUMMY2 0x03
+#define XCVR_DUMMY3 0x04
+
+/* Enable or disable autonegotiation. If this is set to enable,
+ * the forced link modes above are completely ignored.
+ */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+/* Wake-On-Lan options. */
+#define WAKE_PHY (1 << 0)
+#define WAKE_UCAST (1 << 1)
+#define WAKE_MCAST (1 << 2)
+#define WAKE_BCAST (1 << 3)
+#define WAKE_ARP (1 << 4)
+#define WAKE_MAGIC (1 << 5)
+#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
+
+/* The following are all involved in forcing a particular link
+ * * mode for the device for setting things. When getting the
+ * * devices settings, these indicate the current mode and whether
+ * * it was foced up into this mode or autonegotiated.
+ * */
+
+/* The forced speed, 10Mb, 100Mb, gigabit. */
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define SPEED_2500 2500
+#define SPEED_INVALID 0 /* XXX was 3 */
+
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+#define DUPLEX_INVALID 0x02
+
+/* Which connector port. */
+#define PORT_TP 0x00
+#define PORT_AUI 0x01
+#define PORT_MII 0x02
+#define PORT_FIBRE 0x03
+#define PORT_BNC 0x04
+
+/* Which tranceiver to use. */
+#define XCVR_INTERNAL 0x00
+#define XCVR_EXTERNAL 0x01
+#define XCVR_DUMMY1 0x02
+#define XCVR_DUMMY2 0x03
+#define XCVR_DUMMY3 0x04
+
+/* Enable or disable autonegotiation. If this is set to enable,
+ * * the forced link modes above are completely ignored.
+ * */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+/* Wake-On-Lan options. */
+#define WAKE_PHY (1 << 0)
+#define WAKE_UCAST (1 << 1)
+#define WAKE_MCAST (1 << 2)
+#define WAKE_BCAST (1 << 3)
+#define WAKE_ARP (1 << 4)
+#define WAKE_MAGIC (1 << 5)
+#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
+
+/* Hardware data structures and register definitions automatically
+ * generated from RTL code. Do not modify.
+ */
+
+/*
+ * tx_bd definition
+ */
+struct tx_bd {
+ u32 tx_bd_haddr_hi;
+ u32 tx_bd_haddr_lo;
+ u32 tx_bd_mss_nbytes;
+ u32 tx_bd_vlan_tag_flags;
+ #define TX_BD_FLAGS_CONN_FAULT (1<<0)
+ #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
+ #define TX_BD_FLAGS_IP_CKSUM (1<<2)
+ #define TX_BD_FLAGS_VLAN_TAG (1<<3)
+ #define TX_BD_FLAGS_COAL_NOW (1<<4)
+ #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5)
+ #define TX_BD_FLAGS_END (1<<6)
+ #define TX_BD_FLAGS_START (1<<7)
+ #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
+ #define TX_BD_FLAGS_SW_FLAGS (1<<13)
+ #define TX_BD_FLAGS_SW_SNAP (1<<14)
+ #define TX_BD_FLAGS_SW_LSO (1<<15)
+
+};
+
+
+/*
+ * rx_bd definition
+ */
+struct rx_bd {
+ u32 rx_bd_haddr_hi;
+ u32 rx_bd_haddr_lo;
+ u32 rx_bd_len;
+ u32 rx_bd_flags;
+ #define RX_BD_FLAGS_NOPUSH (1<<0)
+ #define RX_BD_FLAGS_DUMMY (1<<1)
+ #define RX_BD_FLAGS_END (1<<2)
+ #define RX_BD_FLAGS_START (1<<3)
+
+};
+
+
+/*
+ * status_block definition
+ */
+struct status_block {
+ u32 status_attn_bits;
+ #define STATUS_ATTN_BITS_LINK_STATE (1L<<0)
+ #define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT (1L<<1)
+ #define STATUS_ATTN_BITS_TX_BD_READ_ABORT (1L<<2)
+ #define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT (1L<<3)
+ #define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT (1L<<4)
+ #define STATUS_ATTN_BITS_TX_DMA_ABORT (1L<<5)
+ #define STATUS_ATTN_BITS_TX_PATCHUP_ABORT (1L<<6)
+ #define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT (1L<<7)
+ #define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT (1L<<8)
+ #define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT (1L<<9)
+ #define STATUS_ATTN_BITS_RX_MBUF_ABORT (1L<<10)
+ #define STATUS_ATTN_BITS_RX_LOOKUP_ABORT (1L<<11)
+ #define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT (1L<<12)
+ #define STATUS_ATTN_BITS_RX_V2P_ABORT (1L<<13)
+ #define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT (1L<<14)
+ #define STATUS_ATTN_BITS_RX_DMA_ABORT (1L<<15)
+ #define STATUS_ATTN_BITS_COMPLETION_ABORT (1L<<16)
+ #define STATUS_ATTN_BITS_HOST_COALESCE_ABORT (1L<<17)
+ #define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT (1L<<18)
+ #define STATUS_ATTN_BITS_CONTEXT_ABORT (1L<<19)
+ #define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT (1L<<20)
+ #define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT (1L<<21)
+ #define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT (1L<<22)
+ #define STATUS_ATTN_BITS_MAC_ABORT (1L<<23)
+ #define STATUS_ATTN_BITS_TIMER_ABORT (1L<<24)
+ #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25)
+ #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26)
+ #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27)
+ #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31)
+
+ u32 status_attn_bits_ack;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_completion_producer_index;
+ u16 status_cmd_consumer_index;
+ u16 status_idx;
+ u16 status_unused;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_cmd_consumer_index;
+ u16 status_completion_producer_index;
+ u16 status_unused;
+ u16 status_idx;
+#endif
+};
+
+
+/*
+ * statistics_block definition
+ */
+struct statistics_block {
+ u32 stat_IfHCInOctets_hi;
+ u32 stat_IfHCInOctets_lo;
+ u32 stat_IfHCInBadOctets_hi;
+ u32 stat_IfHCInBadOctets_lo;
+ u32 stat_IfHCOutOctets_hi;
+ u32 stat_IfHCOutOctets_lo;
+ u32 stat_IfHCOutBadOctets_hi;
+ u32 stat_IfHCOutBadOctets_lo;
+ u32 stat_IfHCInUcastPkts_hi;
+ u32 stat_IfHCInUcastPkts_lo;
+ u32 stat_IfHCInMulticastPkts_hi;
+ u32 stat_IfHCInMulticastPkts_lo;
+ u32 stat_IfHCInBroadcastPkts_hi;
+ u32 stat_IfHCInBroadcastPkts_lo;
+ u32 stat_IfHCOutUcastPkts_hi;
+ u32 stat_IfHCOutUcastPkts_lo;
+ u32 stat_IfHCOutMulticastPkts_hi;
+ u32 stat_IfHCOutMulticastPkts_lo;
+ u32 stat_IfHCOutBroadcastPkts_hi;
+ u32 stat_IfHCOutBroadcastPkts_lo;
+ u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
+ u32 stat_Dot3StatsCarrierSenseErrors;
+ u32 stat_Dot3StatsFCSErrors;
+ u32 stat_Dot3StatsAlignmentErrors;
+ u32 stat_Dot3StatsSingleCollisionFrames;
+ u32 stat_Dot3StatsMultipleCollisionFrames;
+ u32 stat_Dot3StatsDeferredTransmissions;
+ u32 stat_Dot3StatsExcessiveCollisions;
+ u32 stat_Dot3StatsLateCollisions;
+ u32 stat_EtherStatsCollisions;
+ u32 stat_EtherStatsFragments;
+ u32 stat_EtherStatsJabbers;
+ u32 stat_EtherStatsUndersizePkts;
+ u32 stat_EtherStatsOverrsizePkts;
+ u32 stat_EtherStatsPktsRx64Octets;
+ u32 stat_EtherStatsPktsRx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsRx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsRx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
+ u32 stat_EtherStatsPktsTx64Octets;
+ u32 stat_EtherStatsPktsTx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsTx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsTx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
+ u32 stat_XonPauseFramesReceived;
+ u32 stat_XoffPauseFramesReceived;
+ u32 stat_OutXonSent;
+ u32 stat_OutXoffSent;
+ u32 stat_FlowControlDone;
+ u32 stat_MacControlFramesReceived;
+ u32 stat_XoffStateEntered;
+ u32 stat_IfInFramesL2FilterDiscards;
+ u32 stat_IfInRuleCheckerDiscards;
+ u32 stat_IfInFTQDiscards;
+ u32 stat_IfInMBUFDiscards;
+ u32 stat_IfInRuleCheckerP4Hit;
+ u32 stat_CatchupInRuleCheckerDiscards;
+ u32 stat_CatchupInFTQDiscards;
+ u32 stat_CatchupInMBUFDiscards;
+ u32 stat_CatchupInRuleCheckerP4Hit;
+ u32 stat_GenStat00;
+ u32 stat_GenStat01;
+ u32 stat_GenStat02;
+ u32 stat_GenStat03;
+ u32 stat_GenStat04;
+ u32 stat_GenStat05;
+ u32 stat_GenStat06;
+ u32 stat_GenStat07;
+ u32 stat_GenStat08;
+ u32 stat_GenStat09;
+ u32 stat_GenStat10;
+ u32 stat_GenStat11;
+ u32 stat_GenStat12;
+ u32 stat_GenStat13;
+ u32 stat_GenStat14;
+ u32 stat_GenStat15;
+};
+
+
+/*
+ * l2_fhdr definition
+ */
+struct l2_fhdr {
+ u32 l2_fhdr_status;
+ #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0)
+ #define L2_FHDR_STATUS_RULE_P2 (1<<3)
+ #define L2_FHDR_STATUS_RULE_P3 (1<<4)
+ #define L2_FHDR_STATUS_RULE_P4 (1<<5)
+ #define L2_FHDR_STATUS_L2_VLAN_TAG (1<<6)
+ #define L2_FHDR_STATUS_L2_LLC_SNAP (1<<7)
+ #define L2_FHDR_STATUS_RSS_HASH (1<<8)
+ #define L2_FHDR_STATUS_IP_DATAGRAM (1<<13)
+ #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14)
+ #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
+
+ #define L2_FHDR_ERRORS_BAD_CRC (1<<17)
+ #define L2_FHDR_ERRORS_PHY_DECODE (1<<18)
+ #define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
+ #define L2_FHDR_ERRORS_TOO_SHORT (1<<20)
+ #define L2_FHDR_ERRORS_GIANT_FRAME (1<<21)
+ #define L2_FHDR_ERRORS_TCP_XSUM (1<<28)
+ #define L2_FHDR_ERRORS_UDP_XSUM (1<<31)
+
+ u32 l2_fhdr_hash;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_ip_xsum;
+ u16 l2_fhdr_tcp_udp_xsum;
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_tcp_udp_xsum;
+ u16 l2_fhdr_ip_xsum;
+#endif
+};
+
+
+/*
+ * l2_context definition
+ */
+#define BNX2_L2CTX_TYPE 0x00000000
+#define BNX2_L2CTX_TYPE_SIZE_L2 ((0xc0/0x20)<<16)
+#define BNX2_L2CTX_TYPE_TYPE (0xf<<28)
+#define BNX2_L2CTX_TYPE_TYPE_EMPTY (0<<28)
+#define BNX2_L2CTX_TYPE_TYPE_L2 (1<<28)
+
+#define BNX2_L2CTX_TX_HOST_BIDX 0x00000088
+#define BNX2_L2CTX_EST_NBD 0x00000088
+#define BNX2_L2CTX_CMD_TYPE 0x00000088
+#define BNX2_L2CTX_CMD_TYPE_TYPE (0xf<<24)
+#define BNX2_L2CTX_CMD_TYPE_TYPE_L2 (0<<24)
+#define BNX2_L2CTX_CMD_TYPE_TYPE_TCP (1<<24)
+
+#define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090
+#define BNX2_L2CTX_TSCH_BSEQ 0x00000094
+#define BNX2_L2CTX_TBDR_BSEQ 0x00000098
+#define BNX2_L2CTX_TBDR_BOFF 0x0000009c
+#define BNX2_L2CTX_TBDR_BIDX 0x0000009c
+#define BNX2_L2CTX_TBDR_BHADDR_HI 0x000000a0
+#define BNX2_L2CTX_TBDR_BHADDR_LO 0x000000a4
+#define BNX2_L2CTX_TXP_BOFF 0x000000a8
+#define BNX2_L2CTX_TXP_BIDX 0x000000a8
+#define BNX2_L2CTX_TXP_BSEQ 0x000000ac
+
+
+/*
+ * l2_bd_chain_context definition
+ */
+#define BNX2_L2CTX_BD_PRE_READ 0x00000000
+#define BNX2_L2CTX_CTX_SIZE 0x00000000
+#define BNX2_L2CTX_CTX_TYPE 0x00000000
+#define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28)
+
+#define BNX2_L2CTX_HOST_BDIDX 0x00000004
+#define BNX2_L2CTX_HOST_BSEQ 0x00000008
+#define BNX2_L2CTX_NX_BSEQ 0x0000000c
+#define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010
+#define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014
+#define BNX2_L2CTX_NX_BDIDX 0x00000018
+
+
+/*
+ * pci_config_l definition
+ * offset: 0000
+ */
+#define BNX2_PCICFG_MISC_CONFIG 0x00000068
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2)
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3)
+#define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5)
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6)
+#define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7)
+#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8)
+#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28)
+
+#define BNX2_PCICFG_MISC_STATUS 0x0000006c
+#define BNX2_PCICFG_MISC_STATUS_INTA_VALUE (1L<<0)
+#define BNX2_PCICFG_MISC_STATUS_32BIT_DET (1L<<1)
+#define BNX2_PCICFG_MISC_STATUS_M66EN (1L<<2)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_DET (1L<<3)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED (0x3L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66 (0L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4)
+
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+#define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078
+#define BNX2_PCICFG_REG_WINDOW 0x00000080
+#define BNX2_PCICFG_INT_ACK_CMD 0x00000084
+#define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0)
+#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16)
+#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17)
+#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18)
+
+#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
+#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c
+#define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090
+#define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094
+
+
+/*
+ * pci_reg definition
+ * offset: 0x400
+ */
+#define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400
+#define BNX2_PCI_GRC_WINDOW_ADDR_PCI_GRC_WINDOW_ADDR_VALUE (0x3ffffL<<8)
+
+#define BNX2_PCI_CONFIG_1 0x00000404
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32 (2L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64 (3L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128 (4L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256 (5L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512 (6L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024 (7L<<8)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY (0x7L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF (0L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16 (1L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32 (2L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64 (3L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128 (4L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11)
+
+#define BNX2_PCI_CONFIG_2 0x00000408
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_64ENA (1L<<4)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5)
+#define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6)
+#define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K (1L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K (2L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K (3L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K (4L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K (5L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K (6L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K (7L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K (8L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K (9L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K (10L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M (11L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M (12L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M (13L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M (14L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M (15L<<8)
+#define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT (0x1fL<<16)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT (0x3L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512 (0L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K (1L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K (2L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K (3L<<21)
+#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23)
+#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24)
+#define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25)
+
+#define BNX2_PCI_CONFIG_3 0x0000040c
+#define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0)
+#define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24)
+#define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25)
+#define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26)
+#define BNX2_PCI_CONFIG_3_PM_STATE (0x3L<<27)
+#define BNX2_PCI_CONFIG_3_VAUX_PRESET (1L<<30)
+#define BNX2_PCI_CONFIG_3_PCI_POWER (1L<<31)
+
+#define BNX2_PCI_PM_DATA_A 0x00000410
+#define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG (0xffL<<8)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG (0xffL<<16)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG (0xffL<<24)
+
+#define BNX2_PCI_PM_DATA_B 0x00000414
+#define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG (0xffL<<8)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG (0xffL<<16)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG (0xffL<<24)
+
+#define BNX2_PCI_SWAP_DIAG0 0x00000418
+#define BNX2_PCI_SWAP_DIAG1 0x0000041c
+#define BNX2_PCI_EXP_ROM_ADDR 0x00000420
+#define BNX2_PCI_EXP_ROM_ADDR_ADDRESS (0x3fffffL<<2)
+#define BNX2_PCI_EXP_ROM_ADDR_REQ (1L<<31)
+
+#define BNX2_PCI_EXP_ROM_DATA 0x00000424
+#define BNX2_PCI_VPD_INTF 0x00000428
+#define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0)
+
+#define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c
+#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fff<<2)
+#define BNX2_PCI_VPD_ADDR_FLAG_WR (1<<15)
+
+#define BNX2_PCI_VPD_DATA 0x00000430
+#define BNX2_PCI_ID_VAL1 0x00000434
+#define BNX2_PCI_ID_VAL1_DEVICE_ID (0xffffL<<0)
+#define BNX2_PCI_ID_VAL1_VENDOR_ID (0xffffL<<16)
+
+#define BNX2_PCI_ID_VAL2 0x00000438
+#define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID (0xffffL<<0)
+#define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID (0xffffL<<16)
+
+#define BNX2_PCI_ID_VAL3 0x0000043c
+#define BNX2_PCI_ID_VAL3_CLASS_CODE (0xffffffL<<0)
+#define BNX2_PCI_ID_VAL3_REVISION_ID (0xffL<<24)
+
+#define BNX2_PCI_ID_VAL4 0x00000440
+#define BNX2_PCI_ID_VAL4_CAP_ENA (0xfL<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_0 (0L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_1 (1L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_2 (2L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_3 (3L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_4 (4L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_5 (5L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_6 (6L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_7 (7L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_8 (8L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_9 (9L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_10 (10L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_11 (11L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_12 (12L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6)
+#define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9)
+#define BNX2_PCI_ID_VAL4_MSI_ADVERTIZE (0x7L<<12)
+#define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15)
+#define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16)
+#define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17)
+#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE (0x3L<<21)
+#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE (0x7L<<23)
+#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE (0x7L<<26)
+
+#define BNX2_PCI_ID_VAL5 0x00000444
+#define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0)
+#define BNX2_PCI_ID_VAL5_D2_SUPPORT (1L<<1)
+#define BNX2_PCI_ID_VAL5_PME_IN_D0 (1L<<2)
+#define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3)
+#define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4)
+#define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5)
+
+#define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST (1L<<9)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS (0xfL<<16)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX (0xffL<<24)
+
+#define BNX2_PCI_ID_VAL6 0x0000044c
+#define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0)
+#define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8)
+#define BNX2_PCI_ID_VAL6_BIST (0xffL<<16)
+
+#define BNX2_PCI_MSI_DATA 0x00000450
+#define BNX2_PCI_MSI_DATA_PCI_MSI_DATA (0xffffL<<0)
+
+#define BNX2_PCI_MSI_ADDR_H 0x00000454
+#define BNX2_PCI_MSI_ADDR_L 0x00000458
+
+
+/*
+ * misc_reg definition
+ * offset: 0x800
+ */
+#define BNX2_MISC_COMMAND 0x00000800
+#define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0)
+#define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1)
+#define BNX2_MISC_COMMAND_CORE_RESET (1L<<4)
+#define BNX2_MISC_COMMAND_HARD_RESET (1L<<5)
+#define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8)
+#define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16)
+
+#define BNX2_MISC_CFG 0x00000804
+#define BNX2_MISC_CFG_PCI_GRC_TMOUT (1L<<0)
+#define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW (2L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1)
+#define BNX2_MISC_CFG_BIST_EN (1L<<3)
+#define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4)
+#define BNX2_MISC_CFG_BYPASS_BSCAN (1L<<5)
+#define BNX2_MISC_CFG_BYPASS_EJTAG (1L<<6)
+#define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7)
+#define BNX2_MISC_CFG_LEDMODE (0x3L<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8)
+#define BNX2_MISC_CFG_LEDMODE_GPHY1 (1L<<8)
+#define BNX2_MISC_CFG_LEDMODE_GPHY2 (2L<<8)
+
+#define BNX2_MISC_ID 0x00000808
+#define BNX2_MISC_ID_BOND_ID (0xfL<<0)
+#define BNX2_MISC_ID_CHIP_METAL (0xffL<<4)
+#define BNX2_MISC_ID_CHIP_REV (0xfL<<12)
+#define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16)
+
+#define BNX2_MISC_ENABLE_STATUS_BITS 0x0000080c
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ENABLE_SET_BITS 0x00000810
+#define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ENABLE_CLR_BITS 0x00000814
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+#define BNX2_MISC_GPIO 0x0000081c
+#define BNX2_MISC_GPIO_VALUE (0xffL<<0)
+#define BNX2_MISC_GPIO_SET (0xffL<<8)
+#define BNX2_MISC_GPIO_CLR (0xffL<<16)
+#define BNX2_MISC_GPIO_FLOAT (0xffL<<24)
+
+#define BNX2_MISC_GPIO_INT 0x00000820
+#define BNX2_MISC_GPIO_INT_INT_STATE (0xfL<<0)
+#define BNX2_MISC_GPIO_INT_OLD_VALUE (0xfL<<8)
+#define BNX2_MISC_GPIO_INT_OLD_SET (0xfL<<16)
+#define BNX2_MISC_GPIO_INT_OLD_CLR (0xfL<<24)
+
+#define BNX2_MISC_CONFIG_LFSR 0x00000824
+#define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0)
+
+#define BNX2_MISC_LFSR_MASK_BITS 0x00000828
+#define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ARB_REQ0 0x0000082c
+#define BNX2_MISC_ARB_REQ1 0x00000830
+#define BNX2_MISC_ARB_REQ2 0x00000834
+#define BNX2_MISC_ARB_REQ3 0x00000838
+#define BNX2_MISC_ARB_REQ4 0x0000083c
+#define BNX2_MISC_ARB_FREE0 0x00000840
+#define BNX2_MISC_ARB_FREE1 0x00000844
+#define BNX2_MISC_ARB_FREE2 0x00000848
+#define BNX2_MISC_ARB_FREE3 0x0000084c
+#define BNX2_MISC_ARB_FREE4 0x00000850
+#define BNX2_MISC_ARB_REQ_STATUS0 0x00000854
+#define BNX2_MISC_ARB_REQ_STATUS1 0x00000858
+#define BNX2_MISC_ARB_REQ_STATUS2 0x0000085c
+#define BNX2_MISC_ARB_REQ_STATUS3 0x00000860
+#define BNX2_MISC_ARB_REQ_STATUS4 0x00000864
+#define BNX2_MISC_ARB_GNT0 0x00000868
+#define BNX2_MISC_ARB_GNT0_0 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT0_1 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT0_2 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT0_3 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT0_4 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT0_5 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT0_6 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT0_7 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT1 0x0000086c
+#define BNX2_MISC_ARB_GNT1_8 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT1_9 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT1_10 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT1_11 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT1_12 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT1_13 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT1_14 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT1_15 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT2 0x00000870
+#define BNX2_MISC_ARB_GNT2_16 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT2_17 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT2_18 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT2_19 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT2_20 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT2_21 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT2_22 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT2_23 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT3 0x00000874
+#define BNX2_MISC_ARB_GNT3_24 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT3_25 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT3_26 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT3_27 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT3_28 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT3_29 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT3_30 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT3_31 (0x7L<<28)
+
+#define BNX2_MISC_PRBS_CONTROL 0x00000878
+#define BNX2_MISC_PRBS_CONTROL_EN (1L<<0)
+#define BNX2_MISC_PRBS_CONTROL_RSTB (1L<<1)
+#define BNX2_MISC_PRBS_CONTROL_INV (1L<<2)
+#define BNX2_MISC_PRBS_CONTROL_ERR_CLR (1L<<3)
+#define BNX2_MISC_PRBS_CONTROL_ORDER (0x3L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_7TH (0L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_15TH (1L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_23RD (2L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_31ST (3L<<4)
+
+#define BNX2_MISC_PRBS_STATUS 0x0000087c
+#define BNX2_MISC_PRBS_STATUS_LOCK (1L<<0)
+#define BNX2_MISC_PRBS_STATUS_STKY (1L<<1)
+#define BNX2_MISC_PRBS_STATUS_ERRORS (0x3fffL<<2)
+#define BNX2_MISC_PRBS_STATUS_STATE (0xfL<<16)
+
+#define BNX2_MISC_SM_ASF_CONTROL 0x00000880
+#define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0)
+#define BNX2_MISC_SM_ASF_CONTROL_TSC_EN (1L<<1)
+#define BNX2_MISC_SM_ASF_CONTROL_WG_TO (1L<<2)
+#define BNX2_MISC_SM_ASF_CONTROL_HB_TO (1L<<3)
+#define BNX2_MISC_SM_ASF_CONTROL_PA_TO (1L<<4)
+#define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5)
+#define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7)
+#define BNX2_MISC_SM_ASF_CONTROL_RES (0xfL<<8)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x3fL<<16)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x3fL<<24)
+#define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31)
+
+#define BNX2_MISC_SMB_IN 0x00000884
+#define BNX2_MISC_SMB_IN_DAT_IN (0xffL<<0)
+#define BNX2_MISC_SMB_IN_RDY (1L<<8)
+#define BNX2_MISC_SMB_IN_DONE (1L<<9)
+#define BNX2_MISC_SMB_IN_FIRSTBYTE (1L<<10)
+#define BNX2_MISC_SMB_IN_STATUS (0x7L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_OK (0x0L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_PEC (0x1L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_OFLOW (0x2L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_STOP (0x3L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_TIMEOUT (0x4L<<11)
+
+#define BNX2_MISC_SMB_OUT 0x00000888
+#define BNX2_MISC_SMB_OUT_DAT_OUT (0xffL<<0)
+#define BNX2_MISC_SMB_OUT_RDY (1L<<8)
+#define BNX2_MISC_SMB_OUT_START (1L<<9)
+#define BNX2_MISC_SMB_OUT_LAST (1L<<10)
+#define BNX2_MISC_SMB_OUT_ACC_TYPE (1L<<11)
+#define BNX2_MISC_SMB_OUT_ENB_PEC (1L<<12)
+#define BNX2_MISC_SMB_OUT_GET_RX_LEN (1L<<13)
+#define BNX2_MISC_SMB_OUT_SMB_READ_LEN (0x3fL<<14)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (0x6L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN (1L<<27)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN (1L<<28)
+
+#define BNX2_MISC_SMB_WATCHDOG 0x0000088c
+#define BNX2_MISC_SMB_WATCHDOG_WATCHDOG (0xffffL<<0)
+
+#define BNX2_MISC_SMB_HEARTBEAT 0x00000890
+#define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT (0xffffL<<0)
+
+#define BNX2_MISC_SMB_POLL_ASF 0x00000894
+#define BNX2_MISC_SMB_POLL_ASF_POLL_ASF (0xffffL<<0)
+
+#define BNX2_MISC_SMB_POLL_LEGACY 0x00000898
+#define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY (0xffffL<<0)
+
+#define BNX2_MISC_SMB_RETRAN 0x0000089c
+#define BNX2_MISC_SMB_RETRAN_RETRAN (0xffL<<0)
+
+#define BNX2_MISC_SMB_TIMESTAMP 0x000008a0
+#define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP (0xffffffffL<<0)
+
+#define BNX2_MISC_PERR_ENA0 0x000008a4
+#define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC (1L<<0)
+#define BNX2_MISC_PERR_ENA0_COM_MISC_REGF (1L<<1)
+#define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD (1L<<2)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC (1L<<3)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_REGF (1L<<4)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD (1L<<5)
+#define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM (1L<<6)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0 (1L<<7)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1 (1L<<8)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2 (1L<<9)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3 (1L<<10)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4 (1L<<11)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5 (1L<<12)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL (1L<<13)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0 (1L<<14)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1 (1L<<15)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2 (1L<<16)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3 (1L<<17)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4 (1L<<18)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0 (1L<<19)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1 (1L<<20)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2 (1L<<21)
+#define BNX2_MISC_PERR_ENA0_HC_MISC_DMA (1L<<22)
+#define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF (1L<<23)
+#define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD (1L<<24)
+#define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX (1L<<25)
+#define BNX2_MISC_PERR_ENA0_RBDC_MISC (1L<<26)
+#define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB (1L<<27)
+#define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR (1L<<28)
+#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29)
+#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30)
+#define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31)
+
+#define BNX2_MISC_PERR_ENA1 0x000008a8
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0)
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM (1L<<1)
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM (1L<<2)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC (1L<<3)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF (1L<<4)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD (1L<<5)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC (1L<<6)
+#define BNX2_MISC_PERR_ENA1_TBDC_MISC (1L<<7)
+#define BNX2_MISC_PERR_ENA1_TDMA_MISC (1L<<8)
+#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0 (1L<<9)
+#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1 (1L<<10)
+#define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF (1L<<11)
+#define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD (1L<<12)
+#define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB (1L<<13)
+#define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR (1L<<14)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC (1L<<15)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF (1L<<16)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD (1L<<17)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX (1L<<18)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX (1L<<19)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_RX (1L<<20)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_TX (1L<<21)
+#define BNX2_MISC_PERR_ENA1_RDMAQ_MISC (1L<<22)
+#define BNX2_MISC_PERR_ENA1_CSQ_MISC (1L<<23)
+#define BNX2_MISC_PERR_ENA1_CPQ_MISC (1L<<24)
+#define BNX2_MISC_PERR_ENA1_MCPQ_MISC (1L<<25)
+#define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC (1L<<26)
+#define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC (1L<<27)
+#define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC (1L<<28)
+#define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29)
+#define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30)
+#define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31)
+
+#define BNX2_MISC_PERR_ENA2 0x000008ac
+#define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0)
+#define BNX2_MISC_PERR_ENA2_COMXQ_MISC (1L<<1)
+#define BNX2_MISC_PERR_ENA2_COMTQ_MISC (1L<<2)
+#define BNX2_MISC_PERR_ENA2_TSCHQ_MISC (1L<<3)
+#define BNX2_MISC_PERR_ENA2_TBDRQ_MISC (1L<<4)
+#define BNX2_MISC_PERR_ENA2_TXPQ_MISC (1L<<5)
+#define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6)
+#define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7)
+#define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8)
+
+#define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0
+#define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0)
+#define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12)
+
+#define BNX2_MISC_VREG_CONTROL 0x000008b4
+#define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0)
+#define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4)
+
+#define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8
+#define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6)
+
+#define BNX2_MISC_UNUSED0 0x000008bc
+
+
+/*
+ * nvm_reg definition
+ * offset: 0x6400
+ */
+#define BNX2_NVM_COMMAND 0x00006400
+#define BNX2_NVM_COMMAND_RST (1L<<0)
+#define BNX2_NVM_COMMAND_DONE (1L<<3)
+#define BNX2_NVM_COMMAND_DOIT (1L<<4)
+#define BNX2_NVM_COMMAND_WR (1L<<5)
+#define BNX2_NVM_COMMAND_ERASE (1L<<6)
+#define BNX2_NVM_COMMAND_FIRST (1L<<7)
+#define BNX2_NVM_COMMAND_LAST (1L<<8)
+#define BNX2_NVM_COMMAND_WREN (1L<<16)
+#define BNX2_NVM_COMMAND_WRDI (1L<<17)
+#define BNX2_NVM_COMMAND_EWSR (1L<<18)
+#define BNX2_NVM_COMMAND_WRSR (1L<<19)
+
+#define BNX2_NVM_STATUS 0x00006404
+#define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0)
+#define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4)
+#define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8)
+
+#define BNX2_NVM_WRITE 0x00006408
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_ADDR 0x0000640c
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_READ 0x00006410
+#define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_CFG1 0x00006414
+#define BNX2_NVM_CFG1_FLASH_MODE (1L<<0)
+#define BNX2_NVM_CFG1_BUFFER_MODE (1L<<1)
+#define BNX2_NVM_CFG1_PASS_MODE (1L<<2)
+#define BNX2_NVM_CFG1_BITBANG_MODE (1L<<3)
+#define BNX2_NVM_CFG1_STATUS_BIT (0x7L<<4)
+#define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4)
+#define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4)
+#define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7)
+#define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11)
+#define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24)
+#define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25)
+#define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31)
+
+#define BNX2_NVM_CFG2 0x00006418
+#define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0)
+#define BNX2_NVM_CFG2_DUMMY (0xffL<<8)
+#define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16)
+
+#define BNX2_NVM_CFG3 0x0000641c
+#define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0)
+#define BNX2_NVM_CFG3_WRITE_CMD (0xffL<<8)
+#define BNX2_NVM_CFG3_BUFFER_WRITE_CMD (0xffL<<16)
+#define BNX2_NVM_CFG3_READ_CMD (0xffL<<24)
+
+#define BNX2_NVM_SW_ARB 0x00006420
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET0 (1L<<0)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET2 (1L<<2)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET3 (1L<<3)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR0 (1L<<4)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7)
+#define BNX2_NVM_SW_ARB_ARB_ARB0 (1L<<8)
+#define BNX2_NVM_SW_ARB_ARB_ARB1 (1L<<9)
+#define BNX2_NVM_SW_ARB_ARB_ARB2 (1L<<10)
+#define BNX2_NVM_SW_ARB_ARB_ARB3 (1L<<11)
+#define BNX2_NVM_SW_ARB_REQ0 (1L<<12)
+#define BNX2_NVM_SW_ARB_REQ1 (1L<<13)
+#define BNX2_NVM_SW_ARB_REQ2 (1L<<14)
+#define BNX2_NVM_SW_ARB_REQ3 (1L<<15)
+
+#define BNX2_NVM_ACCESS_ENABLE 0x00006424
+#define BNX2_NVM_ACCESS_ENABLE_EN (1L<<0)
+#define BNX2_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
+
+#define BNX2_NVM_WRITE1 0x00006428
+#define BNX2_NVM_WRITE1_WREN_CMD (0xffL<<0)
+#define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8)
+#define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16)
+
+
+
+/*
+ * dma_reg definition
+ * offset: 0xc00
+ */
+#define BNX2_DMA_COMMAND 0x00000c00
+#define BNX2_DMA_COMMAND_ENABLE (1L<<0)
+
+#define BNX2_DMA_STATUS 0x00000c04
+#define BNX2_DMA_STATUS_PAR_ERROR_STATE (1L<<0)
+#define BNX2_DMA_STATUS_READ_TRANSFERS_STAT (1L<<16)
+#define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT (1L<<17)
+#define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT (1L<<18)
+#define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT (1L<<19)
+#define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT (1L<<20)
+#define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT (1L<<21)
+#define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT (1L<<22)
+#define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23)
+#define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24)
+#define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25)
+
+#define BNX2_DMA_CONFIG 0x00000c08
+#define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0)
+#define BNX2_DMA_CONFIG_DATA_WORD_SWAP (1L<<1)
+#define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP (1L<<4)
+#define BNX2_DMA_CONFIG_CNTL_WORD_SWAP (1L<<5)
+#define BNX2_DMA_CONFIG_ONE_DMA (1L<<6)
+#define BNX2_DMA_CONFIG_CNTL_TWO_DMA (1L<<7)
+#define BNX2_DMA_CONFIG_CNTL_FPGA_MODE (1L<<8)
+#define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA (1L<<10)
+#define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY (1L<<11)
+#define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE (0xfL<<12)
+#define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE (0xfL<<16)
+#define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS (0x7L<<20)
+#define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP (1L<<23)
+#define BNX2_DMA_CONFIG_BIG_SIZE (0xfL<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_NONE (0x0L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_64 (0x1L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24)
+
+#define BNX2_DMA_BLACKOUT 0x00000c0c
+#define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0)
+#define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8)
+#define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16)
+
+#define BNX2_DMA_RCHAN_STAT 0x00000c30
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_0 (0x7L<<0)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_0 (1L<<3)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_1 (0x7L<<4)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_1 (1L<<7)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_2 (0x7L<<8)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_2 (1L<<11)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_3 (0x7L<<12)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_3 (1L<<15)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_4 (0x7L<<16)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_4 (1L<<19)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_5 (0x7L<<20)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_5 (1L<<23)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_6 (0x7L<<24)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_6 (1L<<27)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_7 (0x7L<<28)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_7 (1L<<31)
+
+#define BNX2_DMA_WCHAN_STAT 0x00000c34
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_0 (0x7L<<0)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_0 (1L<<3)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_1 (0x7L<<4)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_1 (1L<<7)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_2 (0x7L<<8)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_2 (1L<<11)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_3 (0x7L<<12)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_3 (1L<<15)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_4 (0x7L<<16)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_4 (1L<<19)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_5 (0x7L<<20)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_5 (1L<<23)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_6 (0x7L<<24)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_6 (1L<<27)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_7 (0x7L<<28)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_7 (1L<<31)
+
+#define BNX2_DMA_RCHAN_ASSIGNMENT 0x00000c38
+#define BNX2_DMA_RCHAN_ASSIGNMENT_0 (0xfL<<0)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_1 (0xfL<<4)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_2 (0xfL<<8)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_3 (0xfL<<12)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_4 (0xfL<<16)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_5 (0xfL<<20)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_6 (0xfL<<24)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_7 (0xfL<<28)
+
+#define BNX2_DMA_WCHAN_ASSIGNMENT 0x00000c3c
+#define BNX2_DMA_WCHAN_ASSIGNMENT_0 (0xfL<<0)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_1 (0xfL<<4)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_2 (0xfL<<8)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_3 (0xfL<<12)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_4 (0xfL<<16)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_5 (0xfL<<20)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_6 (0xfL<<24)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_7 (0xfL<<28)
+
+#define BNX2_DMA_RCHAN_STAT_00 0x00000c40
+#define BNX2_DMA_RCHAN_STAT_00_RCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+#define BNX2_DMA_RCHAN_STAT_01 0x00000c44
+#define BNX2_DMA_RCHAN_STAT_01_RCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+#define BNX2_DMA_RCHAN_STAT_02 0x00000c48
+#define BNX2_DMA_RCHAN_STAT_02_LENGTH (0xffffL<<0)
+#define BNX2_DMA_RCHAN_STAT_02_WORD_SWAP (1L<<16)
+#define BNX2_DMA_RCHAN_STAT_02_BYTE_SWAP (1L<<17)
+#define BNX2_DMA_RCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+#define BNX2_DMA_RCHAN_STAT_10 0x00000c4c
+#define BNX2_DMA_RCHAN_STAT_11 0x00000c50
+#define BNX2_DMA_RCHAN_STAT_12 0x00000c54
+#define BNX2_DMA_RCHAN_STAT_20 0x00000c58
+#define BNX2_DMA_RCHAN_STAT_21 0x00000c5c
+#define BNX2_DMA_RCHAN_STAT_22 0x00000c60
+#define BNX2_DMA_RCHAN_STAT_30 0x00000c64
+#define BNX2_DMA_RCHAN_STAT_31 0x00000c68
+#define BNX2_DMA_RCHAN_STAT_32 0x00000c6c
+#define BNX2_DMA_RCHAN_STAT_40 0x00000c70
+#define BNX2_DMA_RCHAN_STAT_41 0x00000c74
+#define BNX2_DMA_RCHAN_STAT_42 0x00000c78
+#define BNX2_DMA_RCHAN_STAT_50 0x00000c7c
+#define BNX2_DMA_RCHAN_STAT_51 0x00000c80
+#define BNX2_DMA_RCHAN_STAT_52 0x00000c84
+#define BNX2_DMA_RCHAN_STAT_60 0x00000c88
+#define BNX2_DMA_RCHAN_STAT_61 0x00000c8c
+#define BNX2_DMA_RCHAN_STAT_62 0x00000c90
+#define BNX2_DMA_RCHAN_STAT_70 0x00000c94
+#define BNX2_DMA_RCHAN_STAT_71 0x00000c98
+#define BNX2_DMA_RCHAN_STAT_72 0x00000c9c
+#define BNX2_DMA_WCHAN_STAT_00 0x00000ca0
+#define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+#define BNX2_DMA_WCHAN_STAT_01 0x00000ca4
+#define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+#define BNX2_DMA_WCHAN_STAT_02 0x00000ca8
+#define BNX2_DMA_WCHAN_STAT_02_LENGTH (0xffffL<<0)
+#define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP (1L<<16)
+#define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP (1L<<17)
+#define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+#define BNX2_DMA_WCHAN_STAT_10 0x00000cac
+#define BNX2_DMA_WCHAN_STAT_11 0x00000cb0
+#define BNX2_DMA_WCHAN_STAT_12 0x00000cb4
+#define BNX2_DMA_WCHAN_STAT_20 0x00000cb8
+#define BNX2_DMA_WCHAN_STAT_21 0x00000cbc
+#define BNX2_DMA_WCHAN_STAT_22 0x00000cc0
+#define BNX2_DMA_WCHAN_STAT_30 0x00000cc4
+#define BNX2_DMA_WCHAN_STAT_31 0x00000cc8
+#define BNX2_DMA_WCHAN_STAT_32 0x00000ccc
+#define BNX2_DMA_WCHAN_STAT_40 0x00000cd0
+#define BNX2_DMA_WCHAN_STAT_41 0x00000cd4
+#define BNX2_DMA_WCHAN_STAT_42 0x00000cd8
+#define BNX2_DMA_WCHAN_STAT_50 0x00000cdc
+#define BNX2_DMA_WCHAN_STAT_51 0x00000ce0
+#define BNX2_DMA_WCHAN_STAT_52 0x00000ce4
+#define BNX2_DMA_WCHAN_STAT_60 0x00000ce8
+#define BNX2_DMA_WCHAN_STAT_61 0x00000cec
+#define BNX2_DMA_WCHAN_STAT_62 0x00000cf0
+#define BNX2_DMA_WCHAN_STAT_70 0x00000cf4
+#define BNX2_DMA_WCHAN_STAT_71 0x00000cf8
+#define BNX2_DMA_WCHAN_STAT_72 0x00000cfc
+#define BNX2_DMA_ARB_STAT_00 0x00000d00
+#define BNX2_DMA_ARB_STAT_00_MASTER (0xffffL<<0)
+#define BNX2_DMA_ARB_STAT_00_MASTER_ENC (0xffL<<16)
+#define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR (0xffL<<24)
+
+#define BNX2_DMA_ARB_STAT_01 0x00000d04
+#define BNX2_DMA_ARB_STAT_01_LPR_RPTR (0xfL<<0)
+#define BNX2_DMA_ARB_STAT_01_LPR_WPTR (0xfL<<4)
+#define BNX2_DMA_ARB_STAT_01_LPB_RPTR (0xfL<<8)
+#define BNX2_DMA_ARB_STAT_01_LPB_WPTR (0xfL<<12)
+#define BNX2_DMA_ARB_STAT_01_HPR_RPTR (0xfL<<16)
+#define BNX2_DMA_ARB_STAT_01_HPR_WPTR (0xfL<<20)
+#define BNX2_DMA_ARB_STAT_01_HPB_RPTR (0xfL<<24)
+#define BNX2_DMA_ARB_STAT_01_HPB_WPTR (0xfL<<28)
+
+#define BNX2_DMA_FUSE_CTRL0_CMD 0x00000f00
+#define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL0_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL0_DATA 0x00000f04
+#define BNX2_DMA_FUSE_CTRL1_CMD 0x00000f08
+#define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL1_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL1_DATA 0x00000f0c
+#define BNX2_DMA_FUSE_CTRL2_CMD 0x00000f10
+#define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL2_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL2_DATA 0x00000f14
+
+
+/*
+ * context_reg definition
+ * offset: 0x1000
+ */
+#define BNX2_CTX_COMMAND 0x00001000
+#define BNX2_CTX_COMMAND_ENABLED (1L<<0)
+
+#define BNX2_CTX_STATUS 0x00001004
+#define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0)
+#define BNX2_CTX_STATUS_READ_STAT (1L<<16)
+#define BNX2_CTX_STATUS_WRITE_STAT (1L<<17)
+#define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18)
+#define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19)
+
+#define BNX2_CTX_VIRT_ADDR 0x00001008
+#define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6)
+
+#define BNX2_CTX_PAGE_TBL 0x0000100c
+#define BNX2_CTX_PAGE_TBL_PAGE_TBL (0x3fffL<<6)
+
+#define BNX2_CTX_DATA_ADR 0x00001010
+#define BNX2_CTX_DATA_ADR_DATA_ADR (0x7ffffL<<2)
+
+#define BNX2_CTX_DATA 0x00001014
+#define BNX2_CTX_LOCK 0x00001018
+#define BNX2_CTX_LOCK_TYPE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0)
+#define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7)
+#define BNX2_CTX_LOCK_GRANTED (1L<<26)
+#define BNX2_CTX_LOCK_MODE (0x7L<<27)
+#define BNX2_CTX_LOCK_MODE_UNLOCK (0x0L<<27)
+#define BNX2_CTX_LOCK_MODE_IMMEDIATE (0x1L<<27)
+#define BNX2_CTX_LOCK_MODE_SURE (0x2L<<27)
+#define BNX2_CTX_LOCK_STATUS (1L<<30)
+#define BNX2_CTX_LOCK_REQ (1L<<31)
+
+#define BNX2_CTX_ACCESS_STATUS 0x00001040
+#define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0)
+#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10)
+#define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12)
+#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14)
+#define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17)
+
+#define BNX2_CTX_DBG_LOCK_STATUS 0x00001044
+#define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0)
+#define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22)
+
+#define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16)
+
+#define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084
+#define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088
+#define BNX2_CTX_CHNL_LOCK_STATUS_3 0x0000108c
+#define BNX2_CTX_CHNL_LOCK_STATUS_4 0x00001090
+#define BNX2_CTX_CHNL_LOCK_STATUS_5 0x00001094
+#define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098
+#define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c
+#define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0
+
+
+/*
+ * emac_reg definition
+ * offset: 0x1400
+ */
+#define BNX2_EMAC_MODE 0x00001400
+#define BNX2_EMAC_MODE_RESET (1L<<0)
+#define BNX2_EMAC_MODE_HALF_DUPLEX (1L<<1)
+#define BNX2_EMAC_MODE_PORT (0x3L<<2)
+#define BNX2_EMAC_MODE_PORT_NONE (0L<<2)
+#define BNX2_EMAC_MODE_PORT_MII (1L<<2)
+#define BNX2_EMAC_MODE_PORT_GMII (2L<<2)
+#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2)
+#define BNX2_EMAC_MODE_MAC_LOOP (1L<<4)
+#define BNX2_EMAC_MODE_25G (1L<<5)
+#define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7)
+#define BNX2_EMAC_MODE_TX_BURST (1L<<8)
+#define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9)
+#define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10)
+#define BNX2_EMAC_MODE_FORCE_LINK (1L<<11)
+#define BNX2_EMAC_MODE_MPKT (1L<<18)
+#define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19)
+#define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20)
+
+#define BNX2_EMAC_STATUS 0x00001404
+#define BNX2_EMAC_STATUS_LINK (1L<<11)
+#define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12)
+#define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22)
+#define BNX2_EMAC_STATUS_MI_INT (1L<<23)
+#define BNX2_EMAC_STATUS_AP_ERROR (1L<<24)
+#define BNX2_EMAC_STATUS_PARITY_ERROR_STATE (1L<<31)
+
+#define BNX2_EMAC_ATTENTION_ENA 0x00001408
+#define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11)
+#define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22)
+#define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23)
+#define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24)
+
+#define BNX2_EMAC_LED 0x0000140c
+#define BNX2_EMAC_LED_OVERRIDE (1L<<0)
+#define BNX2_EMAC_LED_1000MB_OVERRIDE (1L<<1)
+#define BNX2_EMAC_LED_100MB_OVERRIDE (1L<<2)
+#define BNX2_EMAC_LED_10MB_OVERRIDE (1L<<3)
+#define BNX2_EMAC_LED_TRAFFIC_OVERRIDE (1L<<4)
+#define BNX2_EMAC_LED_BLNK_TRAFFIC (1L<<5)
+#define BNX2_EMAC_LED_TRAFFIC (1L<<6)
+#define BNX2_EMAC_LED_1000MB (1L<<7)
+#define BNX2_EMAC_LED_100MB (1L<<8)
+#define BNX2_EMAC_LED_10MB (1L<<9)
+#define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10)
+#define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19)
+#define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31)
+
+#define BNX2_EMAC_MAC_MATCH0 0x00001410
+#define BNX2_EMAC_MAC_MATCH1 0x00001414
+#define BNX2_EMAC_MAC_MATCH2 0x00001418
+#define BNX2_EMAC_MAC_MATCH3 0x0000141c
+#define BNX2_EMAC_MAC_MATCH4 0x00001420
+#define BNX2_EMAC_MAC_MATCH5 0x00001424
+#define BNX2_EMAC_MAC_MATCH6 0x00001428
+#define BNX2_EMAC_MAC_MATCH7 0x0000142c
+#define BNX2_EMAC_MAC_MATCH8 0x00001430
+#define BNX2_EMAC_MAC_MATCH9 0x00001434
+#define BNX2_EMAC_MAC_MATCH10 0x00001438
+#define BNX2_EMAC_MAC_MATCH11 0x0000143c
+#define BNX2_EMAC_MAC_MATCH12 0x00001440
+#define BNX2_EMAC_MAC_MATCH13 0x00001444
+#define BNX2_EMAC_MAC_MATCH14 0x00001448
+#define BNX2_EMAC_MAC_MATCH15 0x0000144c
+#define BNX2_EMAC_MAC_MATCH16 0x00001450
+#define BNX2_EMAC_MAC_MATCH17 0x00001454
+#define BNX2_EMAC_MAC_MATCH18 0x00001458
+#define BNX2_EMAC_MAC_MATCH19 0x0000145c
+#define BNX2_EMAC_MAC_MATCH20 0x00001460
+#define BNX2_EMAC_MAC_MATCH21 0x00001464
+#define BNX2_EMAC_MAC_MATCH22 0x00001468
+#define BNX2_EMAC_MAC_MATCH23 0x0000146c
+#define BNX2_EMAC_MAC_MATCH24 0x00001470
+#define BNX2_EMAC_MAC_MATCH25 0x00001474
+#define BNX2_EMAC_MAC_MATCH26 0x00001478
+#define BNX2_EMAC_MAC_MATCH27 0x0000147c
+#define BNX2_EMAC_MAC_MATCH28 0x00001480
+#define BNX2_EMAC_MAC_MATCH29 0x00001484
+#define BNX2_EMAC_MAC_MATCH30 0x00001488
+#define BNX2_EMAC_MAC_MATCH31 0x0000148c
+#define BNX2_EMAC_BACKOFF_SEED 0x00001498
+#define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED (0x3ffL<<0)
+
+#define BNX2_EMAC_RX_MTU_SIZE 0x0000149c
+#define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE (0xffffL<<0)
+#define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31)
+
+#define BNX2_EMAC_SERDES_CNTL 0x000014a4
+#define BNX2_EMAC_SERDES_CNTL_RXR (0x7L<<0)
+#define BNX2_EMAC_SERDES_CNTL_RXG (0x3L<<3)
+#define BNX2_EMAC_SERDES_CNTL_RXCKSEL (1L<<6)
+#define BNX2_EMAC_SERDES_CNTL_TXBIAS (0x7L<<7)
+#define BNX2_EMAC_SERDES_CNTL_BGMAX (1L<<10)
+#define BNX2_EMAC_SERDES_CNTL_BGMIN (1L<<11)
+#define BNX2_EMAC_SERDES_CNTL_TXMODE (1L<<12)
+#define BNX2_EMAC_SERDES_CNTL_TXEDGE (1L<<13)
+#define BNX2_EMAC_SERDES_CNTL_SERDES_MODE (1L<<14)
+#define BNX2_EMAC_SERDES_CNTL_PLLTEST (1L<<15)
+#define BNX2_EMAC_SERDES_CNTL_CDET_EN (1L<<16)
+#define BNX2_EMAC_SERDES_CNTL_TBI_LBK (1L<<17)
+#define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK (1L<<18)
+#define BNX2_EMAC_SERDES_CNTL_REV_PHASE (1L<<19)
+#define BNX2_EMAC_SERDES_CNTL_REGCTL12 (0x3L<<20)
+#define BNX2_EMAC_SERDES_CNTL_REGCTL25 (0x3L<<22)
+
+#define BNX2_EMAC_SERDES_STATUS 0x000014a8
+#define BNX2_EMAC_SERDES_STATUS_RX_STAT (0xffL<<0)
+#define BNX2_EMAC_SERDES_STATUS_COMMA_DET (1L<<8)
+
+#define BNX2_EMAC_MDIO_COMM 0x000014ac
+#define BNX2_EMAC_MDIO_COMM_DATA (0xffffL<<0)
+#define BNX2_EMAC_MDIO_COMM_REG_ADDR (0x1fL<<16)
+#define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21)
+#define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26)
+#define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28)
+#define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29)
+#define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30)
+
+#define BNX2_EMAC_MDIO_STATUS 0x000014b0
+#define BNX2_EMAC_MDIO_STATUS_LINK (1L<<0)
+#define BNX2_EMAC_MDIO_STATUS_10MB (1L<<1)
+
+#define BNX2_EMAC_MDIO_MODE 0x000014b4
+#define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE (1L<<1)
+#define BNX2_EMAC_MDIO_MODE_AUTO_POLL (1L<<4)
+#define BNX2_EMAC_MDIO_MODE_BIT_BANG (1L<<8)
+#define BNX2_EMAC_MDIO_MODE_MDIO (1L<<9)
+#define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10)
+#define BNX2_EMAC_MDIO_MODE_MDC (1L<<11)
+#define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12)
+#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16)
+
+#define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8
+#define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0)
+
+#define BNX2_EMAC_TX_MODE 0x000014bc
+#define BNX2_EMAC_TX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3)
+#define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4)
+#define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5)
+#define BNX2_EMAC_TX_MODE_LONG_PAUSE (1L<<6)
+#define BNX2_EMAC_TX_MODE_LINK_AWARE (1L<<7)
+
+#define BNX2_EMAC_TX_STATUS 0x000014c0
+#define BNX2_EMAC_TX_STATUS_XOFFED (1L<<0)
+#define BNX2_EMAC_TX_STATUS_XOFF_SENT (1L<<1)
+#define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2)
+#define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3)
+#define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4)
+
+#define BNX2_EMAC_TX_LENGTHS 0x000014c4
+#define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0)
+#define BNX2_EMAC_TX_LENGTHS_IPG (0xfL<<8)
+#define BNX2_EMAC_TX_LENGTHS_IPG_CRS (0x3L<<12)
+
+#define BNX2_EMAC_RX_MODE 0x000014c8
+#define BNX2_EMAC_RX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2)
+#define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3)
+#define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4)
+#define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5)
+#define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6)
+#define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7)
+#define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8)
+#define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9)
+#define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10)
+#define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11)
+#define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12)
+
+#define BNX2_EMAC_RX_STATUS 0x000014cc
+#define BNX2_EMAC_RX_STATUS_FFED (1L<<0)
+#define BNX2_EMAC_RX_STATUS_FF_RECEIVED (1L<<1)
+#define BNX2_EMAC_RX_STATUS_N_RECEIVED (1L<<2)
+
+#define BNX2_EMAC_MULTICAST_HASH0 0x000014d0
+#define BNX2_EMAC_MULTICAST_HASH1 0x000014d4
+#define BNX2_EMAC_MULTICAST_HASH2 0x000014d8
+#define BNX2_EMAC_MULTICAST_HASH3 0x000014dc
+#define BNX2_EMAC_MULTICAST_HASH4 0x000014e0
+#define BNX2_EMAC_MULTICAST_HASH5 0x000014e4
+#define BNX2_EMAC_MULTICAST_HASH6 0x000014e8
+#define BNX2_EMAC_MULTICAST_HASH7 0x000014ec
+#define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500
+#define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504
+#define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508
+#define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS 0x0000150c
+#define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS 0x00001510
+#define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS 0x00001514
+#define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS 0x00001518
+#define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS 0x0000151c
+#define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS 0x00001520
+#define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED 0x00001524
+#define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED 0x00001528
+#define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED 0x0000152c
+#define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED 0x00001530
+#define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG 0x00001534
+#define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS 0x00001538
+#define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS 0x0000153c
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS 0x00001540
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x00001544
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001548
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001558
+#define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c
+#define BNX2_EMAC_RXMAC_DEBUG1 0x00001560
+#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE (1L<<1)
+#define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC (1L<<2)
+#define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR (1L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR (1L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA (1L<<5)
+#define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START (1L<<6)
+#define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT (0xffffL<<7)
+#define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME (0xffL<<23)
+
+#define BNX2_EMAC_RXMAC_DEBUG2 0x00001564
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD (0x1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA (0x2L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP (0x3L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT (0x4L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP (0x5L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP (0x6L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE (0xfL<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE (0x0L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0 (0x1L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1 (0x2L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2 (0x3L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3 (0x4L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT (0x5L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT (0x6L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS (0x7L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST (0x8L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN (0xffL<<7)
+#define BNX2_EMAC_RXMAC_DEBUG2_FALSEC (1L<<15)
+#define BNX2_EMAC_RXMAC_DEBUG2_TAGGED (1L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE (1L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE (0L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED (1L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER (0xfL<<19)
+#define BNX2_EMAC_RXMAC_DEBUG2_QUANTA (0x1fL<<23)
+
+#define BNX2_EMAC_RXMAC_DEBUG3 0x00001568
+#define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR (0xffffL<<0)
+#define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR (0xffffL<<16)
+
+#define BNX2_EMAC_RXMAC_DEBUG4 0x0000156c
+#define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD (0xffffL<<0)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE (0x3fL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE (0x0L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3 (0xaL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1 (0xeL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2 (0xfL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK (0x10L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC (0x11L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2 (0x12L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3 (0x13L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1 (0x14L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2 (0x15L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3 (0x16L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE (0x17L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC (0x18L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE (0x19L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD (0x1aL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC (0x1bL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH (0x1cL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF (0x1dL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON (0x1eL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED (0x1fL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED (0x20L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE (0x21L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL (0x22L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1 (0x23L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2 (0x24L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3 (0x25L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE (0x26L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE (0x27L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL (0x28L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE (0x29L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP (0x2aL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT (1L<<22)
+#define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23)
+#define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24)
+#define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25)
+#define BNX2_EMAC_RXMAC_DEBUG4_sfd_FOUND (1L<<26)
+#define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27)
+#define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28)
+
+#define BNX2_EMAC_RXMAC_DEBUG5 0x00001570
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE (0L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF (1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT (2L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC (3L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE (4L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL (5L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT (6L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1 (0x7L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW (0x0L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT (0x1L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF (0x2L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF (0x3L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF (0x4L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF (0x6L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF (0x7L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED (1L<<7)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0 (0x7L<<8)
+#define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL (1L<<11)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE (1L<<12)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA (1L<<13)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT (1L<<14)
+#define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT (1L<<15)
+#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE (0x3L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19)
+#define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20)
+
+#define BNX2_EMAC_RX_STAT_AC0 0x00001580
+#define BNX2_EMAC_RX_STAT_AC1 0x00001584
+#define BNX2_EMAC_RX_STAT_AC2 0x00001588
+#define BNX2_EMAC_RX_STAT_AC3 0x0000158c
+#define BNX2_EMAC_RX_STAT_AC4 0x00001590
+#define BNX2_EMAC_RX_STAT_AC5 0x00001594
+#define BNX2_EMAC_RX_STAT_AC6 0x00001598
+#define BNX2_EMAC_RX_STAT_AC7 0x0000159c
+#define BNX2_EMAC_RX_STAT_AC8 0x000015a0
+#define BNX2_EMAC_RX_STAT_AC9 0x000015a4
+#define BNX2_EMAC_RX_STAT_AC10 0x000015a8
+#define BNX2_EMAC_RX_STAT_AC11 0x000015ac
+#define BNX2_EMAC_RX_STAT_AC12 0x000015b0
+#define BNX2_EMAC_RX_STAT_AC13 0x000015b4
+#define BNX2_EMAC_RX_STAT_AC14 0x000015b8
+#define BNX2_EMAC_RX_STAT_AC15 0x000015bc
+#define BNX2_EMAC_RX_STAT_AC16 0x000015c0
+#define BNX2_EMAC_RX_STAT_AC17 0x000015c4
+#define BNX2_EMAC_RX_STAT_AC18 0x000015c8
+#define BNX2_EMAC_RX_STAT_AC19 0x000015cc
+#define BNX2_EMAC_RX_STAT_AC20 0x000015d0
+#define BNX2_EMAC_RX_STAT_AC21 0x000015d4
+#define BNX2_EMAC_RX_STAT_AC22 0x000015d8
+#define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc
+#define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600
+#define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604
+#define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608
+#define BNX2_EMAC_TX_STAT_OUTXONSENT 0x0000160c
+#define BNX2_EMAC_TX_STAT_OUTXOFFSENT 0x00001610
+#define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE 0x00001614
+#define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES 0x00001618
+#define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES 0x0000161c
+#define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS 0x00001620
+#define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS 0x00001624
+#define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS 0x00001628
+#define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS 0x0000162c
+#define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS 0x00001630
+#define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS 0x00001634
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS 0x00001638
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x0000163c
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001640
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001650
+#define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654
+#define BNX2_EMAC_TXMAC_DEBUG0 0x00001658
+#define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE (0xfL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0 (0x1L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0 (0x4L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1 (0x5L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2 (0x6L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3 (0x7L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0 (0x8L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1 (0x9L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE (1L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC (1L<<5)
+#define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER (0xfL<<6)
+#define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE (1L<<10)
+#define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION (1L<<11)
+#define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER (1L<<12)
+#define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED (1L<<13)
+#define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE (1L<<14)
+#define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME (0xfL<<15)
+#define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME (0xffL<<19)
+
+#define BNX2_EMAC_TXMAC_DEBUG2 0x00001660
+#define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF (0x3ffL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT (0xffffL<<10)
+#define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT (0x1fL<<26)
+#define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT (1L<<31)
+
+#define BNX2_EMAC_TXMAC_DEBUG3 0x00001664
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE (0xfL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1 (0x1L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2 (0x2L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD (0x3L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA (0x4L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1 (0x5L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2 (0x6L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT (0x7L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB (0x8L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG (0x9L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM (0xaL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM (0xbL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM (0xcL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT (0xdL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF (0xeL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE (0x7L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE (0x0L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT (0x1L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI (0x2L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC (0x3L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2 (0x4L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3 (0x5L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC (0x6L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE (1L<<7)
+#define BNX2_EMAC_TXMAC_DEBUG3_XOFF (1L<<8)
+#define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER (0xfL<<9)
+#define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER (0x1fL<<13)
+
+#define BNX2_EMAC_TXMAC_DEBUG4 0x00001668
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER (0xffffL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE (0xfL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20)
+#define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21)
+#define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22)
+#define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER (1L<<23)
+#define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND (1L<<24)
+#define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING (1L<<25)
+#define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC (1L<<26)
+#define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING (1L<<27)
+#define BNX2_EMAC_TXMAC_DEBUG4_COL_IN (1L<<28)
+#define BNX2_EMAC_TXMAC_DEBUG4_BURSTING (1L<<29)
+#define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE (1L<<30)
+#define BNX2_EMAC_TXMAC_DEBUG4_GO (1L<<31)
+
+#define BNX2_EMAC_TX_STAT_AC0 0x00001680
+#define BNX2_EMAC_TX_STAT_AC1 0x00001684
+#define BNX2_EMAC_TX_STAT_AC2 0x00001688
+#define BNX2_EMAC_TX_STAT_AC3 0x0000168c
+#define BNX2_EMAC_TX_STAT_AC4 0x00001690
+#define BNX2_EMAC_TX_STAT_AC5 0x00001694
+#define BNX2_EMAC_TX_STAT_AC6 0x00001698
+#define BNX2_EMAC_TX_STAT_AC7 0x0000169c
+#define BNX2_EMAC_TX_STAT_AC8 0x000016a0
+#define BNX2_EMAC_TX_STAT_AC9 0x000016a4
+#define BNX2_EMAC_TX_STAT_AC10 0x000016a8
+#define BNX2_EMAC_TX_STAT_AC11 0x000016ac
+#define BNX2_EMAC_TX_STAT_AC12 0x000016b0
+#define BNX2_EMAC_TX_STAT_AC13 0x000016b4
+#define BNX2_EMAC_TX_STAT_AC14 0x000016b8
+#define BNX2_EMAC_TX_STAT_AC15 0x000016bc
+#define BNX2_EMAC_TX_STAT_AC16 0x000016c0
+#define BNX2_EMAC_TX_STAT_AC17 0x000016c4
+#define BNX2_EMAC_TX_STAT_AC18 0x000016c8
+#define BNX2_EMAC_TX_STAT_AC19 0x000016cc
+#define BNX2_EMAC_TX_STAT_AC20 0x000016d0
+#define BNX2_EMAC_TX_STAT_AC21 0x000016d4
+#define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8
+
+
+/*
+ * rpm_reg definition
+ * offset: 0x1800
+ */
+#define BNX2_RPM_COMMAND 0x00001800
+#define BNX2_RPM_COMMAND_ENABLED (1L<<0)
+#define BNX2_RPM_COMMAND_OVERRUN_ABORT (1L<<4)
+
+#define BNX2_RPM_STATUS 0x00001804
+#define BNX2_RPM_STATUS_MBUF_WAIT (1L<<0)
+#define BNX2_RPM_STATUS_FREE_WAIT (1L<<1)
+
+#define BNX2_RPM_CONFIG 0x00001808
+#define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM (1L<<0)
+#define BNX2_RPM_CONFIG_ACPI_ENA (1L<<1)
+#define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2)
+#define BNX2_RPM_CONFIG_MP_KEEP (1L<<3)
+#define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4)
+#define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31)
+
+#define BNX2_RPM_VLAN_MATCH0 0x00001810
+#define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH1 0x00001814
+#define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH2 0x00001818
+#define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH3 0x0000181c
+#define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_SORT_USER0 0x00001820
+#define BNX2_RPM_SORT_USER0_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER0_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER0_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER0_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER0_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER1 0x00001824
+#define BNX2_RPM_SORT_USER1_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER1_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER1_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER1_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER1_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER1_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER1_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER1_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER2 0x00001828
+#define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER2_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER2_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER2_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER3 0x0000182c
+#define BNX2_RPM_SORT_USER3_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER3_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER3_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER3_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER3_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER3_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER3_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER3_ENA (1L<<31)
+
+#define BNX2_RPM_STAT_L2_FILTER_DISCARDS 0x00001840
+#define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS 0x00001844
+#define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848
+#define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c
+#define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850
+#define BNX2_RPM_STAT_AC0 0x00001880
+#define BNX2_RPM_STAT_AC1 0x00001884
+#define BNX2_RPM_STAT_AC2 0x00001888
+#define BNX2_RPM_STAT_AC3 0x0000188c
+#define BNX2_RPM_STAT_AC4 0x00001890
+#define BNX2_RPM_RC_CNTL_0 0x00001900
+#define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_0_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_0_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20)
+#define BNX2_RPM_RC_CNTL_0_MAP (1L<<24)
+#define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_0_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_0_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_0_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_0_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_0_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_0 0x00001904
+#define BNX2_RPM_RC_VALUE_MASK_0_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_0_MASK (0xffffL<<16)
+
+#define BNX2_RPM_RC_CNTL_1 0x00001908
+#define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c
+#define BNX2_RPM_RC_CNTL_2 0x00001910
+#define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_2 0x00001914
+#define BNX2_RPM_RC_CNTL_3 0x00001918
+#define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c
+#define BNX2_RPM_RC_CNTL_4 0x00001920
+#define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_4 0x00001924
+#define BNX2_RPM_RC_CNTL_5 0x00001928
+#define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c
+#define BNX2_RPM_RC_CNTL_6 0x00001930
+#define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_6 0x00001934
+#define BNX2_RPM_RC_CNTL_7 0x00001938
+#define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c
+#define BNX2_RPM_RC_CNTL_8 0x00001940
+#define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_8 0x00001944
+#define BNX2_RPM_RC_CNTL_9 0x00001948
+#define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c
+#define BNX2_RPM_RC_CNTL_10 0x00001950
+#define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_10 0x00001954
+#define BNX2_RPM_RC_CNTL_11 0x00001958
+#define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c
+#define BNX2_RPM_RC_CNTL_12 0x00001960
+#define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_12 0x00001964
+#define BNX2_RPM_RC_CNTL_13 0x00001968
+#define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c
+#define BNX2_RPM_RC_CNTL_14 0x00001970
+#define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_14 0x00001974
+#define BNX2_RPM_RC_CNTL_15 0x00001978
+#define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c
+#define BNX2_RPM_RC_CONFIG 0x00001980
+#define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0)
+#define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24)
+
+#define BNX2_RPM_DEBUG0 0x00001984
+#define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0)
+#define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD (1L<<16)
+#define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD (1L<<17)
+#define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD (1L<<18)
+#define BNX2_RPM_DEBUG0_T_IP_OFST_VLD (1L<<19)
+#define BNX2_RPM_DEBUG0_IP_MORE_FRGMT (1L<<20)
+#define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR (1L<<21)
+#define BNX2_RPM_DEBUG0_LLC_SNAP (1L<<22)
+#define BNX2_RPM_DEBUG0_FM_STARTED (1L<<23)
+#define BNX2_RPM_DEBUG0_DONE (1L<<24)
+#define BNX2_RPM_DEBUG0_WAIT_4_DONE (1L<<25)
+#define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM (1L<<26)
+#define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM (1L<<27)
+#define BNX2_RPM_DEBUG0_IGNORE_VLAN (1L<<28)
+#define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE (1L<<31)
+
+#define BNX2_RPM_DEBUG1 0x00001988
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST (0xffffL<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE (0L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL (1L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC (2L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP (4L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP (8L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START (16L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP (32L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP (64L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP (128L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH (256L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP (512L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD (1024L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA (2048L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY (0x2000L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT (0x4000L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT (0x8000L<<0)
+#define BNX2_RPM_DEBUG1_HDR_BCNT (0x7ffL<<16)
+#define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D (1L<<28)
+#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2 (1L<<29)
+#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1 (1L<<30)
+#define BNX2_RPM_DEBUG1_EOF_0XTRA_WD (1L<<31)
+
+#define BNX2_RPM_DEBUG2 0x0000198c
+#define BNX2_RPM_DEBUG2_CMD_HIT_VEC (0xffffL<<0)
+#define BNX2_RPM_DEBUG2_IP_BCNT (0xffL<<16)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M4 (1L<<24)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M3 (1L<<25)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M2 (1L<<26)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M1 (1L<<27)
+#define BNX2_RPM_DEBUG2_IPIPE_EMPTY (1L<<28)
+#define BNX2_RPM_DEBUG2_FM_DISCARD (1L<<29)
+#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2 (1L<<30)
+#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1 (1L<<31)
+
+#define BNX2_RPM_DEBUG3 0x00001990
+#define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR (0x1ffL<<0)
+#define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT (1L<<9)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT (1L<<10)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT (1L<<11)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ (1L<<12)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ (1L<<13)
+#define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL (1L<<14)
+#define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP (1L<<15)
+#define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT (0xfL<<16)
+#define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL (1L<<21)
+#define BNX2_RPM_DEBUG3_DROP_NXT_VLD (1L<<22)
+#define BNX2_RPM_DEBUG3_DROP_NXT (1L<<23)
+#define BNX2_RPM_DEBUG3_FTQ_FSM (0x3L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE (0x0L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK (0x1L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE (0x2L<<24)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM (0x3L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF (0x0L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF (0x1L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA (0x2L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA (0x3L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF (0x4L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK (0x5L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD (0x6L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE (0x7L<<26)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM (1L<<29)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE (0L<<29)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK (1L<<29)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM (1L<<30)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF (0x0L<<30)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF (0x1L<<30)
+#define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR (1L<<31)
+
+#define BNX2_RPM_DEBUG4 0x00001994
+#define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER (0x1ffffffL<<0)
+#define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE (0x7L<<25)
+#define BNX2_RPM_DEBUG4_MBWRITE_FSM (0x7L<<28)
+#define BNX2_RPM_DEBUG4_DFIFO_EMPTY (1L<<31)
+
+#define BNX2_RPM_DEBUG5 0x00001998
+#define BNX2_RPM_DEBUG5_RDROP_WPTR (0x1fL<<0)
+#define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR (0x1fL<<5)
+#define BNX2_RPM_DEBUG5_RDROP_MC_RPTR (0x1fL<<10)
+#define BNX2_RPM_DEBUG5_RDROP_RC_RPTR (0x1fL<<15)
+#define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY (1L<<20)
+#define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY (1L<<21)
+#define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR (1L<<22)
+#define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT (1L<<23)
+#define BNX2_RPM_DEBUG5_HOLDREG_DISCARD (1L<<24)
+#define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL (1L<<25)
+#define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY (1L<<26)
+#define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY (1L<<27)
+#define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY (1L<<28)
+#define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY (1L<<29)
+#define BNX2_RPM_DEBUG5_HOLDREG_FULL_T (1L<<30)
+#define BNX2_RPM_DEBUG5_HOLDREG_RD (1L<<31)
+
+#define BNX2_RPM_DEBUG6 0x0000199c
+#define BNX2_RPM_DEBUG6_ACPI_VEC (0xffffL<<0)
+#define BNX2_RPM_DEBUG6_VEC (0xffffL<<16)
+
+#define BNX2_RPM_DEBUG7 0x000019a0
+#define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC (0xffffffffL<<0)
+
+#define BNX2_RPM_DEBUG8 0x000019a4
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM (0xfL<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE (0L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR (1L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR (2L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR (3L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF (4L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA (5L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR (6L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR (7L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR (8L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR (9L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF (10L<<0)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_W0 (1L<<4)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA (1L<<5)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT (1L<<6)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3 (1L<<7)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2 (1L<<8)
+#define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES (1L<<9)
+#define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES (1L<<10)
+#define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES (1L<<11)
+#define BNX2_RPM_DEBUG8_EOF_DET (1L<<12)
+#define BNX2_RPM_DEBUG8_SOF_DET (1L<<13)
+#define BNX2_RPM_DEBUG8_WAIT_4_SOF (1L<<14)
+#define BNX2_RPM_DEBUG8_ALL_DONE (1L<<15)
+#define BNX2_RPM_DEBUG8_THBUF_ADDR (0x7fL<<16)
+#define BNX2_RPM_DEBUG8_BYTE_CTR (0xffL<<24)
+
+#define BNX2_RPM_DEBUG9 0x000019a8
+#define BNX2_RPM_DEBUG9_OUTFIFO_COUNT (0x7L<<0)
+#define BNX2_RPM_DEBUG9_RDE_ACPI_RDY (1L<<3)
+#define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT (0x7L<<4)
+#define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED (1L<<28)
+#define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29)
+#define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30)
+#define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31)
+
+#define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0
+#define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4
+#define BNX2_RPM_ACPI_DBG_BUF_W02 0x000019c8
+#define BNX2_RPM_ACPI_DBG_BUF_W03 0x000019cc
+#define BNX2_RPM_ACPI_DBG_BUF_W10 0x000019d0
+#define BNX2_RPM_ACPI_DBG_BUF_W11 0x000019d4
+#define BNX2_RPM_ACPI_DBG_BUF_W12 0x000019d8
+#define BNX2_RPM_ACPI_DBG_BUF_W13 0x000019dc
+#define BNX2_RPM_ACPI_DBG_BUF_W20 0x000019e0
+#define BNX2_RPM_ACPI_DBG_BUF_W21 0x000019e4
+#define BNX2_RPM_ACPI_DBG_BUF_W22 0x000019e8
+#define BNX2_RPM_ACPI_DBG_BUF_W23 0x000019ec
+#define BNX2_RPM_ACPI_DBG_BUF_W30 0x000019f0
+#define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4
+#define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8
+#define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc
+
+
+/*
+ * rbuf_reg definition
+ * offset: 0x200000
+ */
+#define BNX2_RBUF_COMMAND 0x00200000
+#define BNX2_RBUF_COMMAND_ENABLED (1L<<0)
+#define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1)
+#define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2)
+#define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4)
+#define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5)
+
+#define BNX2_RBUF_STATUS1 0x00200004
+#define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0)
+
+#define BNX2_RBUF_STATUS2 0x00200008
+#define BNX2_RBUF_STATUS2_FREE_TAIL (0x3ffL<<0)
+#define BNX2_RBUF_STATUS2_FREE_HEAD (0x3ffL<<16)
+
+#define BNX2_RBUF_CONFIG 0x0020000c
+#define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_FW_BUF_ALLOC 0x00200010
+#define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7)
+
+#define BNX2_RBUF_FW_BUF_FREE 0x00200014
+#define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0)
+#define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16)
+
+#define BNX2_RBUF_FW_BUF_SEL 0x00200018
+#define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0)
+#define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16)
+
+#define BNX2_RBUF_CONFIG2 0x0020001c
+#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_CONFIG3 0x00200020
+#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_PKT_DATA 0x00208000
+#define BNX2_RBUF_CLIST_DATA 0x00210000
+#define BNX2_RBUF_BUF_DATA 0x00220000
+
+
+/*
+ * rv2p_reg definition
+ * offset: 0x2800
+ */
+#define BNX2_RV2P_COMMAND 0x00002800
+#define BNX2_RV2P_COMMAND_ENABLED (1L<<0)
+#define BNX2_RV2P_COMMAND_PROC1_INTRPT (1L<<1)
+#define BNX2_RV2P_COMMAND_PROC2_INTRPT (1L<<2)
+#define BNX2_RV2P_COMMAND_ABORT0 (1L<<4)
+#define BNX2_RV2P_COMMAND_ABORT1 (1L<<5)
+#define BNX2_RV2P_COMMAND_ABORT2 (1L<<6)
+#define BNX2_RV2P_COMMAND_ABORT3 (1L<<7)
+#define BNX2_RV2P_COMMAND_ABORT4 (1L<<8)
+#define BNX2_RV2P_COMMAND_ABORT5 (1L<<9)
+#define BNX2_RV2P_COMMAND_PROC1_RESET (1L<<16)
+#define BNX2_RV2P_COMMAND_PROC2_RESET (1L<<17)
+#define BNX2_RV2P_COMMAND_CTXIF_RESET (1L<<18)
+
+#define BNX2_RV2P_STATUS 0x00002804
+#define BNX2_RV2P_STATUS_ALWAYS_0 (1L<<0)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT (1L<<8)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT (1L<<9)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT (1L<<10)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT (1L<<11)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT (1L<<12)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT (1L<<13)
+
+#define BNX2_RV2P_CONFIG 0x00002808
+#define BNX2_RV2P_CONFIG_STALL_PROC1 (1L<<0)
+#define BNX2_RV2P_CONFIG_STALL_PROC2 (1L<<1)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0 (1L<<8)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1 (1L<<9)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2 (1L<<10)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3 (1L<<11)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4 (1L<<12)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5 (1L<<13)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0 (1L<<16)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1 (1L<<17)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2 (1L<<18)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3 (1L<<19)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4 (1L<<20)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5 (1L<<21)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_0 0x00002810
+#define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_1 0x00002814
+#define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_2 0x00002818
+#define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_3 0x0000281c
+#define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_INSTR_HIGH 0x00002830
+#define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0)
+
+#define BNX2_RV2P_INSTR_LOW 0x00002834
+#define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838
+#define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0)
+#define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31)
+
+#define BNX2_RV2P_PROC2_ADDR_CMD 0x0000283c
+#define BNX2_RV2P_PROC2_ADDR_CMD_ADD (0x3ffL<<0)
+#define BNX2_RV2P_PROC2_ADDR_CMD_RDWR (1L<<31)
+
+#define BNX2_RV2P_PROC1_GRC_DEBUG 0x00002840
+#define BNX2_RV2P_PROC2_GRC_DEBUG 0x00002844
+#define BNX2_RV2P_GRC_PROC_DEBUG 0x00002848
+#define BNX2_RV2P_DEBUG_VECT_PEEK 0x0000284c
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_RV2P_PFTQ_DATA 0x00002b40
+#define BNX2_RV2P_PFTQ_CMD 0x00002b78
+#define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_PFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_PFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_PFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_PFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_PFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_PFTQ_CTL 0x00002b7c
+#define BNX2_RV2P_PFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_PFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RV2P_TFTQ_DATA 0x00002b80
+#define BNX2_RV2P_TFTQ_CMD 0x00002bb8
+#define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_TFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_TFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_TFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_TFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_TFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_TFTQ_CTL 0x00002bbc
+#define BNX2_RV2P_TFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_TFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RV2P_MFTQ_DATA 0x00002bc0
+#define BNX2_RV2P_MFTQ_CMD 0x00002bf8
+#define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_MFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_MFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_MFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_MFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_MFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_MFTQ_CTL 0x00002bfc
+#define BNX2_RV2P_MFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_MFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * mq_reg definition
+ * offset: 0x3c00
+ */
+#define BNX2_MQ_COMMAND 0x00003c00
+#define BNX2_MQ_COMMAND_ENABLED (1L<<0)
+#define BNX2_MQ_COMMAND_OVERFLOW (1L<<4)
+#define BNX2_MQ_COMMAND_WR_ERROR (1L<<5)
+#define BNX2_MQ_COMMAND_RD_ERROR (1L<<6)
+
+#define BNX2_MQ_STATUS 0x00003c04
+#define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16)
+#define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17)
+#define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18)
+
+#define BNX2_MQ_CONFIG 0x00003c08
+#define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0)
+#define BNX2_MQ_CONFIG_HALT_DIS (1L<<1)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K (2L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K (3L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K (4L<<4)
+#define BNX2_MQ_CONFIG_MAX_DEPTH (0x7fL<<8)
+#define BNX2_MQ_CONFIG_CUR_DEPTH (0x7fL<<20)
+
+#define BNX2_MQ_ENQUEUE1 0x00003c0c
+#define BNX2_MQ_ENQUEUE1_OFFSET (0x3fL<<2)
+#define BNX2_MQ_ENQUEUE1_CID (0x3fffL<<8)
+#define BNX2_MQ_ENQUEUE1_BYTE_MASK (0xfL<<24)
+#define BNX2_MQ_ENQUEUE1_KNL_MODE (1L<<28)
+
+#define BNX2_MQ_ENQUEUE2 0x00003c10
+#define BNX2_MQ_BAD_WR_ADDR 0x00003c14
+#define BNX2_MQ_BAD_RD_ADDR 0x00003c18
+#define BNX2_MQ_KNL_BYP_WIND_START 0x00003c1c
+#define BNX2_MQ_KNL_BYP_WIND_START_VALUE (0xfffffL<<12)
+
+#define BNX2_MQ_KNL_WIND_END 0x00003c20
+#define BNX2_MQ_KNL_WIND_END_VALUE (0xffffffL<<8)
+
+#define BNX2_MQ_KNL_WRITE_MASK1 0x00003c24
+#define BNX2_MQ_KNL_TX_MASK1 0x00003c28
+#define BNX2_MQ_KNL_CMD_MASK1 0x00003c2c
+#define BNX2_MQ_KNL_COND_ENQUEUE_MASK1 0x00003c30
+#define BNX2_MQ_KNL_RX_V2P_MASK1 0x00003c34
+#define BNX2_MQ_KNL_WRITE_MASK2 0x00003c38
+#define BNX2_MQ_KNL_TX_MASK2 0x00003c3c
+#define BNX2_MQ_KNL_CMD_MASK2 0x00003c40
+#define BNX2_MQ_KNL_COND_ENQUEUE_MASK2 0x00003c44
+#define BNX2_MQ_KNL_RX_V2P_MASK2 0x00003c48
+#define BNX2_MQ_KNL_BYP_WRITE_MASK1 0x00003c4c
+#define BNX2_MQ_KNL_BYP_TX_MASK1 0x00003c50
+#define BNX2_MQ_KNL_BYP_CMD_MASK1 0x00003c54
+#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1 0x00003c58
+#define BNX2_MQ_KNL_BYP_RX_V2P_MASK1 0x00003c5c
+#define BNX2_MQ_KNL_BYP_WRITE_MASK2 0x00003c60
+#define BNX2_MQ_KNL_BYP_TX_MASK2 0x00003c64
+#define BNX2_MQ_KNL_BYP_CMD_MASK2 0x00003c68
+#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2 0x00003c6c
+#define BNX2_MQ_KNL_BYP_RX_V2P_MASK2 0x00003c70
+#define BNX2_MQ_MEM_WR_ADDR 0x00003c74
+#define BNX2_MQ_MEM_WR_ADDR_VALUE (0x3fL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA0 0x00003c78
+#define BNX2_MQ_MEM_WR_DATA0_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA1 0x00003c7c
+#define BNX2_MQ_MEM_WR_DATA1_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA2 0x00003c80
+#define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_ADDR 0x00003c84
+#define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA0 0x00003c88
+#define BNX2_MQ_MEM_RD_DATA0_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA1 0x00003c8c
+#define BNX2_MQ_MEM_RD_DATA1_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA2 0x00003c90
+#define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0)
+
+
+
+/*
+ * tbdr_reg definition
+ * offset: 0x5000
+ */
+#define BNX2_TBDR_COMMAND 0x00005000
+#define BNX2_TBDR_COMMAND_ENABLE (1L<<0)
+#define BNX2_TBDR_COMMAND_SOFT_RST (1L<<1)
+#define BNX2_TBDR_COMMAND_MSTR_ABORT (1L<<4)
+
+#define BNX2_TBDR_STATUS 0x00005004
+#define BNX2_TBDR_STATUS_DMA_WAIT (1L<<0)
+#define BNX2_TBDR_STATUS_FTQ_WAIT (1L<<1)
+#define BNX2_TBDR_STATUS_FIFO_OVERFLOW (1L<<2)
+#define BNX2_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3)
+#define BNX2_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4)
+#define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5)
+#define BNX2_TBDR_STATUS_BURST_CNT (1L<<6)
+
+#define BNX2_TBDR_CONFIG 0x00005008
+#define BNX2_TBDR_CONFIG_MAX_BDS (0xffL<<0)
+#define BNX2_TBDR_CONFIG_SWAP_MODE (1L<<8)
+#define BNX2_TBDR_CONFIG_PRIORITY (1L<<9)
+#define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BNX2_TBDR_DEBUG_VECT_PEEK 0x0000500c
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TBDR_FTQ_DATA 0x000053c0
+#define BNX2_TBDR_FTQ_CMD 0x000053f8
+#define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TBDR_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TBDR_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TBDR_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TBDR_FTQ_CMD_POP (1L<<30)
+#define BNX2_TBDR_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TBDR_FTQ_CTL 0x000053fc
+#define BNX2_TBDR_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TBDR_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * tdma_reg definition
+ * offset: 0x5c00
+ */
+#define BNX2_TDMA_COMMAND 0x00005c00
+#define BNX2_TDMA_COMMAND_ENABLED (1L<<0)
+#define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4)
+#define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
+
+#define BNX2_TDMA_STATUS 0x00005c04
+#define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0)
+#define BNX2_TDMA_STATUS_PAYLOAD_WAIT (1L<<1)
+#define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2)
+#define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3)
+#define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16)
+#define BNX2_TDMA_STATUS_BURST_CNT (1L<<17)
+
+#define BNX2_TDMA_CONFIG 0x00005c08
+#define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0)
+#define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4)
+#define BNX2_TDMA_CONFIG_LINE_SZ (0xfL<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_64 (0L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_128 (4L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_256 (6L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8)
+#define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15)
+#define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16)
+#define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20)
+
+#define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c
+#define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3)
+
+#define BNX2_TDMA_DBG_WATCHDOG 0x00005c10
+#define BNX2_TDMA_DBG_TRIGGER 0x00005c14
+#define BNX2_TDMA_DMAD_FSM 0x00005c80
+#define BNX2_TDMA_DMAD_FSM_BD_INVLD (1L<<0)
+#define BNX2_TDMA_DMAD_FSM_PUSH (0xfL<<4)
+#define BNX2_TDMA_DMAD_FSM_ARB_TBDC (0x3L<<8)
+#define BNX2_TDMA_DMAD_FSM_ARB_CTX (1L<<12)
+#define BNX2_TDMA_DMAD_FSM_DR_INTF (1L<<16)
+#define BNX2_TDMA_DMAD_FSM_DMAD (0x7L<<20)
+#define BNX2_TDMA_DMAD_FSM_BD (0xfL<<24)
+
+#define BNX2_TDMA_DMAD_STATUS 0x00005c84
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY (0x3L<<0)
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY (0x3L<<4)
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY (0x3L<<8)
+#define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM (0xfL<<12)
+
+#define BNX2_TDMA_DR_INTF_FSM 0x00005c88
+#define BNX2_TDMA_DR_INTF_FSM_L2_COMP (0x3L<<0)
+#define BNX2_TDMA_DR_INTF_FSM_TPATQ (0x7L<<4)
+#define BNX2_TDMA_DR_INTF_FSM_TPBUF (0x3L<<8)
+#define BNX2_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12)
+#define BNX2_TDMA_DR_INTF_FSM_DMAD (0x7L<<16)
+
+#define BNX2_TDMA_DR_INTF_STATUS 0x00005c8c
+#define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0)
+#define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4)
+#define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8)
+#define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12)
+#define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16)
+
+#define BNX2_TDMA_FTQ_DATA 0x00005fc0
+#define BNX2_TDMA_FTQ_CMD 0x00005ff8
+#define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TDMA_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TDMA_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TDMA_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TDMA_FTQ_CMD_POP (1L<<30)
+#define BNX2_TDMA_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TDMA_FTQ_CTL 0x00005ffc
+#define BNX2_TDMA_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TDMA_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TDMA_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * hc_reg definition
+ * offset: 0x6800
+ */
+#define BNX2_HC_COMMAND 0x00006800
+#define BNX2_HC_COMMAND_ENABLE (1L<<0)
+#define BNX2_HC_COMMAND_SKIP_ABORT (1L<<4)
+#define BNX2_HC_COMMAND_COAL_NOW (1L<<16)
+#define BNX2_HC_COMMAND_COAL_NOW_WO_INT (1L<<17)
+#define BNX2_HC_COMMAND_STATS_NOW (1L<<18)
+#define BNX2_HC_COMMAND_FORCE_INT (0x3L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_NULL (0L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_HIGH (1L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19)
+#define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21)
+
+#define BNX2_HC_STATUS 0x00006804
+#define BNX2_HC_STATUS_MASTER_ABORT (1L<<0)
+#define BNX2_HC_STATUS_PARITY_ERROR_STATE (1L<<1)
+#define BNX2_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16)
+#define BNX2_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17)
+#define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18)
+#define BNX2_HC_STATUS_NUM_INT_GEN_STAT (1L<<19)
+#define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20)
+#define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT (1L<<23)
+#define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT (1L<<24)
+#define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT (1L<<25)
+
+#define BNX2_HC_CONFIG 0x00006808
+#define BNX2_HC_CONFIG_COLLECT_STATS (1L<<0)
+#define BNX2_HC_CONFIG_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_CONFIG_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_CONFIG_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_CONFIG_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5)
+#define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6)
+#define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8)
+
+#define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c
+#define BNX2_HC_STATUS_ADDR_L 0x00006810
+#define BNX2_HC_STATUS_ADDR_H 0x00006814
+#define BNX2_HC_STATISTICS_ADDR_L 0x00006818
+#define BNX2_HC_STATISTICS_ADDR_H 0x0000681c
+#define BNX2_HC_TX_QUICK_CONS_TRIP 0x00006820
+#define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP 0x00006824
+#define BNX2_HC_COMP_PROD_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP 0x00006828
+#define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS 0x0000682c
+#define BNX2_HC_RX_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS 0x00006830
+#define BNX2_HC_TX_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS 0x00006834
+#define BNX2_HC_COM_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS 0x00006838
+#define BNX2_HC_CMD_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS 0x0000683c
+#define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
+
+#define BNX2_HC_STAT_COLLECT_TICKS 0x00006840
+#define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4)
+
+#define BNX2_HC_STATS_TICKS 0x00006844
+#define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8)
+
+#define BNX2_HC_STAT_MEM_DATA 0x0000684c
+#define BNX2_HC_STAT_GEN_SEL_0 0x00006850
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3 (3L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4 (4L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5 (5L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6 (6L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7 (7L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8 (8L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9 (9L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10 (10L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11 (11L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0 (12L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1 (13L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2 (14L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3 (15L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4 (16L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5 (17L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6 (18L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7 (19L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0 (20L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1 (21L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2 (22L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3 (23L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4 (24L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5 (25L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6 (26L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7 (27L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8 (28L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9 (29L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10 (30L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11 (31L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0 (32L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1 (33L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2 (34L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3 (35L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0 (36L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1 (37L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2 (38L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3 (39L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4 (40L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5 (41L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6 (42L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7 (43L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0 (44L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1 (45L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2 (46L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3 (47L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4 (48L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5 (49L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6 (50L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7 (51L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT (52L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT (53L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS (54L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN (55L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR (56L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK (59L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK (60L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK (61L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT (62L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT (63L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT (64L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT (65L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT (75L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT (76L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT (77L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT (78L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT (79L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT (80L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT (81L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT (82L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT (83L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT (84L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT (85L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT (86L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT (87L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT (88L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT (89L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT (90L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT (91L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT (92L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT (93L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT (94L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64 (95L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64 (96L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS (97L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS (98L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT (99L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT (100L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT (101L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT (102L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT (103L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT (104L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT (105L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT (106L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT (107L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT (108L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT (109L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT (110L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT (111L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT (112L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT (113L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT (114L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0 (115L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1 (116L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2 (117L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3 (118L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4 (119L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5 (120L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS (121L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS (122L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT (127L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_1 0x00006854
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_2 0x00006858
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_3 0x0000685c
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_STAT0 0x00006888
+#define BNX2_HC_STAT_GEN_STAT1 0x0000688c
+#define BNX2_HC_STAT_GEN_STAT2 0x00006890
+#define BNX2_HC_STAT_GEN_STAT3 0x00006894
+#define BNX2_HC_STAT_GEN_STAT4 0x00006898
+#define BNX2_HC_STAT_GEN_STAT5 0x0000689c
+#define BNX2_HC_STAT_GEN_STAT6 0x000068a0
+#define BNX2_HC_STAT_GEN_STAT7 0x000068a4
+#define BNX2_HC_STAT_GEN_STAT8 0x000068a8
+#define BNX2_HC_STAT_GEN_STAT9 0x000068ac
+#define BNX2_HC_STAT_GEN_STAT10 0x000068b0
+#define BNX2_HC_STAT_GEN_STAT11 0x000068b4
+#define BNX2_HC_STAT_GEN_STAT12 0x000068b8
+#define BNX2_HC_STAT_GEN_STAT13 0x000068bc
+#define BNX2_HC_STAT_GEN_STAT14 0x000068c0
+#define BNX2_HC_STAT_GEN_STAT15 0x000068c4
+#define BNX2_HC_STAT_GEN_STAT_AC0 0x000068c8
+#define BNX2_HC_STAT_GEN_STAT_AC1 0x000068cc
+#define BNX2_HC_STAT_GEN_STAT_AC2 0x000068d0
+#define BNX2_HC_STAT_GEN_STAT_AC3 0x000068d4
+#define BNX2_HC_STAT_GEN_STAT_AC4 0x000068d8
+#define BNX2_HC_STAT_GEN_STAT_AC5 0x000068dc
+#define BNX2_HC_STAT_GEN_STAT_AC6 0x000068e0
+#define BNX2_HC_STAT_GEN_STAT_AC7 0x000068e4
+#define BNX2_HC_STAT_GEN_STAT_AC8 0x000068e8
+#define BNX2_HC_STAT_GEN_STAT_AC9 0x000068ec
+#define BNX2_HC_STAT_GEN_STAT_AC10 0x000068f0
+#define BNX2_HC_STAT_GEN_STAT_AC11 0x000068f4
+#define BNX2_HC_STAT_GEN_STAT_AC12 0x000068f8
+#define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc
+#define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900
+#define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904
+#define BNX2_HC_VIS 0x00006908
+#define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_START (1L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST (2L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64 (3L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32 (4L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE (5L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_DMA (6L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL (7L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW (8L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH (9L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA (10L<<0)
+#define BNX2_HC_VIS_DMA_STAT_STATE (0xfL<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_IDLE (0L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM (1L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA (2L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP (3L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_COMP (4L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM (5L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA (6L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1 (7L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2 (8L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WAIT (9L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_ABORT (15L<<8)
+#define BNX2_HC_VIS_DMA_MSI_STATE (0x7L<<12)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE (0x3L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE (0L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT (1L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START (2L<<15)
+
+#define BNX2_HC_VIS_1 0x0000690c
+#define BNX2_HC_VIS_1_HW_INTACK_STATE (1L<<4)
+#define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE (0L<<4)
+#define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT (1L<<4)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE (1L<<5)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE (0L<<5)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT (1L<<5)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE (1L<<6)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE (0L<<6)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT (1L<<6)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE (1L<<7)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE (0L<<7)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT (1L<<7)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE (0xfL<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE (0L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA (1L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE (2L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN (3L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT (4L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE (5L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN (6L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT (7L<<17)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE (0x3L<<21)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL (0L<<21)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR (1L<<21)
+#define BNX2_HC_VIS_1_INT_GEN_STATE (1L<<23)
+#define BNX2_HC_VIS_1_INT_GEN_STATE_DLE (0L<<23)
+#define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT (1L<<23)
+#define BNX2_HC_VIS_1_STAT_CHAN_ID (0x7L<<24)
+#define BNX2_HC_VIS_1_INT_B (1L<<27)
+
+#define BNX2_HC_DEBUG_VECT_PEEK 0x00006910
+#define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_HC_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+
+
+/*
+ * txp_reg definition
+ * offset: 0x40000
+ */
+#define BNX2_TXP_CPU_MODE 0x00045000
+#define BNX2_TXP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_TXP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_TXP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_TXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_TXP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_TXP_CPU_STATE 0x00045004
+#define BNX2_TXP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_TXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_TXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_TXP_CPU_EVENT_MASK 0x00045008
+#define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_TXP_CPU_PROGRAM_COUNTER 0x0004501c
+#define BNX2_TXP_CPU_INSTRUCTION 0x00045020
+#define BNX2_TXP_CPU_DATA_ACCESS 0x00045024
+#define BNX2_TXP_CPU_INTERRUPT_ENABLE 0x00045028
+#define BNX2_TXP_CPU_INTERRUPT_VECTOR 0x0004502c
+#define BNX2_TXP_CPU_INTERRUPT_SAVED_PC 0x00045030
+#define BNX2_TXP_CPU_HW_BREAKPOINT 0x00045034
+#define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK 0x00045038
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR 0x00045048
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_TXP_CPU_REG_FILE 0x00045200
+#define BNX2_TXP_FTQ_DATA 0x000453c0
+#define BNX2_TXP_FTQ_CMD 0x000453f8
+#define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TXP_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TXP_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TXP_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TXP_FTQ_CMD_POP (1L<<30)
+#define BNX2_TXP_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TXP_FTQ_CTL 0x000453fc
+#define BNX2_TXP_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TXP_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_TXP_SCRATCH 0x00060000
+
+
+/*
+ * tpat_reg definition
+ * offset: 0x80000
+ */
+#define BNX2_TPAT_CPU_MODE 0x00085000
+#define BNX2_TPAT_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_TPAT_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_TPAT_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_TPAT_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_TPAT_CPU_STATE 0x00085004
+#define BNX2_TPAT_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_TPAT_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_TPAT_CPU_EVENT_MASK 0x00085008
+#define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_TPAT_CPU_PROGRAM_COUNTER 0x0008501c
+#define BNX2_TPAT_CPU_INSTRUCTION 0x00085020
+#define BNX2_TPAT_CPU_DATA_ACCESS 0x00085024
+#define BNX2_TPAT_CPU_INTERRUPT_ENABLE 0x00085028
+#define BNX2_TPAT_CPU_INTERRUPT_VECTOR 0x0008502c
+#define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC 0x00085030
+#define BNX2_TPAT_CPU_HW_BREAKPOINT 0x00085034
+#define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK 0x00085038
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR 0x00085048
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_TPAT_CPU_REG_FILE 0x00085200
+#define BNX2_TPAT_FTQ_DATA 0x000853c0
+#define BNX2_TPAT_FTQ_CMD 0x000853f8
+#define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TPAT_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TPAT_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TPAT_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TPAT_FTQ_CMD_POP (1L<<30)
+#define BNX2_TPAT_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TPAT_FTQ_CTL 0x000853fc
+#define BNX2_TPAT_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TPAT_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TPAT_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TPAT_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_TPAT_SCRATCH 0x000a0000
+
+
+/*
+ * rxp_reg definition
+ * offset: 0xc0000
+ */
+#define BNX2_RXP_CPU_MODE 0x000c5000
+#define BNX2_RXP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_RXP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_RXP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_RXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_RXP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_RXP_CPU_STATE 0x000c5004
+#define BNX2_RXP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_RXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_RXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_RXP_CPU_EVENT_MASK 0x000c5008
+#define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_RXP_CPU_PROGRAM_COUNTER 0x000c501c
+#define BNX2_RXP_CPU_INSTRUCTION 0x000c5020
+#define BNX2_RXP_CPU_DATA_ACCESS 0x000c5024
+#define BNX2_RXP_CPU_INTERRUPT_ENABLE 0x000c5028
+#define BNX2_RXP_CPU_INTERRUPT_VECTOR 0x000c502c
+#define BNX2_RXP_CPU_INTERRUPT_SAVED_PC 0x000c5030
+#define BNX2_RXP_CPU_HW_BREAKPOINT 0x000c5034
+#define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK 0x000c5038
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR 0x000c5048
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_RXP_CPU_REG_FILE 0x000c5200
+#define BNX2_RXP_CFTQ_DATA 0x000c5380
+#define BNX2_RXP_CFTQ_CMD 0x000c53b8
+#define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RXP_CFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RXP_CFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RXP_CFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RXP_CFTQ_CMD_POP (1L<<30)
+#define BNX2_RXP_CFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RXP_CFTQ_CTL 0x000c53bc
+#define BNX2_RXP_CFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RXP_CFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RXP_FTQ_DATA 0x000c53c0
+#define BNX2_RXP_FTQ_CMD 0x000c53f8
+#define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RXP_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RXP_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RXP_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RXP_FTQ_CMD_POP (1L<<30)
+#define BNX2_RXP_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RXP_FTQ_CTL 0x000c53fc
+#define BNX2_RXP_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RXP_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RXP_SCRATCH 0x000e0000
+
+
+/*
+ * com_reg definition
+ * offset: 0x100000
+ */
+#define BNX2_COM_CPU_MODE 0x00105000
+#define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_COM_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_COM_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_COM_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_COM_CPU_STATE 0x00105004
+#define BNX2_COM_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_COM_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_COM_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_COM_CPU_EVENT_MASK 0x00105008
+#define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_COM_CPU_PROGRAM_COUNTER 0x0010501c
+#define BNX2_COM_CPU_INSTRUCTION 0x00105020
+#define BNX2_COM_CPU_DATA_ACCESS 0x00105024
+#define BNX2_COM_CPU_INTERRUPT_ENABLE 0x00105028
+#define BNX2_COM_CPU_INTERRUPT_VECTOR 0x0010502c
+#define BNX2_COM_CPU_INTERRUPT_SAVED_PC 0x00105030
+#define BNX2_COM_CPU_HW_BREAKPOINT 0x00105034
+#define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK 0x00105038
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR 0x00105048
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_COM_CPU_REG_FILE 0x00105200
+#define BNX2_COM_COMXQ_FTQ_DATA 0x00105340
+#define BNX2_COM_COMXQ_FTQ_CMD 0x00105378
+#define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMXQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMXQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMXQ_FTQ_CTL 0x0010537c
+#define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_COMTQ_FTQ_DATA 0x00105380
+#define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8
+#define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMTQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMTQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMTQ_FTQ_CTL 0x001053bc
+#define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_COMQ_FTQ_DATA 0x001053c0
+#define BNX2_COM_COMQ_FTQ_CMD 0x001053f8
+#define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMQ_FTQ_CTL 0x001053fc
+#define BNX2_COM_COMQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_SCRATCH 0x00120000
+
+
+/*
+ * cp_reg definition
+ * offset: 0x180000
+ */
+#define BNX2_CP_CPU_MODE 0x00185000
+#define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_CP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_CP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_CP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_CP_CPU_STATE 0x00185004
+#define BNX2_CP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_CP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_CP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_CP_CPU_EVENT_MASK 0x00185008
+#define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_CP_CPU_PROGRAM_COUNTER 0x0018501c
+#define BNX2_CP_CPU_INSTRUCTION 0x00185020
+#define BNX2_CP_CPU_DATA_ACCESS 0x00185024
+#define BNX2_CP_CPU_INTERRUPT_ENABLE 0x00185028
+#define BNX2_CP_CPU_INTERRUPT_VECTOR 0x0018502c
+#define BNX2_CP_CPU_INTERRUPT_SAVED_PC 0x00185030
+#define BNX2_CP_CPU_HW_BREAKPOINT 0x00185034
+#define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK 0x00185038
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR 0x00185048
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_CP_CPU_REG_FILE 0x00185200
+#define BNX2_CP_CPQ_FTQ_DATA 0x001853c0
+#define BNX2_CP_CPQ_FTQ_CMD 0x001853f8
+#define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_CP_CPQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_CP_CPQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_CP_CPQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_CP_CPQ_FTQ_CTL 0x001853fc
+#define BNX2_CP_CPQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_CP_SCRATCH 0x001a0000
+
+
+/*
+ * mcp_reg definition
+ * offset: 0x140000
+ */
+#define BNX2_MCP_CPU_MODE 0x00145000
+#define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_MCP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_MCP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_MCP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_MCP_CPU_STATE 0x00145004
+#define BNX2_MCP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_MCP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_MCP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_MCP_CPU_EVENT_MASK 0x00145008
+#define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_MCP_CPU_PROGRAM_COUNTER 0x0014501c
+#define BNX2_MCP_CPU_INSTRUCTION 0x00145020
+#define BNX2_MCP_CPU_DATA_ACCESS 0x00145024
+#define BNX2_MCP_CPU_INTERRUPT_ENABLE 0x00145028
+#define BNX2_MCP_CPU_INTERRUPT_VECTOR 0x0014502c
+#define BNX2_MCP_CPU_INTERRUPT_SAVED_PC 0x00145030
+#define BNX2_MCP_CPU_HW_BREAKPOINT 0x00145034
+#define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK 0x00145038
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR 0x00145048
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_MCP_CPU_REG_FILE 0x00145200
+#define BNX2_MCP_MCPQ_FTQ_DATA 0x001453c0
+#define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8
+#define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_MCP_MCPQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_MCP_MCPQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_MCP_MCPQ_FTQ_CTL 0x001453fc
+#define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_MCP_ROM 0x00150000
+#define BNX2_MCP_SCRATCH 0x00160000
+
+#define BNX2_SHM_HDR_SIGNATURE BNX2_MCP_SCRATCH
+#define BNX2_SHM_HDR_SIGNATURE_SIG_MASK 0xffff0000
+#define BNX2_SHM_HDR_SIGNATURE_SIG 0x53530000
+#define BNX2_SHM_HDR_SIGNATURE_VER_MASK 0x000000ff
+#define BNX2_SHM_HDR_SIGNATURE_VER_ONE 0x00000001
+
+#define BNX2_SHM_HDR_ADDR_0 BNX2_MCP_SCRATCH + 4
+#define BNX2_SHM_HDR_ADDR_1 BNX2_MCP_SCRATCH + 8
+
+
+#define NUM_MC_HASH_REGISTERS 8
+
+
+/* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0. */
+#define PHY_BCM5706_PHY_ID 0x00206160
+
+#define PHY_ID(id) ((id) & 0xfffffff0)
+#define PHY_REV_ID(id) ((id) & 0xf)
+
+/* 5708 Serdes PHY registers */
+
+#define BCM5708S_UP1 0xb
+
+#define BCM5708S_UP1_2G5 0x1
+
+#define BCM5708S_BLK_ADDR 0x1f
+
+#define BCM5708S_BLK_ADDR_DIG 0x0000
+#define BCM5708S_BLK_ADDR_DIG3 0x0002
+#define BCM5708S_BLK_ADDR_TX_MISC 0x0005
+
+/* Digital Block */
+#define BCM5708S_1000X_CTL1 0x10
+
+#define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001
+#define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010
+
+#define BCM5708S_1000X_CTL2 0x11
+
+#define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001
+
+#define BCM5708S_1000X_STAT1 0x14
+
+#define BCM5708S_1000X_STAT1_SGMII 0x0001
+#define BCM5708S_1000X_STAT1_LINK 0x0002
+#define BCM5708S_1000X_STAT1_FD 0x0004
+#define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018
+#define BCM5708S_1000X_STAT1_SPEED_10 0x0000
+#define BCM5708S_1000X_STAT1_SPEED_100 0x0008
+#define BCM5708S_1000X_STAT1_SPEED_1G 0x0010
+#define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018
+#define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020
+#define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040
+
+/* Digital3 Block */
+#define BCM5708S_DIG_3_0 0x10
+
+#define BCM5708S_DIG_3_0_USE_IEEE 0x0001
+
+/* Tx/Misc Block */
+#define BCM5708S_TX_ACTL1 0x15
+
+#define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30
+
+#define BCM5708S_TX_ACTL3 0x17
+
+#define MIN_ETHERNET_PACKET_SIZE 60
+#define MAX_ETHERNET_PACKET_SIZE 1514
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
+
+#define RX_COPY_THRESH 92
+
+#define DMA_READ_CHANS 5
+#define DMA_WRITE_CHANS 3
+
+#define BCM_PAGE_BITS 12
+#define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS)
+
+#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
+#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+
+#define MAX_RX_RINGS 4
+#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
+#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
+#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
+
+#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
+ (MAX_TX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+#define PREV_TX_BD(x) ((((x)-1) & (MAX_TX_DESC_CNT)) == \
+ (MAX_TX_DESC_CNT)) ? \
+ (x) - 2 : (x) - 1
+
+#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
+
+#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \
+ (MAX_RX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
+
+//#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
+#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
+
+/* Context size. */
+#define CTX_SHIFT 7
+#define CTX_SIZE (1 << CTX_SHIFT)
+#define CTX_MASK (CTX_SIZE - 1)
+#define GET_CID_ADDR(_cid) ((_cid) << CTX_SHIFT)
+#define GET_CID(_cid_addr) ((_cid_addr) >> CTX_SHIFT)
+
+#define PHY_CTX_SHIFT 6
+#define PHY_CTX_SIZE (1 << PHY_CTX_SHIFT)
+#define PHY_CTX_MASK (PHY_CTX_SIZE - 1)
+#define GET_PCID_ADDR(_pcid) ((_pcid) << PHY_CTX_SHIFT)
+#define GET_PCID(_pcid_addr) ((_pcid_addr) >> PHY_CTX_SHIFT)
+
+#define MB_KERNEL_CTX_SHIFT 8
+#define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT)
+#define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1)
+#define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT))
+
+#define MAX_CID_CNT 0x4000
+#define MAX_CID_ADDR (GET_CID_ADDR(MAX_CID_CNT))
+#define INVALID_CID_ADDR 0xffffffff
+
+#define TX_CID 16
+#define RX_CID 0
+
+#define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID)
+#define MB_RX_CID_ADDR MB_GET_CID_ADDR(RX_CID)
+
+#if 0
+struct sw_bd {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+};
+#endif
+
+/* Buffered flash (Atmel: AT45DB011B) specific information */
+#define SEEPROM_PAGE_BITS 2
+#define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS)
+#define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1)
+#define SEEPROM_PAGE_SIZE 4
+#define SEEPROM_TOTAL_SIZE 65536
+
+#define BUFFERED_FLASH_PAGE_BITS 9
+#define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS)
+#define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1)
+#define BUFFERED_FLASH_PAGE_SIZE 264
+#define BUFFERED_FLASH_TOTAL_SIZE 0x21000
+
+#define SAIFUN_FLASH_PAGE_BITS 8
+#define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS)
+#define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1)
+#define SAIFUN_FLASH_PAGE_SIZE 256
+#define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536
+
+#define ST_MICRO_FLASH_PAGE_BITS 8
+#define ST_MICRO_FLASH_PHY_PAGE_SIZE (1 << ST_MICRO_FLASH_PAGE_BITS)
+#define ST_MICRO_FLASH_BYTE_ADDR_MASK (ST_MICRO_FLASH_PHY_PAGE_SIZE-1)
+#define ST_MICRO_FLASH_PAGE_SIZE 256
+#define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536
+
+#define NVRAM_TIMEOUT_COUNT 30000
+
+
+#define FLASH_STRAP_MASK (BNX2_NVM_CFG1_FLASH_MODE | \
+ BNX2_NVM_CFG1_BUFFER_MODE | \
+ BNX2_NVM_CFG1_PROTECT_MODE | \
+ BNX2_NVM_CFG1_FLASH_SIZE)
+
+#define FLASH_BACKUP_STRAP_MASK (0xf << 26)
+
+struct flash_spec {
+ u32 strapping;
+ u32 config1;
+ u32 config2;
+ u32 config3;
+ u32 write1;
+ u32 buffered;
+ u32 page_bits;
+ u32 page_size;
+ u32 addr_mask;
+ u32 total_size;
+ char *name;
+};
+
+struct bnx2 {
+ /* Fields used in the tx and intr/napi performance paths are grouped */
+ /* together in the beginning of the structure. */
+ void /*__iomem*/ *regview;
+
+ struct nic *nic;
+ struct pci_device *pdev;
+
+ /* atomic_t intr_sem; */
+
+ struct status_block *status_blk;
+ u32 last_status_idx;
+
+ u32 flags;
+#define PCIX_FLAG 1
+#define PCI_32BIT_FLAG 2
+#define ONE_TDMA_FLAG 4 /* no longer used */
+#define NO_WOL_FLAG 8
+#define USING_DAC_FLAG 0x10
+#define USING_MSI_FLAG 0x20
+#define ASF_ENABLE_FLAG 0x40
+
+ /* Put tx producer and consumer fields in separate cache lines. */
+ u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
+ u16 tx_prod;
+
+ struct tx_bd *tx_desc_ring;
+ struct sw_bd *tx_buf_ring;
+ int tx_ring_size;
+
+ u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
+ u16 hw_tx_cons;
+
+#ifdef BCM_VLAN
+ struct vlan_group *vlgrp;
+#endif
+
+ u32 rx_offset;
+ u32 rx_buf_use_size; /* useable size */
+ u32 rx_buf_size; /* with alignment */
+ u32 rx_max_ring_idx;
+
+ u32 rx_prod_bseq;
+ u16 rx_prod;
+ u16 rx_cons;
+ u16 hw_rx_cons;
+
+ u32 rx_csum;
+
+#if 0
+ struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
+#endif
+ struct rx_bd *rx_desc_ring;
+
+ /* End of fields used in the performance code paths. */
+
+ char *name;
+
+#if 0
+ int timer_interval;
+ int current_interval;
+ struct timer_list timer;
+ struct work_struct reset_task;
+ int in_reset_task;
+
+ /* Used to synchronize phy accesses. */
+ spinlock_t phy_lock;
+#endif
+
+ u32 phy_flags;
+#define PHY_SERDES_FLAG 1
+#define PHY_CRC_FIX_FLAG 2
+#define PHY_PARALLEL_DETECT_FLAG 4
+#define PHY_2_5G_CAPABLE_FLAG 8
+#define PHY_INT_MODE_MASK_FLAG 0x300
+#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
+#define PHY_INT_MODE_LINK_READY_FLAG 0x200
+
+ u32 chip_id;
+ /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
+#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
+#define CHIP_NUM_5706 0x57060000
+#define CHIP_NUM_5708 0x57080000
+
+#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
+#define CHIP_REV_Ax 0x00000000
+#define CHIP_REV_Bx 0x00001000
+#define CHIP_REV_Cx 0x00002000
+
+#define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0)
+#define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f)
+
+#define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0)
+#define CHIP_ID_5706_A0 0x57060000
+#define CHIP_ID_5706_A1 0x57060010
+#define CHIP_ID_5706_A2 0x57060020
+#define CHIP_ID_5708_A0 0x57080000
+#define CHIP_ID_5708_B0 0x57081000
+#define CHIP_ID_5708_B1 0x57081010
+
+#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
+
+/* A serdes chip will have the first bit of the bond id set. */
+#define CHIP_BOND_ID_SERDES_BIT 0x01
+
+ u32 phy_addr;
+ u32 phy_id;
+
+ u16 bus_speed_mhz;
+ u8 wol;
+
+ u8 pad;
+
+ u16 fw_wr_seq;
+ u16 fw_drv_pulse_wr_seq;
+
+ dma_addr_t tx_desc_mapping;
+
+
+ int rx_max_ring;
+ int rx_ring_size;
+#if 0
+ dma_addr_t rx_desc_mapping[MAX_RX_RINGS];
+#endif
+ dma_addr_t rx_desc_mapping;
+
+ u16 tx_quick_cons_trip;
+ u16 tx_quick_cons_trip_int;
+ u16 rx_quick_cons_trip;
+ u16 rx_quick_cons_trip_int;
+ u16 comp_prod_trip;
+ u16 comp_prod_trip_int;
+ u16 tx_ticks;
+ u16 tx_ticks_int;
+ u16 com_ticks;
+ u16 com_ticks_int;
+ u16 cmd_ticks;
+ u16 cmd_ticks_int;
+ u16 rx_ticks;
+ u16 rx_ticks_int;
+
+ u32 stats_ticks;
+
+ dma_addr_t status_blk_mapping;
+
+ struct statistics_block *stats_blk;
+ dma_addr_t stats_blk_mapping;
+
+ u32 hc_cmd;
+ u32 rx_mode;
+
+ u16 req_line_speed;
+ u8 req_duplex;
+
+ u8 link_up;
+
+ u16 line_speed;
+ u8 duplex;
+ u8 flow_ctrl; /* actual flow ctrl settings */
+ /* may be different from */
+ /* req_flow_ctrl if autoneg */
+#define FLOW_CTRL_TX 1
+#define FLOW_CTRL_RX 2
+
+ u32 advertising;
+
+ u8 req_flow_ctrl; /* flow ctrl advertisement */
+ /* settings or forced */
+ /* settings */
+ u8 autoneg;
+#define AUTONEG_SPEED 1
+#define AUTONEG_FLOW_CTRL 2
+
+ u8 loopback;
+#define MAC_LOOPBACK 1
+#define PHY_LOOPBACK 2
+
+ u8 serdes_an_pending;
+#define SERDES_AN_TIMEOUT (HZ / 3)
+
+ u8 mac_addr[8];
+
+ u32 shmem_base;
+
+ u32 fw_ver;
+
+ int pm_cap;
+ int pcix_cap;
+
+ /* struct net_device_stats net_stats; */
+
+ struct flash_spec *flash_info;
+ u32 flash_size;
+
+ int status_stats_size;
+};
+
+static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
+static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val);
+
+#define REG_RD(bp, offset) \
+ readl(bp->regview + offset)
+
+#define REG_WR(bp, offset, val) \
+ writel(val, bp->regview + offset)
+
+#define REG_WR16(bp, offset, val) \
+ writew(val, bp->regview + offset)
+
+#define REG_RD_IND(bp, offset) \
+ bnx2_reg_rd_ind(bp, offset)
+
+#define REG_WR_IND(bp, offset, val) \
+ bnx2_reg_wr_ind(bp, offset, val)
+
+/* Indirect context access. Unlike the MBQ_WR, these macros will not
+ * trigger a chip event. */
+static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val);
+
+#define CTX_WR(bp, cid_addr, offset, val) \
+ bnx2_ctx_wr(bp, cid_addr, offset, val)
+
+struct cpu_reg {
+ u32 mode;
+ u32 mode_value_halt;
+ u32 mode_value_sstep;
+
+ u32 state;
+ u32 state_value_clear;
+
+ u32 gpr0;
+ u32 evmask;
+ u32 pc;
+ u32 inst;
+ u32 bp;
+
+ u32 spad_base;
+
+ u32 mips_view_base;
+};
+
+struct fw_info {
+ u32 ver_major;
+ u32 ver_minor;
+ u32 ver_fix;
+
+ u32 start_addr;
+
+ /* Text section. */
+ u32 text_addr;
+ u32 text_len;
+ u32 text_index;
+ u32 *text;
+
+ /* Data section. */
+ u32 data_addr;
+ u32 data_len;
+ u32 data_index;
+ u32 *data;
+
+ /* SBSS section. */
+ u32 sbss_addr;
+ u32 sbss_len;
+ u32 sbss_index;
+ u32 *sbss;
+
+ /* BSS section. */
+ u32 bss_addr;
+ u32 bss_len;
+ u32 bss_index;
+ u32 *bss;
+
+ /* Read-only section. */
+ u32 rodata_addr;
+ u32 rodata_len;
+ u32 rodata_index;
+ u32 *rodata;
+};
+
+#define RV2P_PROC1 0
+#define RV2P_PROC2 1
+
+
+/* This value (in milliseconds) determines the frequency of the driver
+ * issuing the PULSE message code. The firmware monitors this periodic
+ * pulse to determine when to switch to an OS-absent mode. */
+#define DRV_PULSE_PERIOD_MS 250
+
+/* This value (in milliseconds) determines how long the driver should
+ * wait for an acknowledgement from the firmware before timing out. Once
+ * the firmware has timed out, the driver will assume there is no firmware
+ * running and there won't be any firmware-driver synchronization during a
+ * driver reset. */
+#define FW_ACK_TIME_OUT_MS 100
+
+
+#define BNX2_DRV_RESET_SIGNATURE 0x00000000
+#define BNX2_DRV_RESET_SIGNATURE_MAGIC 0x4841564b /* HAVK */
+//#define DRV_RESET_SIGNATURE_MAGIC 0x47495352 /* RSIG */
+
+#define BNX2_DRV_MB 0x00000004
+#define BNX2_DRV_MSG_CODE 0xff000000
+#define BNX2_DRV_MSG_CODE_RESET 0x01000000
+#define BNX2_DRV_MSG_CODE_UNLOAD 0x02000000
+#define BNX2_DRV_MSG_CODE_SHUTDOWN 0x03000000
+#define BNX2_DRV_MSG_CODE_SUSPEND_WOL 0x04000000
+#define BNX2_DRV_MSG_CODE_FW_TIMEOUT 0x05000000
+#define BNX2_DRV_MSG_CODE_PULSE 0x06000000
+#define BNX2_DRV_MSG_CODE_DIAG 0x07000000
+#define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000
+
+#define BNX2_DRV_MSG_DATA 0x00ff0000
+#define BNX2_DRV_MSG_DATA_WAIT0 0x00010000
+#define BNX2_DRV_MSG_DATA_WAIT1 0x00020000
+#define BNX2_DRV_MSG_DATA_WAIT2 0x00030000
+#define BNX2_DRV_MSG_DATA_WAIT3 0x00040000
+
+#define BNX2_DRV_MSG_SEQ 0x0000ffff
+
+#define BNX2_FW_MB 0x00000008
+#define BNX2_FW_MSG_ACK 0x0000ffff
+#define BNX2_FW_MSG_STATUS_MASK 0x00ff0000
+#define BNX2_FW_MSG_STATUS_OK 0x00000000
+#define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000
+
+#define BNX2_LINK_STATUS 0x0000000c
+#define BNX2_LINK_STATUS_INIT_VALUE 0xffffffff
+#define BNX2_LINK_STATUS_LINK_UP 0x1
+#define BNX2_LINK_STATUS_LINK_DOWN 0x0
+#define BNX2_LINK_STATUS_SPEED_MASK 0x1e
+#define BNX2_LINK_STATUS_AN_INCOMPLETE (0<<1)
+#define BNX2_LINK_STATUS_10HALF (1<<1)
+#define BNX2_LINK_STATUS_10FULL (2<<1)
+#define BNX2_LINK_STATUS_100HALF (3<<1)
+#define BNX2_LINK_STATUS_100BASE_T4 (4<<1)
+#define BNX2_LINK_STATUS_100FULL (5<<1)
+#define BNX2_LINK_STATUS_1000HALF (6<<1)
+#define BNX2_LINK_STATUS_1000FULL (7<<1)
+#define BNX2_LINK_STATUS_2500HALF (8<<1)
+#define BNX2_LINK_STATUS_2500FULL (9<<1)
+#define BNX2_LINK_STATUS_AN_ENABLED (1<<5)
+#define BNX2_LINK_STATUS_AN_COMPLETE (1<<6)
+#define BNX2_LINK_STATUS_PARALLEL_DET (1<<7)
+#define BNX2_LINK_STATUS_RESERVED (1<<8)
+#define BNX2_LINK_STATUS_PARTNER_AD_1000FULL (1<<9)
+#define BNX2_LINK_STATUS_PARTNER_AD_1000HALF (1<<10)
+#define BNX2_LINK_STATUS_PARTNER_AD_100BT4 (1<<11)
+#define BNX2_LINK_STATUS_PARTNER_AD_100FULL (1<<12)
+#define BNX2_LINK_STATUS_PARTNER_AD_100HALF (1<<13)
+#define BNX2_LINK_STATUS_PARTNER_AD_10FULL (1<<14)
+#define BNX2_LINK_STATUS_PARTNER_AD_10HALF (1<<15)
+#define BNX2_LINK_STATUS_TX_FC_ENABLED (1<<16)
+#define BNX2_LINK_STATUS_RX_FC_ENABLED (1<<17)
+#define BNX2_LINK_STATUS_PARTNER_SYM_PAUSE_CAP (1<<18)
+#define BNX2_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP (1<<19)
+#define BNX2_LINK_STATUS_SERDES_LINK (1<<20)
+#define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21)
+#define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22)
+
+#define BNX2_DRV_PULSE_MB 0x00000010
+#define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff
+
+/* Indicate to the firmware not to go into the
+ * OS absent when it is not getting driver pulse.
+ * This is used for debugging. */
+#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000
+
+#define BNX2_DEV_INFO_SIGNATURE 0x00000020
+#define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900
+#define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00
+#define BNX2_DEV_INFO_FEATURE_CFG_VALID 0x01
+#define BNX2_DEV_INFO_SECONDARY_PORT 0x80
+#define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE 0x40
+
+#define BNX2_SHARED_HW_CFG_PART_NUM 0x00000024
+
+#define BNX2_SHARED_HW_CFG_POWER_DISSIPATED 0x00000034
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK 0xff000000
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK 0xff0000
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK 0xff00
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK 0xff
+
+#define BNX2_SHARED_HW_CFG POWER_CONSUMED 0x00000038
+#define BNX2_SHARED_HW_CFG_CONFIG 0x0000003c
+#define BNX2_SHARED_HW_CFG_DESIGN_NIC 0
+#define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1
+#define BNX2_SHARED_HW_CFG_PHY_COPPER 0
+#define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2
+#define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20
+#define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40
+#define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8
+#define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300
+#define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0
+#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100
+#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200
+
+#define BNX2_SHARED_HW_CFG_CONFIG2 0x00000040
+#define BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK 0x00fff000
+
+#define BNX2_DEV_INFO_BC_REV 0x0000004c
+
+#define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050
+#define BNX2_PORT_HW_CFG_UPPERMAC_MASK 0xffff
+
+#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
+#define BNX2_PORT_HW_CFG_CONFIG 0x00000058
+#define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000
+#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000
+
+#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
+#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c
+#define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER 0x00000070
+#define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER 0x00000074
+#define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER 0x00000078
+#define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER 0x0000007c
+
+#define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2 0x000000b4
+
+#define BNX2_DEV_INFO_FORMAT_REV 0x000000c4
+#define BNX2_DEV_INFO_FORMAT_REV_MASK 0xff000000
+#define BNX2_DEV_INFO_FORMAT_REV_ID ('A' << 24)
+
+#define BNX2_SHARED_FEATURE 0x000000c8
+#define BNX2_SHARED_FEATURE_MASK 0xffffffff
+
+#define BNX2_PORT_FEATURE 0x000000d8
+#define BNX2_PORT2_FEATURE 0x00000014c
+#define BNX2_PORT_FEATURE_WOL_ENABLED 0x01000000
+#define BNX2_PORT_FEATURE_MBA_ENABLED 0x02000000
+#define BNX2_PORT_FEATURE_ASF_ENABLED 0x04000000
+#define BNX2_PORT_FEATURE_IMD_ENABLED 0x08000000
+#define BNX2_PORT_FEATURE_BAR1_SIZE_MASK 0xf
+#define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED 0x0
+#define BNX2_PORT_FEATURE_BAR1_SIZE_64K 0x1
+#define BNX2_PORT_FEATURE_BAR1_SIZE_128K 0x2
+#define BNX2_PORT_FEATURE_BAR1_SIZE_256K 0x3
+#define BNX2_PORT_FEATURE_BAR1_SIZE_512K 0x4
+#define BNX2_PORT_FEATURE_BAR1_SIZE_1M 0x5
+#define BNX2_PORT_FEATURE_BAR1_SIZE_2M 0x6
+#define BNX2_PORT_FEATURE_BAR1_SIZE_4M 0x7
+#define BNX2_PORT_FEATURE_BAR1_SIZE_8M 0x8
+#define BNX2_PORT_FEATURE_BAR1_SIZE_16M 0x9
+#define BNX2_PORT_FEATURE_BAR1_SIZE_32M 0xa
+#define BNX2_PORT_FEATURE_BAR1_SIZE_64M 0xb
+#define BNX2_PORT_FEATURE_BAR1_SIZE_128M 0xc
+#define BNX2_PORT_FEATURE_BAR1_SIZE_256M 0xd
+#define BNX2_PORT_FEATURE_BAR1_SIZE_512M 0xe
+#define BNX2_PORT_FEATURE_BAR1_SIZE_1G 0xf
+
+#define BNX2_PORT_FEATURE_WOL 0xdc
+#define BNX2_PORT2_FEATURE_WOL 0x150
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS 4
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK 0x30
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE 0
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC 0x10
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI 0x20
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x30
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK 0xf
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG 0
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF 1
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL 2
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF 5
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL 6
+#define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000 0x40
+#define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400
+#define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP 0x800
+
+#define BNX2_PORT_FEATURE_MBA 0xe0
+#define BNX2_PORT2_FEATURE_MBA 0x154
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS 0
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x3
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 1
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 2
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS 2
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG 0
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF 0x4
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL 0x8
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF 0xc
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL 0x10
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF 0x14
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL 0x18
+#define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x40
+#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S 0
+#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x80
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS 8
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0xff00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K 0x100
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x200
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x300
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x400
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x500
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x600
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x700
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x800
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x900
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0xa00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0xb00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0xc00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0xd00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0xe00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0xf00
+#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS 16
+#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0xf0000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS 20
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x300000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x100000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x200000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x300000
+
+#define BNX2_PORT_FEATURE_IMD 0xe4
+#define BNX2_PORT2_FEATURE_IMD 0x158
+#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT 0
+#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE 1
+
+#define BNX2_PORT_FEATURE_VLAN 0xe8
+#define BNX2_PORT2_FEATURE_VLAN 0x15c
+#define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff
+#define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000
+
+#define BNX2_BC_STATE_RESET_TYPE 0x000001c0
+#define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254
+#define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff
+#define BNX2_BC_STATE_RESET_TYPE_NONE (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00010000)
+#define BNX2_BC_STATE_RESET_TYPE_PCI (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00020000)
+#define BNX2_BC_STATE_RESET_TYPE_VAUX (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00030000)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_MASK DRV_MSG_CODE
+#define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_RESET)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_UNLOAD)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_SHUTDOWN)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_WOL)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_DIAG)
+#define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ (msg))
+
+#define BNX2_BC_STATE 0x000001c4
+#define BNX2_BC_STATE_ERR_MASK 0x0000ff00
+#define BNX2_BC_STATE_SIGN 0x42530000
+#define BNX2_BC_STATE_SIGN_MASK 0xffff0000
+#define BNX2_BC_STATE_BC1_START (BNX2_BC_STATE_SIGN | 0x1)
+#define BNX2_BC_STATE_GET_NVM_CFG1 (BNX2_BC_STATE_SIGN | 0x2)
+#define BNX2_BC_STATE_PROG_BAR (BNX2_BC_STATE_SIGN | 0x3)
+#define BNX2_BC_STATE_INIT_VID (BNX2_BC_STATE_SIGN | 0x4)
+#define BNX2_BC_STATE_GET_NVM_CFG2 (BNX2_BC_STATE_SIGN | 0x5)
+#define BNX2_BC_STATE_APPLY_WKARND (BNX2_BC_STATE_SIGN | 0x6)
+#define BNX2_BC_STATE_LOAD_BC2 (BNX2_BC_STATE_SIGN | 0x7)
+#define BNX2_BC_STATE_GOING_BC2 (BNX2_BC_STATE_SIGN | 0x8)
+#define BNX2_BC_STATE_GOING_DIAG (BNX2_BC_STATE_SIGN | 0x9)
+#define BNX2_BC_STATE_RT_FINAL_INIT (BNX2_BC_STATE_SIGN | 0x81)
+#define BNX2_BC_STATE_RT_WKARND (BNX2_BC_STATE_SIGN | 0x82)
+#define BNX2_BC_STATE_RT_DRV_PULSE (BNX2_BC_STATE_SIGN | 0x83)
+#define BNX2_BC_STATE_RT_FIOEVTS (BNX2_BC_STATE_SIGN | 0x84)
+#define BNX2_BC_STATE_RT_DRV_CMD (BNX2_BC_STATE_SIGN | 0x85)
+#define BNX2_BC_STATE_RT_LOW_POWER (BNX2_BC_STATE_SIGN | 0x86)
+#define BNX2_BC_STATE_RT_SET_WOL (BNX2_BC_STATE_SIGN | 0x87)
+#define BNX2_BC_STATE_RT_OTHER_FW (BNX2_BC_STATE_SIGN | 0x88)
+#define BNX2_BC_STATE_RT_GOING_D3 (BNX2_BC_STATE_SIGN | 0x89)
+#define BNX2_BC_STATE_ERR_BAD_VERSION (BNX2_BC_STATE_SIGN | 0x0100)
+#define BNX2_BC_STATE_ERR_BAD_BC2_CRC (BNX2_BC_STATE_SIGN | 0x0200)
+#define BNX2_BC_STATE_ERR_BC1_LOOP (BNX2_BC_STATE_SIGN | 0x0300)
+#define BNX2_BC_STATE_ERR_UNKNOWN_CMD (BNX2_BC_STATE_SIGN | 0x0400)
+#define BNX2_BC_STATE_ERR_DRV_DEAD (BNX2_BC_STATE_SIGN | 0x0500)
+#define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600)
+#define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700)
+
+#define BNX2_BC_STATE_DEBUG_CMD 0x1dc
+#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000
+#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000
+#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff
+#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff
+
+#define HOST_VIEW_SHMEM_BASE 0x167c00
+
+/* Enable or disable autonegotiation. If this is set to enable,
+ * the forced link modes above are completely ignored.
+ */
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+#define RX_OFFSET (sizeof(struct l2_fhdr) + 2)
+
+#define RX_BUF_CNT 20
+
+/* 8 for CRC and VLAN */
+#define RX_BUF_USE_SIZE (ETH_MAX_MTU + ETH_HLEN + RX_OFFSET + 8)
+
+/* 8 for alignment */
+//#define RX_BUF_SIZE (RX_BUF_USE_SIZE + 8)
+#define RX_BUF_SIZE (L1_CACHE_ALIGN(RX_BUF_USE_SIZE + 8))
+
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/davicom.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/davicom.c
new file mode 100644
index 0000000..07c5e1b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/davicom.c
@@ -0,0 +1,727 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+/*
+ DAVICOM DM9009/DM9102/DM9102A Etherboot Driver V1.00
+
+ This driver was ported from Marty Connor's Tulip Etherboot driver.
+ Thanks Marty Connor (mdc@etherboot.org)
+
+ This davicom etherboot driver supports DM9009/DM9102/DM9102A/
+ DM9102A+DM9801/DM9102A+DM9802 NICs.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+*/
+
+FILE_LICENCE ( GPL_ANY );
+
+/*********************************************************************/
+/* Revision History */
+/*********************************************************************/
+
+/*
+ 19 OCT 2000 Sten 1.00
+ Different half and full duplex mode
+ Do the different programming for DM9801/DM9802
+
+ 12 OCT 2000 Sten 0.90
+ This driver was ported from tulip driver and it
+ has the following difference.
+ Changed symbol tulip/TULIP to davicom/DAVICOM
+ Deleted some code that did not use in this driver.
+ Used chain-strcture to replace ring structure
+ for both TX/RX descriptor.
+ Allocated two tx descriptor.
+ According current media mode to set operating
+ register(CR6)
+*/
+
+
+/*********************************************************************/
+/* Declarations */
+/*********************************************************************/
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+
+#undef DAVICOM_DEBUG
+#undef DAVICOM_DEBUG_WHERE
+
+#define TX_TIME_OUT 2*TICKS_PER_SEC
+
+/* Register offsets for davicom device */
+enum davicom_offsets {
+ CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+ CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+ CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
+};
+
+/* EEPROM Address width definitions */
+#define EEPROM_ADDRLEN 6
+#define EEPROM_SIZE 32 /* 1 << EEPROM_ADDRLEN */
+/* Used to be 128, but we only need to read enough to get the MAC
+ address at bytes 20..25 */
+
+/* Data Read from the EEPROM */
+static unsigned char ee_data[EEPROM_SIZE];
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << addr_len)
+#define EE_READ_CMD (6 << addr_len)
+#define EE_ERASE_CMD (7 << addr_len)
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
+#define EE_CS 0x01 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x05
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_ENB (0x4800 | EE_CS)
+
+/* Sten 10/11 for phyxcer */
+#define PHY_DATA_0 0x0
+#define PHY_DATA_1 0x20000
+#define MDCLKH 0x10000
+
+/* Delay between EEPROM clock transitions. Even at 33Mhz current PCI
+ implementations don't overrun the EEPROM clock. We add a bus
+ turn-around to insure that this remains true. */
+#define eeprom_delay() inl(ee_addr)
+
+/* helpful macro if on a big_endian machine for changing byte order.
+ not strictly needed on Intel
+ Already defined in Etherboot includes
+#define le16_to_cpu(val) (val)
+*/
+
+/* transmit and receive descriptor format */
+struct txdesc {
+ volatile unsigned long status; /* owner, status */
+ unsigned long buf1sz:11, /* size of buffer 1 */
+ buf2sz:11, /* size of buffer 2 */
+ control:10; /* control bits */
+ const unsigned char *buf1addr; /* buffer 1 address */
+ const unsigned char *buf2addr; /* buffer 2 address */
+};
+
+struct rxdesc {
+ volatile unsigned long status; /* owner, status */
+ unsigned long buf1sz:11, /* size of buffer 1 */
+ buf2sz:11, /* size of buffer 2 */
+ control:10; /* control bits */
+ unsigned char *buf1addr; /* buffer 1 address */
+ unsigned char *buf2addr; /* buffer 2 address */
+};
+
+/* Size of transmit and receive buffers */
+#define BUFLEN 1536
+
+/*********************************************************************/
+/* Global Storage */
+/*********************************************************************/
+
+static struct nic_operations davicom_operations;
+
+/* PCI Bus parameters */
+static unsigned short vendor, dev_id;
+static unsigned long ioaddr;
+
+/* Note: transmit and receive buffers must be longword aligned and
+ longword divisable */
+
+/* transmit descriptor and buffer */
+#define NTXD 2
+#define NRXD 4
+struct {
+ struct txdesc txd[NTXD] __attribute__ ((aligned(4)));
+ unsigned char txb[BUFLEN] __attribute__ ((aligned(4)));
+ struct rxdesc rxd[NRXD] __attribute__ ((aligned(4)));
+ unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4)));
+} davicom_bufs __shared;
+#define txd davicom_bufs.txd
+#define txb davicom_bufs.txb
+#define rxd davicom_bufs.rxd
+#define rxb davicom_bufs.rxb
+static int rxd_tail;
+static int TxPtr;
+
+
+/*********************************************************************/
+/* Function Prototypes */
+/*********************************************************************/
+static void whereami(const char *str);
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
+static int davicom_probe(struct nic *nic,struct pci_device *pci);
+static void davicom_init_chain(struct nic *nic); /* Sten 10/9 */
+static void davicom_reset(struct nic *nic);
+static void davicom_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p);
+static int davicom_poll(struct nic *nic, int retrieve);
+static void davicom_disable(struct nic *nic);
+#ifdef DAVICOM_DEBUG
+static void davicom_more(void);
+#endif /* DAVICOM_DEBUG */
+static void davicom_wait(unsigned int nticks);
+static int phy_read(int);
+static void phy_write(int, u16);
+static void phy_write_1bit(u32, u32);
+static int phy_read_1bit(u32);
+static void davicom_media_chk(struct nic *);
+
+
+/*********************************************************************/
+/* Utility Routines */
+/*********************************************************************/
+static inline void whereami(const char *str)
+{
+ printf("%s\n", str);
+ /* sleep(2); */
+}
+
+#ifdef DAVICOM_DEBUG
+static void davicom_more()
+{
+ printf("\n\n-- more --");
+ while (!iskey())
+ /* wait */;
+ getchar();
+ printf("\n\n");
+}
+#endif /* DAVICOM_DEBUG */
+
+static void davicom_wait(unsigned int nticks)
+{
+ unsigned int to = currticks() + nticks;
+ while (currticks() < to)
+ /* wait */ ;
+}
+
+
+/*********************************************************************/
+/* For DAVICOM phyxcer register by MII interface */
+/*********************************************************************/
+/*
+ Read a word data from phy register
+*/
+static int phy_read(int location)
+{
+ int i, phy_addr=1;
+ u16 phy_data;
+ u32 io_dcr9;
+
+ whereami("phy_read\n");
+
+ io_dcr9 = ioaddr + CSR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i=0; i<34; i++)
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+
+ /* Send Phy addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* Send register addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* Skip transition state */
+ phy_read_1bit(io_dcr9);
+
+ /* read 16bit data */
+ for (phy_data=0, i=0; i<16; i++) {
+ phy_data<<=1;
+ phy_data|=phy_read_1bit(io_dcr9);
+ }
+
+ return phy_data;
+}
+
+/*
+ Write a word to Phy register
+*/
+static void phy_write(int location, u16 phy_data)
+{
+ u16 i, phy_addr=1;
+ u32 io_dcr9;
+
+ whereami("phy_write\n");
+
+ io_dcr9 = ioaddr + CSR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i=0; i<34; i++)
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+
+ /* Send Phy addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* Send register addres */
+ for (i=0x10; i>0; i=i>>1)
+ phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0);
+
+ /* written trasnition */
+ phy_write_1bit(io_dcr9, PHY_DATA_1);
+ phy_write_1bit(io_dcr9, PHY_DATA_0);
+
+ /* Write a word data to PHY controller */
+ for (i=0x8000; i>0; i>>=1)
+ phy_write_1bit(io_dcr9, phy_data&i ? PHY_DATA_1: PHY_DATA_0);
+}
+
+/*
+ Write one bit data to Phy Controller
+*/
+static void phy_write_1bit(u32 ee_addr, u32 phy_data)
+{
+ whereami("phy_write_1bit\n");
+ outl(phy_data, ee_addr); /* MII Clock Low */
+ eeprom_delay();
+ outl(phy_data|MDCLKH, ee_addr); /* MII Clock High */
+ eeprom_delay();
+ outl(phy_data, ee_addr); /* MII Clock Low */
+ eeprom_delay();
+}
+
+/*
+ Read one bit phy data from PHY controller
+*/
+static int phy_read_1bit(u32 ee_addr)
+{
+ int phy_data;
+
+ whereami("phy_read_1bit\n");
+
+ outl(0x50000, ee_addr);
+ eeprom_delay();
+
+ phy_data=(inl(ee_addr)>>19) & 0x1;
+
+ outl(0x40000, ee_addr);
+ eeprom_delay();
+
+ return phy_data;
+}
+
+/*
+ DM9801/DM9802 present check and program
+*/
+static void HPNA_process(void)
+{
+
+ if ( (phy_read(3) & 0xfff0) == 0xb900 ) {
+ if ( phy_read(31) == 0x4404 ) {
+ /* DM9801 present */
+ if (phy_read(3) == 0xb901)
+ phy_write(16, 0x5); /* DM9801 E4 */
+ else
+ phy_write(16, 0x1005); /* DM9801 E3 and others */
+ phy_write(25, ((phy_read(24) + 3) & 0xff) | 0xf000);
+ } else {
+ /* DM9802 present */
+ phy_write(16, 0x5);
+ phy_write(25, (phy_read(25) & 0xff00) + 2);
+ }
+ }
+}
+
+/*
+ Sense media mode and set CR6
+*/
+static void davicom_media_chk(struct nic * nic __unused)
+{
+ unsigned long to, csr6;
+
+ csr6 = 0x00200000; /* SF */
+ outl(csr6, ioaddr + CSR6);
+
+#define PCI_DEVICE_ID_DM9009 0x9009
+ if (vendor == PCI_VENDOR_ID_DAVICOM && dev_id == PCI_DEVICE_ID_DM9009) {
+ /* Set to 10BaseT mode for DM9009 */
+ phy_write(0, 0);
+ } else {
+ /* For DM9102/DM9102A */
+ to = currticks() + 2 * TICKS_PER_SEC;
+ while ( ((phy_read(1) & 0x24)!=0x24) && (currticks() < to))
+ /* wait */ ;
+
+ if ( (phy_read(1) & 0x24) == 0x24 ) {
+ if (phy_read(17) & 0xa000)
+ csr6 |= 0x00000200; /* Full Duplex mode */
+ } else
+ csr6 |= 0x00040000; /* Select DM9801/DM9802 when Ethernet link failed */
+ }
+
+ /* set the chip's operating mode */
+ outl(csr6, ioaddr + CSR6);
+
+ /* DM9801/DM9802 present check & program */
+ if (csr6 & 0x40000)
+ HPNA_process();
+}
+
+
+/*********************************************************************/
+/* EEPROM Reading Code */
+/*********************************************************************/
+/* EEPROM routines adapted from the Linux Tulip Code */
+/* Reading a serial EEPROM is a "bit" grungy, but we work our way
+ through:->.
+*/
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
+{
+ int i;
+ unsigned short retval = 0;
+ long ee_addr = ioaddr + CSR9;
+ int read_cmd = location | EE_READ_CMD;
+
+ whereami("read_eeprom\n");
+
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ outl(EE_ENB, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, ee_addr);
+ eeprom_delay();
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ }
+ outl(EE_ENB, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, ee_addr);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ return retval;
+}
+
+/*********************************************************************/
+/* davicom_init_chain - setup the tx and rx descriptors */
+/* Sten 10/9 */
+/*********************************************************************/
+static void davicom_init_chain(struct nic *nic)
+{
+ int i;
+
+ /* setup the transmit descriptor */
+ /* Sten: Set 2 TX descriptor but use one TX buffer because
+ it transmit a packet and wait complete every time. */
+ for (i=0; i<NTXD; i++) {
+ txd[i].buf1addr = (void *)virt_to_bus(&txb[0]); /* Used same TX buffer */
+ txd[i].buf2addr = (void *)virt_to_bus(&txd[i+1]); /* Point to Next TX desc */
+ txd[i].buf1sz = 0;
+ txd[i].buf2sz = 0;
+ txd[i].control = 0x184; /* Begin/End/Chain */
+ txd[i].status = 0x00000000; /* give ownership to Host */
+ }
+
+ /* construct perfect filter frame with mac address as first match
+ and broadcast address for all others */
+ for (i=0; i<192; i++) txb[i] = 0xFF;
+ txb[0] = nic->node_addr[0];
+ txb[1] = nic->node_addr[1];
+ txb[4] = nic->node_addr[2];
+ txb[5] = nic->node_addr[3];
+ txb[8] = nic->node_addr[4];
+ txb[9] = nic->node_addr[5];
+
+ /* setup receive descriptor */
+ for (i=0; i<NRXD; i++) {
+ rxd[i].buf1addr = (void *)virt_to_bus(&rxb[i * BUFLEN]);
+ rxd[i].buf2addr = (void *)virt_to_bus(&rxd[i+1]); /* Point to Next RX desc */
+ rxd[i].buf1sz = BUFLEN;
+ rxd[i].buf2sz = 0; /* not used */
+ rxd[i].control = 0x4; /* Chain Structure */
+ rxd[i].status = 0x80000000; /* give ownership to device */
+ }
+
+ /* Chain the last descriptor to first */
+ txd[NTXD - 1].buf2addr = (void *)virt_to_bus(&txd[0]);
+ rxd[NRXD - 1].buf2addr = (void *)virt_to_bus(&rxd[0]);
+ TxPtr = 0;
+ rxd_tail = 0;
+}
+
+
+/*********************************************************************/
+/* davicom_reset - Reset adapter */
+/*********************************************************************/
+static void davicom_reset(struct nic *nic)
+{
+ unsigned long to;
+
+ whereami("davicom_reset\n");
+
+ /* Stop Tx and RX */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+ outl(0x00000001, ioaddr + CSR0);
+
+ davicom_wait(TICKS_PER_SEC);
+
+ /* TX/RX descriptor burst */
+ outl(0x0C00000, ioaddr + CSR0); /* Sten 10/9 */
+
+ /* set up transmit and receive descriptors */
+ davicom_init_chain(nic); /* Sten 10/9 */
+
+ /* Point to receive descriptor */
+ outl(virt_to_bus(&rxd[0]), ioaddr + CSR3);
+ outl(virt_to_bus(&txd[0]), ioaddr + CSR4); /* Sten 10/9 */
+
+ /* According phyxcer media mode to set CR6,
+ DM9102/A phyxcer can auto-detect media mode */
+ davicom_media_chk(nic);
+
+ /* Prepare Setup Frame Sten 10/9 */
+ txd[TxPtr].buf1sz = 192;
+ txd[TxPtr].control = 0x024; /* SF/CE */
+ txd[TxPtr].status = 0x80000000; /* Give ownership to device */
+
+ /* Start Tx */
+ outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6);
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((txd[TxPtr].status & 0x80000000) && (currticks() < to)) /* Sten 10/9 */
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ printf ("TX Setup Timeout!\n");
+ }
+ /* Point to next TX descriptor */
+ TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */
+
+#ifdef DAVICOM_DEBUG
+ printf("txd.status = %X\n", txd.status);
+ printf("ticks = %d\n", currticks() - (to - TX_TIME_OUT));
+ davicom_more();
+#endif
+
+ /* enable RX */
+ outl(inl(ioaddr + CSR6) | 0x00000002, ioaddr + CSR6);
+ /* immediate poll demand */
+ outl(0, ioaddr + CSR2);
+}
+
+
+/*********************************************************************/
+/* eth_transmit - Transmit a frame */
+/*********************************************************************/
+static void davicom_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p)
+{
+ unsigned long to;
+
+ whereami("davicom_transmit\n");
+
+ /* Stop Tx */
+ /* outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6); */
+
+ /* setup ethernet header */
+ memcpy(&txb[0], d, ETH_ALEN); /* DA 6byte */
+ memcpy(&txb[ETH_ALEN], nic->node_addr, ETH_ALEN); /* SA 6byte*/
+ txb[ETH_ALEN*2] = (t >> 8) & 0xFF; /* Frame type: 2byte */
+ txb[ETH_ALEN*2+1] = t & 0xFF;
+ memcpy(&txb[ETH_HLEN], p, s); /* Frame data */
+
+ /* setup the transmit descriptor */
+ txd[TxPtr].buf1sz = ETH_HLEN+s;
+ txd[TxPtr].control = 0x00000184; /* LS+FS+CE */
+ txd[TxPtr].status = 0x80000000; /* give ownership to device */
+
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((txd[TxPtr].status & 0x80000000) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ printf ("TX Timeout!\n");
+ }
+
+ /* Point to next TX descriptor */
+ TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */
+
+}
+
+/*********************************************************************/
+/* eth_poll - Wait for a frame */
+/*********************************************************************/
+static int davicom_poll(struct nic *nic, int retrieve)
+{
+ whereami("davicom_poll\n");
+
+ if (rxd[rxd_tail].status & 0x80000000)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ whereami("davicom_poll got one\n");
+
+ nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
+
+ if( rxd[rxd_tail].status & 0x00008000){
+ rxd[rxd_tail].status = 0x80000000;
+ rxd_tail++;
+ if (rxd_tail == NRXD) rxd_tail = 0;
+ return 0;
+ }
+
+ /* copy packet to working buffer */
+ /* XXX - this copy could be avoided with a little more work
+ but for now we are content with it because the optimised
+ memcpy is quite fast */
+
+ memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen);
+
+ /* return the descriptor and buffer to receive ring */
+ rxd[rxd_tail].status = 0x80000000;
+ rxd_tail++;
+ if (rxd_tail == NRXD) rxd_tail = 0;
+
+ return 1;
+}
+
+/*********************************************************************/
+/* eth_disable - Disable the interface */
+/*********************************************************************/
+static void davicom_disable ( struct nic *nic ) {
+
+ whereami("davicom_disable\n");
+
+ davicom_reset(nic);
+
+ /* disable interrupts */
+ outl(0x00000000, ioaddr + CSR7);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+}
+
+
+/*********************************************************************/
+/* eth_irq - enable, disable and force interrupts */
+/*********************************************************************/
+static void davicom_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+
+/*********************************************************************/
+/* eth_probe - Look for an adapter */
+/*********************************************************************/
+static int davicom_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ unsigned int i;
+
+ whereami("davicom_probe\n");
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ vendor = pci->vendor;
+ dev_id = pci->device;
+ ioaddr = pci->ioaddr;
+
+ nic->ioaddr = pci->ioaddr;
+ nic->irqno = 0;
+
+ /* wakeup chip */
+ pci_write_config_dword(pci, 0x40, 0x00000000);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+
+ /* Get MAC Address */
+ /* read EEPROM data */
+ for (i = 0; i < sizeof(ee_data)/2; i++)
+ ((unsigned short *)ee_data)[i] =
+ le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
+
+ /* extract MAC address from EEPROM buffer */
+ for (i=0; i<ETH_ALEN; i++)
+ nic->node_addr[i] = ee_data[20+i];
+
+ DBG ( "Davicom %s at IOADDR %4.4lx\n", eth_ntoa ( nic->node_addr ), ioaddr );
+
+ /* initialize device */
+ davicom_reset(nic);
+ nic->nic_op = &davicom_operations;
+ return 1;
+}
+
+static struct nic_operations davicom_operations = {
+ .connect = dummy_connect,
+ .poll = davicom_poll,
+ .transmit = davicom_transmit,
+ .irq = davicom_irq,
+
+};
+
+static struct pci_device_id davicom_nics[] = {
+PCI_ROM(0x1282, 0x9100, "davicom9100", "Davicom 9100", 0),
+PCI_ROM(0x1282, 0x9102, "davicom9102", "Davicom 9102", 0),
+PCI_ROM(0x1282, 0x9009, "davicom9009", "Davicom 9009", 0),
+PCI_ROM(0x1282, 0x9132, "davicom9132", "Davicom 9132", 0), /* Needs probably some fixing */
+};
+
+PCI_DRIVER ( davicom_driver, davicom_nics, PCI_NO_CLASS );
+
+DRIVER ( "DAVICOM", nic_driver, pci_driver, davicom_driver,
+ davicom_probe, davicom_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/depca.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/depca.c
new file mode 100644
index 0000000..ea85cbe
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/depca.c
@@ -0,0 +1,805 @@
+/* #warning "depca.c: FIXME: fix relocation" */
+
+FILE_LICENCE ( GPL_ANY );
+
+#if 0
+/* Not fixed for relocation yet. Probably won't work relocated above 16MB */
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+/* Etherboot: depca.h merged, comments from Linux driver retained */
+/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
+
+ Written 1994, 1995 by David C. Davies.
+
+
+ Copyright 1994 David C. Davies
+ and
+ United States Government
+ (as represented by the Director, National Security Agency).
+
+ Copyright 1995 Digital Equipment Corporation.
+
+
+ This software may be used and distributed according to the terms of
+ the GNU Public License, incorporated herein by reference.
+
+ This driver is written for the Digital Equipment Corporation series
+ of DEPCA and EtherWORKS ethernet cards:
+
+ DEPCA (the original)
+ DE100
+ DE101
+ DE200 Turbo
+ DE201 Turbo
+ DE202 Turbo (TP BNC)
+ DE210
+ DE422 (EISA)
+
+ The driver has been tested on DE100, DE200 and DE202 cards in a
+ relatively busy network. The DE422 has been tested a little.
+
+ This driver will NOT work for the DE203, DE204 and DE205 series of
+ cards, since they have a new custom ASIC in place of the AMD LANCE
+ chip. See the 'ewrk3.c' driver in the Linux source tree for running
+ those cards.
+
+ I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from)
+ a DECstation 5000/200.
+
+ The author may be reached at davies@maniac.ultranet.com
+
+ =========================================================================
+
+ The driver was originally based on the 'lance.c' driver from Donald
+ Becker which is included with the standard driver distribution for
+ linux. V0.4 is a complete re-write with only the kernel interface
+ remaining from the original code.
+
+ 1) Lance.c code in /linux/drivers/net/
+ 2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook",
+ AMD, 1992 [(800) 222-9323].
+ 3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
+ AMD, Pub. #17881, May 1993.
+ 4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA",
+ AMD, Pub. #16907, May 1992
+ 5) "DEC EtherWORKS LC Ethernet Controller Owners Manual",
+ Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003
+ 6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual",
+ Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003
+ 7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR
+ Digital Equipment Corporation, 1989
+ 8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
+ Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
+
+
+ Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
+ driver.
+
+ The original DEPCA card requires that the ethernet ROM address counter
+ be enabled to count and has an 8 bit NICSR. The ROM counter enabling is
+ only done when a 0x08 is read as the first address octet (to minimise
+ the chances of writing over some other hardware's I/O register). The
+ NICSR accesses have been changed to byte accesses for all the cards
+ supported by this driver, since there is only one useful bit in the MSB
+ (remote boot timeout) and it is not used. Also, there is a maximum of
+ only 48kB network RAM for this card. My thanks to Torbjorn Lindh for
+ help debugging all this (and holding my feet to the fire until I got it
+ right).
+
+ The DE200 series boards have on-board 64kB RAM for use as a shared
+ memory network buffer. Only the DE100 cards make use of a 2kB buffer
+ mode which has not been implemented in this driver (only the 32kB and
+ 64kB modes are supported [16kB/48kB for the original DEPCA]).
+
+ At the most only 2 DEPCA cards can be supported on the ISA bus because
+ there is only provision for two I/O base addresses on each card (0x300
+ and 0x200). The I/O address is detected by searching for a byte sequence
+ in the Ethernet station address PROM at the expected I/O address for the
+ Ethernet PROM. The shared memory base address is 'autoprobed' by
+ looking for the self test PROM and detecting the card name. When a
+ second DEPCA is detected, information is placed in the base_addr
+ variable of the next device structure (which is created if necessary),
+ thus enabling ethif_probe initialization for the device. More than 2
+ EISA cards can be supported, but care will be needed assigning the
+ shared memory to ensure that each slot has the correct IRQ, I/O address
+ and shared memory address assigned.
+
+ ************************************************************************
+
+ NOTE: If you are using two ISA DEPCAs, it is important that you assign
+ the base memory addresses correctly. The driver autoprobes I/O 0x300
+ then 0x200. The base memory address for the first device must be less
+ than that of the second so that the auto probe will correctly assign the
+ I/O and memory addresses on the same card. I can't think of a way to do
+ this unambiguously at the moment, since there is nothing on the cards to
+ tie I/O and memory information together.
+
+ I am unable to test 2 cards together for now, so this code is
+ unchecked. All reports, good or bad, are welcome.
+
+ ************************************************************************
+
+ The board IRQ setting must be at an unused IRQ which is auto-probed
+ using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
+ {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is
+ really IRQ9 in machines with 16 IRQ lines.
+
+ No 16MB memory limitation should exist with this driver as DMA is not
+ used and the common memory area is in low memory on the network card (my
+ current system has 20MB and I've not had problems yet).
+
+ The ability to load this driver as a loadable module has been added. To
+ utilise this ability, you have to do <8 things:
+
+ 0) have a copy of the loadable modules code installed on your system.
+ 1) copy depca.c from the /linux/drivers/net directory to your favourite
+ temporary directory.
+ 2) if you wish, edit the source code near line 1530 to reflect the I/O
+ address and IRQ you're using (see also 5).
+ 3) compile depca.c, but include -DMODULE in the command line to ensure
+ that the correct bits are compiled (see end of source code).
+ 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
+ kernel with the depca configuration turned off and reboot.
+ 5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
+ [Alan Cox: Changed the code to allow command line irq/io assignments]
+ [Dave Davies: Changed the code to allow command line mem/name
+ assignments]
+ 6) run the net startup bits for your eth?? interface manually
+ (usually /etc/rc.inet[12] at boot time).
+ 7) enjoy!
+
+ Note that autoprobing is not allowed in loadable modules - the system is
+ already up and running and you're messing with interrupts.
+
+ To unload a module, turn off the associated interface
+ 'ifconfig eth?? down' then 'rmmod depca'.
+
+ To assign a base memory address for the shared memory when running as a
+ loadable module, see 5 above. To include the adapter name (if you have
+ no PROM but know the card name) also see 5 above. Note that this last
+ option will not work with kernel built-in depca's.
+
+ The shared memory assignment for a loadable module makes sense to avoid
+ the 'memory autoprobe' picking the wrong shared memory (for the case of
+ 2 depca's in a PC).
+
+ ************************************************************************
+ Support for MCA EtherWORKS cards added 11-3-98.
+ Verified to work with up to 2 DE212 cards in a system (although not
+ fully stress-tested).
+
+ Currently known bugs/limitations:
+
+ Note: with the MCA stuff as a module, it trusts the MCA configuration,
+ not the command line for IRQ and memory address. You can
+ specify them if you want, but it will throw your values out.
+ You still have to pass the IO address it was configured as
+ though.
+
+ ************************************************************************
+ TO DO:
+ ------
+
+
+ Revision History
+ ----------------
+
+ Version Date Description
+
+ 0.1 25-jan-94 Initial writing.
+ 0.2 27-jan-94 Added LANCE TX hardware buffer chaining.
+ 0.3 1-feb-94 Added multiple DEPCA support.
+ 0.31 4-feb-94 Added DE202 recognition.
+ 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support.
+ 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable.
+ Add jabber packet fix from murf@perftech.com
+ and becker@super.org
+ 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access.
+ 0.35 8-mar-94 Added DE201 recognition. Tidied up.
+ 0.351 30-apr-94 Added EISA support. Added DE422 recognition.
+ 0.36 16-may-94 DE422 fix released.
+ 0.37 22-jul-94 Added MODULE support
+ 0.38 15-aug-94 Added DBR ROM switch in depca_close().
+ Multi DEPCA bug fix.
+ 0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0.
+ 0.381 12-dec-94 Added DE101 recognition, fix multicast bug.
+ 0.382 9-feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>.
+ 0.383 22-feb-95 Fix for conflict with VESA SCSI reported by
+ <stromain@alf.dec.com>
+ 0.384 17-mar-95 Fix a ring full bug reported by <bkm@star.rl.ac.uk>
+ 0.385 3-apr-95 Fix a recognition bug reported by
+ <ryan.niemi@lastfrontier.com>
+ 0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility
+ 0.40 25-May-95 Rewrite for portability & updated.
+ ALPHA support from <jestabro@amt.tay1.dec.com>
+ 0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from
+ suggestion by <heiko@colossus.escape.de>
+ 0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable
+ modules.
+ Add 'adapter_name' for loadable modules when no PROM.
+ Both above from a suggestion by
+ <pchen@woodruffs121.residence.gatech.edu>.
+ Add new multicasting code.
+ 0.421 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi>
+ 0.422 29-Apr-96 Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
+ 0.423 7-Jun-96 Fix module load bug <kmg@barco.be>
+ 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c
+ 0.44 1-Sep-97 Fix *_probe() to test check_region() first - bug
+ reported by <mmogilvi@elbert.uccs.edu>
+ 0.45 3-Nov-98 Added support for MCA EtherWORKS (DE210/DE212) cards
+ by <tymm@computer.org>
+ 0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
+ 0.5 14-Nov-98 Re-spin for 2.1.x kernels.
+ 0.51 27-Jun-99 Correct received packet length for CRC from
+ report by <worm@dkik.dk>
+
+ =========================================================================
+*/
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/isa.h>
+#include "console.h"
+#include <gpxe/ethernet.h>
+
+/*
+** I/O addresses. Note that the 2k buffer option is not supported in
+** this driver.
+*/
+#define DEPCA_NICSR 0x00 /* Network interface CSR */
+#define DEPCA_RBI 0x02 /* RAM buffer index (2k buffer mode) */
+#define DEPCA_DATA 0x04 /* LANCE registers' data port */
+#define DEPCA_ADDR 0x06 /* LANCE registers' address port */
+#define DEPCA_HBASE 0x08 /* EISA high memory base address reg. */
+#define DEPCA_PROM 0x0c /* Ethernet address ROM data port */
+#define DEPCA_CNFG 0x0c /* EISA Configuration port */
+#define DEPCA_RBSA 0x0e /* RAM buffer starting address (2k buff.) */
+
+/*
+** These are LANCE registers addressable through nic->ioaddr + DEPCA_ADDR
+*/
+#define CSR0 0
+#define CSR1 1
+#define CSR2 2
+#define CSR3 3
+
+/*
+** NETWORK INTERFACE CSR (NI_CSR) bit definitions
+*/
+
+#define TO 0x0100 /* Time Out for remote boot */
+#define SHE 0x0080 /* SHadow memory Enable */
+#define BS 0x0040 /* Bank Select */
+#define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */
+#define RBE 0x0010 /* Remote Boot Enable (1->net boot) */
+#define AAC 0x0008 /* Address ROM Address Counter (1->enable) */
+#define _128KB 0x0008 /* 128kB Network RAM (1->enable) */
+#define IM 0x0004 /* Interrupt Mask (1->mask) */
+#define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */
+#define LED 0x0001 /* LED control */
+
+/*
+** Control and Status Register 0 (CSR0) bit definitions
+*/
+
+#define ERR 0x8000 /* Error summary */
+#define BABL 0x4000 /* Babble transmitter timeout error */
+#define CERR 0x2000 /* Collision Error */
+#define MISS 0x1000 /* Missed packet */
+#define MERR 0x0800 /* Memory Error */
+#define RINT 0x0400 /* Receiver Interrupt */
+#define TINT 0x0200 /* Transmit Interrupt */
+#define IDON 0x0100 /* Initialization Done */
+#define INTR 0x0080 /* Interrupt Flag */
+#define INEA 0x0040 /* Interrupt Enable */
+#define RXON 0x0020 /* Receiver on */
+#define TXON 0x0010 /* Transmitter on */
+#define TDMD 0x0008 /* Transmit Demand */
+#define STOP 0x0004 /* Stop */
+#define STRT 0x0002 /* Start */
+#define INIT 0x0001 /* Initialize */
+#define INTM 0xff00 /* Interrupt Mask */
+#define INTE 0xfff0 /* Interrupt Enable */
+
+/*
+** CONTROL AND STATUS REGISTER 3 (CSR3)
+*/
+
+#define BSWP 0x0004 /* Byte SWaP */
+#define ACON 0x0002 /* ALE control */
+#define BCON 0x0001 /* Byte CONtrol */
+
+/*
+** Initialization Block Mode Register
+*/
+
+#define PROM 0x8000 /* Promiscuous Mode */
+#define EMBA 0x0080 /* Enable Modified Back-off Algorithm */
+#define INTL 0x0040 /* Internal Loopback */
+#define DRTY 0x0020 /* Disable Retry */
+#define COLL 0x0010 /* Force Collision */
+#define DTCR 0x0008 /* Disable Transmit CRC */
+#define LOOP 0x0004 /* Loopback */
+#define DTX 0x0002 /* Disable the Transmitter */
+#define DRX 0x0001 /* Disable the Receiver */
+
+/*
+** Receive Message Descriptor 1 (RMD1) bit definitions.
+*/
+
+#define R_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */
+#define R_ERR 0x4000 /* Error Summary */
+#define R_FRAM 0x2000 /* Framing Error */
+#define R_OFLO 0x1000 /* Overflow Error */
+#define R_CRC 0x0800 /* CRC Error */
+#define R_BUFF 0x0400 /* Buffer Error */
+#define R_STP 0x0200 /* Start of Packet */
+#define R_ENP 0x0100 /* End of Packet */
+
+/*
+** Transmit Message Descriptor 1 (TMD1) bit definitions.
+*/
+
+#define T_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */
+#define T_ERR 0x4000 /* Error Summary */
+#define T_ADD_FCS 0x2000 /* More the 1 retry needed to Xmit */
+#define T_MORE 0x1000 /* >1 retry to transmit packet */
+#define T_ONE 0x0800 /* 1 try needed to transmit the packet */
+#define T_DEF 0x0400 /* Deferred */
+#define T_STP 0x02000000 /* Start of Packet */
+#define T_ENP 0x01000000 /* End of Packet */
+#define T_FLAGS 0xff000000 /* TX Flags Field */
+
+/*
+** Transmit Message Descriptor 3 (TMD3) bit definitions.
+*/
+
+#define TMD3_BUFF 0x8000 /* BUFFer error */
+#define TMD3_UFLO 0x4000 /* UnderFLOw error */
+#define TMD3_RES 0x2000 /* REServed */
+#define TMD3_LCOL 0x1000 /* Late COLlision */
+#define TMD3_LCAR 0x0800 /* Loss of CARrier */
+#define TMD3_RTRY 0x0400 /* ReTRY error */
+
+/*
+** Ethernet PROM defines
+*/
+#define PROBE_LENGTH 32
+
+/*
+** Set the number of Tx and Rx buffers. Ensure that the memory requested
+** here is <= to the amount of shared memory set up by the board switches.
+** The number of descriptors MUST BE A POWER OF 2.
+**
+** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
+*/
+#define NUM_RX_DESC 2 /* Number of RX descriptors */
+#define NUM_TX_DESC 2 /* Number of TX descriptors */
+#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */
+#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */
+
+/*
+** ISA Bus defines
+*/
+#ifndef DEPCA_MODEL
+#define DEPCA_MODEL DEPCA
+#endif
+
+static enum {
+ DEPCA, DE100, DE101, DE200, DE201, DE202, DE210, DE212, DE422, unknown
+} adapter = DEPCA_MODEL;
+
+/*
+** Name <-> Adapter mapping
+*/
+
+static char *adapter_name[] = {
+ "DEPCA",
+ "DE100","DE101",
+ "DE200","DE201","DE202",
+ "DE210","DE212",
+ "DE422",
+ ""
+};
+
+#ifndef DEPCA_RAM_BASE
+#define DEPCA_RAM_BASE 0xd0000
+#endif
+
+/*
+** Memory Alignment. Each descriptor is 4 longwords long. To force a
+** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
+** DESC_ALIGN. ALIGN aligns the start address of the private memory area
+** and hence the RX descriptor ring's first entry.
+*/
+#define ALIGN4 ((u32)4 - 1) /* 1 longword align */
+#define ALIGN8 ((u32)8 - 1) /* 2 longword (quadword) align */
+#define ALIGN ALIGN8 /* Keep the LANCE happy... */
+
+/*
+** The DEPCA Rx and Tx ring descriptors.
+*/
+struct depca_rx_desc {
+ volatile s32 base;
+ s16 buf_length; /* This length is negative 2's complement! */
+ s16 msg_length; /* This length is "normal". */
+};
+
+struct depca_tx_desc {
+ volatile s32 base;
+ s16 length; /* This length is negative 2's complement! */
+ s16 misc; /* Errors and TDR info */
+};
+
+#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM
+ to LANCE memory address space */
+
+/*
+** The Lance initialization block, described in databook, in common memory.
+*/
+struct depca_init {
+ u16 mode; /* Mode register */
+ u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */
+ u8 mcast_table[8]; /* Multicast Hash Table. */
+ u32 rx_ring; /* Rx ring base pointer & ring length */
+ u32 tx_ring; /* Tx ring base pointer & ring length */
+};
+
+struct depca_private {
+ struct depca_rx_desc *rx_ring;
+ struct depca_tx_desc *tx_ring;
+ struct depca_init init_block; /* Shadow init block */
+ char *rx_memcpy[NUM_RX_DESC];
+ char *tx_memcpy[NUM_TX_DESC];
+ u32 bus_offset; /* ISA bus address offset */
+ u32 sh_mem; /* address of shared mem */
+ u32 dma_buffs; /* Rx & Tx buffer start */
+ int rx_cur, tx_cur; /* Next free ring entry */
+ int txRingMask, rxRingMask;
+ s32 rx_rlen, tx_rlen;
+ /* log2([rt]xRingMask+1) for the descriptors */
+};
+
+static Address mem_start = DEPCA_RAM_BASE;
+static Address mem_len, offset;
+static struct depca_private lp;
+
+/*
+** Miscellaneous defines...
+*/
+#define STOP_DEPCA(ioaddr) \
+ outw(CSR0, ioaddr + DEPCA_ADDR);\
+ outw(STOP, ioaddr + DEPCA_DATA)
+
+/* Initialize the lance Rx and Tx descriptor rings. */
+static void depca_init_ring(struct nic *nic)
+{
+ int i;
+ u32 p;
+
+ lp.rx_cur = lp.tx_cur = 0;
+ /* Initialize the base addresses and length of each buffer in the ring */
+ for (i = 0; i <= lp.rxRingMask; i++) {
+ writel((p = lp.dma_buffs + i * RX_BUFF_SZ) | R_OWN, &lp.rx_ring[i].base);
+ writew(-RX_BUFF_SZ, &lp.rx_ring[i].buf_length);
+ lp.rx_memcpy[i] = (char *) (p + lp.bus_offset);
+ }
+ for (i = 0; i <= lp.txRingMask; i++) {
+ writel((p = lp.dma_buffs + (i + lp.txRingMask + 1) * TX_BUFF_SZ) & 0x00ffffff, &lp.tx_ring[i].base);
+ lp.tx_memcpy[i] = (char *) (p + lp.bus_offset);
+ }
+
+ /* Set up the initialization block */
+ lp.init_block.rx_ring = ((u32) ((u32) lp.rx_ring) & LA_MASK) | lp.rx_rlen;
+ lp.init_block.tx_ring = ((u32) ((u32) lp.tx_ring) & LA_MASK) | lp.tx_rlen;
+ for (i = 0; i < ETH_ALEN; i++)
+ lp.init_block.phys_addr[i] = nic->node_addr[i];
+ lp.init_block.mode = 0x0000; /* Enable the Tx and Rx */
+ memset(lp.init_block.mcast_table, 0, sizeof(lp.init_block.mcast_table));
+}
+
+static inline void LoadCSRs(struct nic *nic)
+{
+ outw(CSR1, nic->ioaddr + DEPCA_ADDR); /* initialisation block address LSW */
+ outw((u16) (lp.sh_mem & LA_MASK), nic->ioaddr + DEPCA_DATA);
+ outw(CSR2, nic->ioaddr + DEPCA_ADDR); /* initialisation block address MSW */
+ outw((u16) ((lp.sh_mem & LA_MASK) >> 16), nic->ioaddr + DEPCA_DATA);
+ outw(CSR3, nic->ioaddr + DEPCA_ADDR); /* ALE control */
+ outw(ACON, nic->ioaddr + DEPCA_DATA);
+ outw(CSR0, nic->ioaddr + DEPCA_ADDR); /* Point back to CSR0 */
+}
+
+static inline int InitRestartDepca(struct nic *nic)
+{
+ int i;
+
+ /* Copy the shadow init_block to shared memory */
+ memcpy_toio((char *)lp.sh_mem, &lp.init_block, sizeof(struct depca_init));
+ outw(CSR0, nic->ioaddr + DEPCA_ADDR); /* point back to CSR0 */
+ outw(INIT, nic->ioaddr + DEPCA_DATA); /* initialise DEPCA */
+
+ for (i = 0; i < 100 && !(inw(nic->ioaddr + DEPCA_DATA) & IDON); i++)
+ ;
+ if (i < 100) {
+ /* clear IDON by writing a 1, and start LANCE */
+ outw(IDON | STRT, nic->ioaddr + DEPCA_DATA);
+ } else {
+ printf("DEPCA not initialised\n");
+ return (1);
+ }
+ return (0);
+}
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void depca_reset(struct nic *nic)
+{
+ s16 nicsr;
+ int i, j;
+
+ STOP_DEPCA(nic->ioaddr);
+ nicsr = inb(nic->ioaddr + DEPCA_NICSR);
+ nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
+ outb(nicsr, nic->ioaddr + DEPCA_NICSR);
+ if (inw(nic->ioaddr + DEPCA_DATA) != STOP)
+ {
+ printf("depca: Cannot stop NIC\n");
+ return;
+ }
+
+ /* Initialisation block */
+ lp.sh_mem = mem_start;
+ mem_start += sizeof(struct depca_init);
+ /* Tx & Rx descriptors (aligned to a quadword boundary) */
+ mem_start = (mem_start + ALIGN) & ~ALIGN;
+ lp.rx_ring = (struct depca_rx_desc *) mem_start;
+ mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
+ lp.tx_ring = (struct depca_tx_desc *) mem_start;
+ mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
+
+ lp.bus_offset = mem_start & 0x00ff0000;
+ /* LANCE re-mapped start address */
+ lp.dma_buffs = mem_start & LA_MASK;
+
+ /* Finish initialising the ring information. */
+ lp.rxRingMask = NUM_RX_DESC - 1;
+ lp.txRingMask = NUM_TX_DESC - 1;
+
+ /* Calculate Tx/Rx RLEN size for the descriptors. */
+ for (i = 0, j = lp.rxRingMask; j > 0; i++) {
+ j >>= 1;
+ }
+ lp.rx_rlen = (s32) (i << 29);
+ for (i = 0, j = lp.txRingMask; j > 0; i++) {
+ j >>= 1;
+ }
+ lp.tx_rlen = (s32) (i << 29);
+
+ /* Load the initialisation block */
+ depca_init_ring(nic);
+ LoadCSRs(nic);
+ InitRestartDepca(nic);
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int depca_poll(struct nic *nic, int retrieve)
+{
+ int entry;
+ u32 status;
+
+ entry = lp.rx_cur;
+ if ((status = readl(&lp.rx_ring[entry].base) & R_OWN))
+ return (0);
+
+ if ( ! retrieve ) return 1;
+
+ memcpy(nic->packet, lp.rx_memcpy[entry], nic->packetlen = lp.rx_ring[entry].msg_length);
+ lp.rx_ring[entry].base |= R_OWN;
+ lp.rx_cur = (++lp.rx_cur) & lp.rxRingMask;
+ return (1);
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void depca_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ int entry, len;
+ char *mem;
+
+ /* send the packet to destination */
+ /*
+ ** Caution: the right order is important here... dont
+ ** setup the ownership rights until all the other
+ ** information is in place
+ */
+ mem = lp.tx_memcpy[entry = lp.tx_cur];
+ memcpy_toio(mem, d, ETH_ALEN);
+ memcpy_toio(mem + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ mem[ETH_ALEN * 2] = t >> 8;
+ mem[ETH_ALEN * 2 + 1] = t;
+ memcpy_toio(mem + ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ len = (s < ETH_ZLEN ? ETH_ZLEN : s);
+ /* clean out flags */
+ writel(readl(&lp.tx_ring[entry].base) & ~T_FLAGS, &lp.tx_ring[entry].base);
+ /* clears other error flags */
+ writew(0x0000, &lp.tx_ring[entry].misc);
+ /* packet length in buffer */
+ writew(-len, &lp.tx_ring[entry].length);
+ /* start and end of packet, ownership */
+ writel(readl(&lp.tx_ring[entry].base) | (T_STP|T_ENP|T_OWN), &lp.tx_ring[entry].base);
+ /* update current pointers */
+ lp.tx_cur = (++lp.tx_cur) & lp.txRingMask;
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void depca_disable ( struct nic *nic ) {
+ depca_reset(nic);
+
+ STOP_DEPCA(nic->ioaddr);
+}
+
+/**************************************************************************
+IRQ - Interrupt Control
+***************************************************************************/
+static void depca_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/*
+** Look for a special sequence in the Ethernet station address PROM that
+** is common across all DEPCA products. Note that the original DEPCA needs
+** its ROM address counter to be initialized and enabled. Only enable
+** if the first address octet is a 0x08 - this minimises the chances of
+** messing around with some other hardware, but it assumes that this DEPCA
+** card initialized itself correctly.
+**
+** Search the Ethernet address ROM for the signature. Since the ROM address
+** counter can start at an arbitrary point, the search must include the entire
+** probe sequence length plus the (length_of_the_signature - 1).
+** Stop the search IMMEDIATELY after the signature is found so that the
+** PROM address counter is correctly positioned at the start of the
+** ethernet address for later read out.
+*/
+
+
+/*
+ * Ugly, ugly, ugly. I can't quite make out where the split should be
+ * between probe1 and probe()...
+ *
+ */
+static u8 nicsr;
+
+
+static int depca_probe1 ( isa_probe_addr_t ioaddr ) {
+ u8 data;
+ /* This is only correct for little endian machines, but then
+ Etherboot doesn't work on anything but a PC */
+ u8 sig[] = { 0xFF, 0x00, 0x55, 0xAA, 0xFF, 0x00, 0x55, 0xAA };
+ int i, j;
+
+ data = inb(ioaddr + DEPCA_PROM); /* clear counter on DEPCA */
+ data = inb(ioaddr + DEPCA_PROM); /* read data */
+ if (data == 0x8) {
+ nicsr = inb(ioaddr + DEPCA_NICSR);
+ nicsr |= AAC;
+ outb(nicsr, ioaddr + DEPCA_NICSR);
+ }
+ for (i = 0, j = 0; j < (int)sizeof(sig) && i < PROBE_LENGTH+((int)sizeof(sig))-1; ++i) {
+ data = inb(ioaddr + DEPCA_PROM);
+ if (data == sig[j]) /* track signature */
+ ++j;
+ else
+ j = (data == sig[0]) ? 1 : 0;
+ }
+ if (j != sizeof(sig))
+ return (0);
+ /* put the card in its initial state */
+ STOP_DEPCA(ioaddr);
+ nicsr = ((inb(ioaddr + DEPCA_NICSR) & ~SHE & ~RBE & ~IEN) | IM);
+ outb(nicsr, ioaddr + DEPCA_NICSR);
+ if (inw(ioaddr + DEPCA_DATA) != STOP)
+ return (0);
+ memcpy((char *)mem_start, sig, sizeof(sig));
+ if (memcmp((char *)mem_start, sig, sizeof(sig)) != 0)
+ return (0);
+
+ return 1;
+}
+
+static struct nic_operations depca_operations = {
+ .connect = dummy_connect,
+ .poll = depca_poll,
+ .transmit = depca_transmit,
+ .irq = depca_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int depca_probe ( struct nic *nic, struct isa_device *isa ) {
+
+ int i, j;
+ long sum, chksum;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+
+ for (i = 0, j = 0, sum = 0; j < 3; j++) {
+ sum <<= 1;
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ sum += (u8)(nic->node_addr[i++] = inb(nic->ioaddr + DEPCA_PROM));
+ sum += (u16)((nic->node_addr[i++] = inb(nic->ioaddr + DEPCA_PROM)) << 8);
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+ if (sum == 0xFFFF)
+ sum = 0;
+ chksum = (u8)inb(nic->ioaddr + DEPCA_PROM);
+ chksum |= (u16)(inb(nic->ioaddr + DEPCA_PROM) << 8);
+ mem_len = (adapter == DEPCA) ? (48 << 10) : (64 << 10);
+ offset = 0;
+ if (nicsr & BUF) {
+ offset = 0x8000;
+ nicsr &= ~BS;
+ mem_len -= (32 << 10);
+ }
+ if (adapter != DEPCA) /* enable shadow RAM */
+ outb(nicsr |= SHE, nic->ioaddr + DEPCA_NICSR);
+ DBG ( "%s base %4.4x, memory [%4.4lx-%4.4lx] addr %s",
+ adapter_name[adapter], nic->ioaddr, mem_start,
+ mem_start + mem_len, eth_ntoa ( nic->node_addr ) );
+ if (sum != chksum)
+ printf(" (bad checksum)");
+ putchar('\n');
+
+ depca_reset(nic);
+
+ /* point to NIC specific routines */
+ nic->nic_op = &depca_operations;
+ return 1;
+}
+
+static isa_probe_addr_t depca_probe_addrs[] = {
+ 0x300, 0x200,
+};
+
+ISA_DRIVER ( depca_driver, depca_probe_addrs, depca_probe1,
+ GENERIC_ISAPNP_VENDOR, 0x80f7 );
+
+DRIVER ( "depce", nic_driver, isa_driver, depca_driver,
+ depca_probe, depca_disable );
+
+ISA_ROM ( "depca", "Digital DE100 and DE200" );
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/dmfe.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/dmfe.c
new file mode 100644
index 0000000..8d79158
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/dmfe.c
@@ -0,0 +1,1226 @@
+/**************************************************************************
+*
+* dmfe.c -- Etherboot device driver for the Davicom
+* DM9102/DM9102A/DM9102A+DM9801/DM9102A+DM9802 NIC fast ethernet card
+*
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+*
+* dmfe.c: A Davicom DM9102/DM9102A/DM9102A+DM9801/DM9102A+DM9802
+* NIC fast ethernet driver for Linux.
+* Copyright (C) 1997 Sten Wang
+* (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
+*
+*
+* REVISION HISTORY:
+* ================
+* v1.0 10-02-2004 timlegge Boots ltsp needs cleanup
+*
+* Indent Options: indent -kr -i8
+*
+*
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+
+/* #define EDEBUG 1 */
+#ifdef EDEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* Board/System/Debug information/definition ---------------- */
+#define PCI_DM9132_ID 0x91321282 /* Davicom DM9132 ID */
+#define PCI_DM9102_ID 0x91021282 /* Davicom DM9102 ID */
+#define PCI_DM9100_ID 0x91001282 /* Davicom DM9100 ID */
+#define PCI_DM9009_ID 0x90091282 /* Davicom DM9009 ID */
+
+#define DM9102_IO_SIZE 0x80
+#define DM9102A_IO_SIZE 0x100
+#define TX_MAX_SEND_CNT 0x1 /* Maximum tx packet per time */
+#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */
+#define RX_DESC_CNT 0x20 /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
+#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC 0x600
+#define RX_ALLOC_SIZE 0x620
+#define DM910X_RESET 1
+#define CR0_DEFAULT 0x00E00000 /* TX & RX burst mode */
+#define CR6_DEFAULT 0x00080000 /* HD */
+#define CR7_DEFAULT 0x180c1
+#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define DMFE_MAX_MULTICAST 14
+#define RX_COPY_SIZE 100
+#define MAX_CHECK_PACKET 0x8000
+#define DM9801_NOISE_FLOOR 8
+#define DM9802_NOISE_FLOOR 5
+
+#define DMFE_10MHF 0
+#define DMFE_100MHF 1
+#define DMFE_10MFD 4
+#define DMFE_100MFD 5
+#define DMFE_AUTO 8
+#define DMFE_1M_HPNA 0x10
+
+#define DMFE_TXTH_72 0x400000 /* TX TH 72 byte */
+#define DMFE_TXTH_96 0x404000 /* TX TH 96 byte */
+#define DMFE_TXTH_128 0x0000 /* TX TH 128 byte */
+#define DMFE_TXTH_256 0x4000 /* TX TH 256 byte */
+#define DMFE_TXTH_512 0x8000 /* TX TH 512 byte */
+#define DMFE_TXTH_1K 0xC000 /* TX TH 1K byte */
+
+#define DMFE_TIMER_WUT (jiffies + HZ * 1) /* timer wakeup time : 1 second */
+#define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */
+#define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */
+
+#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value))
+
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
+
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ 0x4800
+#define CR9_SRCS 0x1
+#define CR9_SRCLK 0x2
+#define CR9_CRDOUT 0x8
+#define SROM_DATA_0 0x0
+#define SROM_DATA_1 0x4
+#define PHY_DATA_1 0x20000
+#define PHY_DATA_0 0x00000
+#define MDCLKH 0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE 0x14
+
+#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);
+
+#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
+#define CHK_IO_SIZE(pci_dev, dev_rev) __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
+
+/* Sten Check */
+#define DEVICE net_device
+
+/* Structure/enum declaration ------------------------------- */
+struct tx_desc {
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ void * tx_buf_ptr; /* Data for us */
+ struct tx_desc * next_tx_desc;
+} __attribute__ ((aligned(32)));
+
+struct rx_desc {
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ void * rx_skb_ptr; /* Data for us */
+ struct rx_desc * next_rx_desc;
+} __attribute__ ((aligned(32)));
+
+static struct dmfe_private {
+ u32 chip_id; /* Chip vendor/Device ID */
+ u32 chip_revision; /* Chip revision */
+ u32 cr0_data;
+// u32 cr5_data;
+ u32 cr6_data;
+ u32 cr7_data;
+ u32 cr15_data;
+
+ u16 HPNA_command; /* For HPNA register 16 */
+ u16 HPNA_timer; /* For HPNA remote device check */
+ u16 NIC_capability; /* NIC media capability */
+ u16 PHY_reg4; /* Saved Phyxcer register 4 value */
+
+ u8 HPNA_present; /* 0:none, 1:DM9801, 2:DM9802 */
+ u8 chip_type; /* Keep DM9102A chip type */
+ u8 media_mode; /* user specify media mode */
+ u8 op_mode; /* real work media mode */
+ u8 phy_addr;
+ u8 dm910x_chk_mode; /* Operating mode check */
+
+ /* NIC SROM data */
+ unsigned char srom[128];
+ /* Etherboot Only */
+ u8 cur_tx;
+ u8 cur_rx;
+} dfx;
+
+static struct dmfe_private *db;
+
+enum dmfe_offsets {
+ DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+ DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+ DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 =
+ 0x70,
+ DCR15 = 0x78
+};
+
+enum dmfe_CR6_bits {
+ CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+ CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+ CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration ----------------------------- */
+static struct nic_operations dmfe_operations;
+
+static unsigned char dmfe_media_mode = DMFE_AUTO;
+static u32 dmfe_cr6_user_set;
+
+/* For module input parameter */
+static u8 chkmode = 1;
+static u8 HPNA_mode; /* Default: Low Power/High Speed */
+static u8 HPNA_rx_cmd; /* Default: Disable Rx remote command */
+static u8 HPNA_tx_cmd; /* Default: Don't issue remote command */
+static u8 HPNA_NoiseFloor; /* Default: HPNA NoiseFloor */
+static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control
+ 4: TX pause packet */
+
+
+/**********************************************
+* Descriptor Ring and Buffer defination
+***********************************************/
+struct {
+ struct tx_desc txd[TX_DESC_CNT] __attribute__ ((aligned(32)));
+ unsigned char txb[TX_BUF_ALLOC * TX_DESC_CNT]
+ __attribute__ ((aligned(32)));
+ struct rx_desc rxd[RX_DESC_CNT] __attribute__ ((aligned(32)));
+ unsigned char rxb[RX_ALLOC_SIZE * RX_DESC_CNT]
+ __attribute__ ((aligned(32)));
+} dmfe_bufs __shared;
+#define txd dmfe_bufs.txd
+#define txb dmfe_bufs.txb
+#define rxd dmfe_bufs.rxd
+#define rxb dmfe_bufs.rxb
+
+/* NIC specific static variables go here */
+static long int BASE;
+
+static u16 read_srom_word(long ioaddr, int offset);
+static void dmfe_init_dm910x(struct nic *nic);
+static void dmfe_descriptor_init(struct nic *, unsigned long ioaddr);
+static void update_cr6(u32, unsigned long);
+static void send_filter_frame(struct nic *nic);
+static void dm9132_id_table(struct nic *nic);
+
+static u16 phy_read(unsigned long, u8, u8, u32);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_write_1bit(unsigned long, u32);
+static u16 phy_read_1bit(unsigned long);
+static void dmfe_set_phyxcer(struct nic *nic);
+
+static void dmfe_parse_srom(struct nic *nic);
+static void dmfe_program_DM9801(struct nic *nic, int);
+static void dmfe_program_DM9802(struct nic *nic);
+
+static void dmfe_reset(struct nic *nic)
+{
+ /* system variable init */
+ db->cr6_data = CR6_DEFAULT | dmfe_cr6_user_set;
+
+ db->NIC_capability = 0xf; /* All capability */
+ db->PHY_reg4 = 0x1e0;
+
+ /* CR6 operation mode decision */
+ if (!chkmode || (db->chip_id == PCI_DM9132_ID) ||
+ (db->chip_revision >= 0x02000030)) {
+ db->cr6_data |= DMFE_TXTH_256;
+ db->cr0_data = CR0_DEFAULT;
+ db->dm910x_chk_mode = 4; /* Enter the normal mode */
+ } else {
+ db->cr6_data |= CR6_SFT; /* Store & Forward mode */
+ db->cr0_data = 0;
+ db->dm910x_chk_mode = 1; /* Enter the check mode */
+ }
+ /* Initilize DM910X board */
+ dmfe_init_dm910x(nic);
+
+ return;
+}
+
+/* Initilize DM910X board
+ * Reset DM910X board
+ * Initilize TX/Rx descriptor chain structure
+ * Send the set-up frame
+ * Enable Tx/Rx machine
+ */
+
+static void dmfe_init_dm910x(struct nic *nic)
+{
+ unsigned long ioaddr = BASE;
+
+ /* Reset DM910x MAC controller */
+ outl(DM910X_RESET, ioaddr + DCR0); /* RESET MAC */
+ udelay(100);
+ outl(db->cr0_data, ioaddr + DCR0);
+ udelay(5);
+
+ /* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
+ db->phy_addr = 1;
+
+ /* Parser SROM and media mode */
+ dmfe_parse_srom(nic);
+ db->media_mode = dmfe_media_mode;
+
+ /* RESET Phyxcer Chip by GPR port bit 7 */
+ outl(0x180, ioaddr + DCR12); /* Let bit 7 output port */
+ if (db->chip_id == PCI_DM9009_ID) {
+ outl(0x80, ioaddr + DCR12); /* Issue RESET signal */
+ mdelay(300); /* Delay 300 ms */
+ }
+ outl(0x0, ioaddr + DCR12); /* Clear RESET signal */
+
+ /* Process Phyxcer Media Mode */
+ if (!(db->media_mode & 0x10)) /* Force 1M mode */
+ dmfe_set_phyxcer(nic);
+
+ /* Media Mode Process */
+ if (!(db->media_mode & DMFE_AUTO))
+ db->op_mode = db->media_mode; /* Force Mode */
+
+ /* Initiliaze Transmit/Receive decriptor and CR3/4 */
+ dmfe_descriptor_init(nic, ioaddr);
+
+ /* tx descriptor start pointer */
+ outl(virt_to_le32desc(&txd[0]), ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ outl(virt_to_le32desc(&rxd[0]), ioaddr + DCR3); /* RX DESC address */
+
+ /* Init CR6 to program DM910x operation */
+ update_cr6(db->cr6_data, ioaddr);
+
+ /* Send setup frame */
+ if (db->chip_id == PCI_DM9132_ID) {
+ dm9132_id_table(nic); /* DM9132 */
+ } else {
+ send_filter_frame(nic); /* DM9102/DM9102A */
+ }
+
+ /* Init CR7, interrupt active bit */
+ db->cr7_data = CR7_DEFAULT;
+ outl(db->cr7_data, ioaddr + DCR7);
+ /* Init CR15, Tx jabber and Rx watchdog timer */
+ outl(db->cr15_data, ioaddr + DCR15);
+ /* Enable DM910X Tx/Rx function */
+ db->cr6_data |= CR6_RXSC | CR6_TXSC | 0x40000;
+ update_cr6(db->cr6_data, ioaddr);
+}
+#ifdef EDEBUG
+void hex_dump(const char *data, const unsigned int len);
+#endif
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int dmfe_poll(struct nic *nic, int retrieve)
+{
+ u32 rdes0;
+ int entry = db->cur_rx % RX_DESC_CNT;
+ int rxlen;
+ rdes0 = le32_to_cpu(rxd[entry].rdes0);
+ if (rdes0 & 0x80000000)
+ return 0;
+
+ if (!retrieve)
+ return 1;
+
+ if ((rdes0 & 0x300) != 0x300) {
+ /* A packet without First/Last flag */
+ printf("strange Packet\n");
+ rxd[entry].rdes0 = cpu_to_le32(0x80000000);
+ return 0;
+ } else {
+ /* A packet with First/Last flag */
+ rxlen = ((rdes0 >> 16) & 0x3fff) - 4;
+ /* error summary bit check */
+ if (rdes0 & 0x8000) {
+ printf("Error\n");
+ return 0;
+ }
+ if (!(rdes0 & 0x8000) ||
+ ((db->cr6_data & CR6_PM) && (rxlen > 6))) {
+ if (db->dm910x_chk_mode & 1)
+ printf("Silly check mode\n");
+
+ nic->packetlen = rxlen;
+ memcpy(nic->packet, rxb + (entry * RX_ALLOC_SIZE),
+ nic->packetlen);
+ }
+ }
+ rxd[entry].rdes0 = cpu_to_le32(0x80000000);
+ db->cur_rx++;
+ return 1;
+}
+
+static void dmfe_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void dmfe_transmit(struct nic *nic,
+ const char *dest, /* Destination */
+ unsigned int type, /* Type */
+ unsigned int size, /* size */
+ const char *packet) /* Packet */
+{
+ u16 nstype;
+ u8 *ptxb;
+
+ ptxb = &txb[db->cur_tx];
+
+ /* Stop Tx */
+ outl(0, BASE + DCR7);
+ memcpy(ptxb, dest, ETH_ALEN);
+ memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) type);
+ memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(ptxb + ETH_HLEN, packet, size);
+
+ size += ETH_HLEN;
+ while (size < ETH_ZLEN)
+ ptxb[size++] = '\0';
+
+ /* setup the transmit descriptor */
+ txd[db->cur_tx].tdes1 = cpu_to_le32(0xe1000000 | size);
+ txd[db->cur_tx].tdes0 = cpu_to_le32(0x80000000); /* give ownership to device */
+
+ /* immediate transmit demand */
+ outl(0x1, BASE + DCR1);
+ outl(db->cr7_data, BASE + DCR7);
+
+ /* Point to next TX descriptor */
+ db->cur_tx++;
+ db->cur_tx = db->cur_tx % TX_DESC_CNT;
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void dmfe_disable ( struct nic *nic __unused ) {
+ /* Reset & stop DM910X board */
+ outl(DM910X_RESET, BASE + DCR0);
+ udelay(5);
+ phy_write(BASE, db->phy_addr, 0, 0x8000, db->chip_id);
+
+}
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+
+#define board_found 1
+#define valid_link 0
+static int dmfe_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ uint32_t dev_rev, pci_pmr;
+ int i;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ BASE = pci->ioaddr;
+ printf("dmfe.c: Vendor=0x%hX Device=0x%hX\n",
+ pci->vendor, pci->device);
+
+ /* Read Chip revision */
+ pci_read_config_dword(pci, PCI_REVISION_ID, &dev_rev);
+ dprintf(("Revision %lX\n", dev_rev));
+
+ /* point to private storage */
+ db = &dfx;
+
+ db->chip_id = ((u32) pci->device << 16) | pci->vendor;
+ BASE = pci_bar_start(pci, PCI_BASE_ADDRESS_0);
+ db->chip_revision = dev_rev;
+
+ pci_read_config_dword(pci, 0x50, &pci_pmr);
+ pci_pmr &= 0x70000;
+ if ((pci_pmr == 0x10000) && (dev_rev == 0x02000031))
+ db->chip_type = 1; /* DM9102A E3 */
+ else
+ db->chip_type = 0;
+
+ dprintf(("Chip type : %d\n", db->chip_type));
+
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(BASE, i));
+
+ /* Set Node address */
+ for (i = 0; i < 6; i++)
+ nic->node_addr[i] = db->srom[20 + i];
+
+ /* Print out some hardware info */
+ DBG ( "%s: at ioaddr %4.4lx\n", eth_ntoa ( nic->node_addr ), BASE );
+
+ /* Set the card as PCI Bus Master */
+ adjust_pci_device(pci);
+
+ dmfe_reset(nic);
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ /* point to NIC specific routines */
+ nic->nic_op = &dmfe_operations;
+
+ return 1;
+}
+
+/*
+ * Initialize transmit/Receive descriptor
+ * Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void dmfe_descriptor_init(struct nic *nic __unused, unsigned long ioaddr)
+{
+ int i;
+ db->cur_tx = 0;
+ db->cur_rx = 0;
+
+ /* tx descriptor start pointer */
+ outl(virt_to_le32desc(&txd[0]), ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ outl(virt_to_le32desc(&rxd[0]), ioaddr + DCR3); /* RX DESC address */
+
+ /* Init Transmit chain */
+ for (i = 0; i < TX_DESC_CNT; i++) {
+ txd[i].tx_buf_ptr = &txb[i];
+ txd[i].tdes0 = cpu_to_le32(0);
+ txd[i].tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
+ txd[i].tdes2 = cpu_to_le32(virt_to_bus(&txb[i]));
+ txd[i].tdes3 = cpu_to_le32(virt_to_bus(&txd[i + 1]));
+ txd[i].next_tx_desc = &txd[i + 1];
+ }
+ /* Mark the last entry as wrapping the ring */
+ txd[i - 1].tdes3 = virt_to_le32desc(&txd[0]);
+ txd[i - 1].next_tx_desc = &txd[0];
+
+ /* receive descriptor chain */
+ for (i = 0; i < RX_DESC_CNT; i++) {
+ rxd[i].rx_skb_ptr = &rxb[i * RX_ALLOC_SIZE];
+ rxd[i].rdes0 = cpu_to_le32(0x80000000);
+ rxd[i].rdes1 = cpu_to_le32(0x01000600);
+ rxd[i].rdes2 =
+ cpu_to_le32(virt_to_bus(&rxb[i * RX_ALLOC_SIZE]));
+ rxd[i].rdes3 = cpu_to_le32(virt_to_bus(&rxd[i + 1]));
+ rxd[i].next_rx_desc = &rxd[i + 1];
+ }
+ /* Mark the last entry as wrapping the ring */
+ rxd[i - 1].rdes3 = cpu_to_le32(virt_to_bus(&rxd[0]));
+ rxd[i - 1].next_rx_desc = &rxd[0];
+
+}
+
+/*
+ * Update CR6 value
+ * Firstly stop DM910X , then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+ u32 cr6_tmp;
+
+ cr6_tmp = cr6_data & ~0x2002; /* stop Tx/Rx */
+ outl(cr6_tmp, ioaddr + DCR6);
+ udelay(5);
+ outl(cr6_data, ioaddr + DCR6);
+ udelay(5);
+}
+
+
+/*
+ * Send a setup frame for DM9132
+ * This setup frame initilize DM910X addres filter mode
+*/
+
+static void dm9132_id_table(struct nic *nic __unused)
+{
+#ifdef LINUX
+ u16 *addrptr;
+ u8 dmi_addr[8];
+ unsigned long ioaddr = BASE + 0xc0; /* ID Table */
+ u32 hash_val;
+ u16 i, hash_table[4];
+#endif
+ dprintf(("dm9132_id_table\n"));
+
+ printf("FIXME: This function is broken. If you have this card contact "
+ "Timothy Legge at the etherboot-user list\n");
+
+#ifdef LINUX
+ //DMFE_DBUG(0, "dm9132_id_table()", 0);
+
+ /* Node address */
+ addrptr = (u16 *) nic->node_addr;
+ outw(addrptr[0], ioaddr);
+ ioaddr += 4;
+ outw(addrptr[1], ioaddr);
+ ioaddr += 4;
+ outw(addrptr[2], ioaddr);
+ ioaddr += 4;
+
+ /* Clear Hash Table */
+ for (i = 0; i < 4; i++)
+ hash_table[i] = 0x0;
+
+ /* broadcast address */
+ hash_table[3] = 0x8000;
+
+ /* the multicast address in Hash Table : 64 bits */
+ for (mcptr = mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+ hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
+ }
+
+ /* Write the hash table to MAC MD table */
+ for (i = 0; i < 4; i++, ioaddr += 4)
+ outw(hash_table[i], ioaddr);
+#endif
+}
+
+
+/*
+ * Send a setup frame for DM9102/DM9102A
+ * This setup frame initilize DM910X addres filter mode
+ */
+
+static void send_filter_frame(struct nic *nic)
+{
+
+ u8 *ptxb;
+ int i;
+
+ dprintf(("send_filter_frame\n"));
+ /* point to the current txb incase multiple tx_rings are used */
+ ptxb = &txb[db->cur_tx];
+
+ /* construct perfect filter frame with mac address as first match
+ and broadcast address for all others */
+ for (i = 0; i < 192; i++)
+ ptxb[i] = 0xFF;
+ ptxb[0] = nic->node_addr[0];
+ ptxb[1] = nic->node_addr[1];
+ ptxb[4] = nic->node_addr[2];
+ ptxb[5] = nic->node_addr[3];
+ ptxb[8] = nic->node_addr[4];
+ ptxb[9] = nic->node_addr[5];
+
+ /* prepare the setup frame */
+ txd[db->cur_tx].tdes1 = cpu_to_le32(0x890000c0);
+ txd[db->cur_tx].tdes0 = cpu_to_le32(0x80000000);
+ update_cr6(db->cr6_data | 0x2000, BASE);
+ outl(0x1, BASE + DCR1); /* Issue Tx polling */
+ update_cr6(db->cr6_data, BASE);
+ db->cur_tx++;
+}
+
+/*
+ * Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+ int i;
+ u16 srom_data = 0;
+ long cr9_ioaddr = ioaddr + DCR9;
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ /* Send the Read Command 110b */
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+ /* Send the offset */
+ for (i = 5; i >= 0; i--) {
+ srom_data =
+ (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+ SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ }
+
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ for (i = 16; i > 0; i--) {
+ outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ udelay(5);
+ srom_data =
+ (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1
+ : 0);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ udelay(5);
+ }
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ return srom_data;
+}
+
+
+/*
+ * Auto sense the media mode
+ */
+
+#if 0 /* not used */
+static u8 dmfe_sense_speed(struct nic *nic __unused)
+{
+ u8 ErrFlag = 0;
+ u16 phy_mode;
+
+ /* CR6 bit18=0, select 10/100M */
+ update_cr6((db->cr6_data & ~0x40000), BASE);
+
+ phy_mode = phy_read(BASE, db->phy_addr, 1, db->chip_id);
+ phy_mode = phy_read(BASE, db->phy_addr, 1, db->chip_id);
+
+ if ((phy_mode & 0x24) == 0x24) {
+ if (db->chip_id == PCI_DM9132_ID) /* DM9132 */
+ phy_mode =
+ phy_read(BASE, db->phy_addr, 7,
+ db->chip_id) & 0xf000;
+ else /* DM9102/DM9102A */
+ phy_mode =
+ phy_read(BASE, db->phy_addr, 17,
+ db->chip_id) & 0xf000;
+ /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
+ switch (phy_mode) {
+ case 0x1000:
+ db->op_mode = DMFE_10MHF;
+ break;
+ case 0x2000:
+ db->op_mode = DMFE_10MFD;
+ break;
+ case 0x4000:
+ db->op_mode = DMFE_100MHF;
+ break;
+ case 0x8000:
+ db->op_mode = DMFE_100MFD;
+ break;
+ default:
+ db->op_mode = DMFE_10MHF;
+ ErrFlag = 1;
+ break;
+ }
+ } else {
+ db->op_mode = DMFE_10MHF;
+ //DMFE_DBUG(0, "Link Failed :", phy_mode);
+ ErrFlag = 1;
+ }
+
+ return ErrFlag;
+}
+#endif
+
+/*
+ * Set 10/100 phyxcer capability
+ * AUTO mode : phyxcer register4 is NIC capability
+ * Force mode: phyxcer register4 is the force media
+ */
+
+static void dmfe_set_phyxcer(struct nic *nic __unused)
+{
+ u16 phy_reg;
+
+ /* Select 10/100M phyxcer */
+ db->cr6_data &= ~0x40000;
+ update_cr6(db->cr6_data, BASE);
+
+ /* DM9009 Chip: Phyxcer reg18 bit12=0 */
+ if (db->chip_id == PCI_DM9009_ID) {
+ phy_reg =
+ phy_read(BASE, db->phy_addr, 18,
+ db->chip_id) & ~0x1000;
+ phy_write(BASE, db->phy_addr, 18, phy_reg, db->chip_id);
+ }
+
+ /* Phyxcer capability setting */
+ phy_reg = phy_read(BASE, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+ if (db->media_mode & DMFE_AUTO) {
+ /* AUTO Mode */
+ phy_reg |= db->PHY_reg4;
+ } else {
+ /* Force Mode */
+ switch (db->media_mode) {
+ case DMFE_10MHF:
+ phy_reg |= 0x20;
+ break;
+ case DMFE_10MFD:
+ phy_reg |= 0x40;
+ break;
+ case DMFE_100MHF:
+ phy_reg |= 0x80;
+ break;
+ case DMFE_100MFD:
+ phy_reg |= 0x100;
+ break;
+ }
+ if (db->chip_id == PCI_DM9009_ID)
+ phy_reg &= 0x61;
+ }
+
+ /* Write new capability to Phyxcer Reg4 */
+ if (!(phy_reg & 0x01e0)) {
+ phy_reg |= db->PHY_reg4;
+ db->media_mode |= DMFE_AUTO;
+ }
+ phy_write(BASE, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ /* Restart Auto-Negotiation */
+ if (db->chip_type && (db->chip_id == PCI_DM9102_ID))
+ phy_write(BASE, db->phy_addr, 0, 0x1800, db->chip_id);
+ if (!db->chip_type)
+ phy_write(BASE, db->phy_addr, 0, 0x1200, db->chip_id);
+}
+
+
+/*
+ * Process op-mode
+ * AUTO mode : PHY controller in Auto-negotiation Mode
+ * Force mode: PHY controller in force mode with HUB
+ * N-way force capability with SWITCH
+ */
+
+#if 0 /* not used */
+static void dmfe_process_mode(struct nic *nic __unused)
+{
+ u16 phy_reg;
+
+ /* Full Duplex Mode Check */
+ if (db->op_mode & 0x4)
+ db->cr6_data |= CR6_FDM; /* Set Full Duplex Bit */
+ else
+ db->cr6_data &= ~CR6_FDM; /* Clear Full Duplex Bit */
+
+ /* Transciver Selection */
+ if (db->op_mode & 0x10) /* 1M HomePNA */
+ db->cr6_data |= 0x40000; /* External MII select */
+ else
+ db->cr6_data &= ~0x40000; /* Internal 10/100 transciver */
+
+ update_cr6(db->cr6_data, BASE);
+
+ /* 10/100M phyxcer force mode need */
+ if (!(db->media_mode & 0x18)) {
+ /* Forece Mode */
+ phy_reg = phy_read(BASE, db->phy_addr, 6, db->chip_id);
+ if (!(phy_reg & 0x1)) {
+ /* parter without N-Way capability */
+ phy_reg = 0x0;
+ switch (db->op_mode) {
+ case DMFE_10MHF:
+ phy_reg = 0x0;
+ break;
+ case DMFE_10MFD:
+ phy_reg = 0x100;
+ break;
+ case DMFE_100MHF:
+ phy_reg = 0x2000;
+ break;
+ case DMFE_100MFD:
+ phy_reg = 0x2100;
+ break;
+ }
+ phy_write(BASE, db->phy_addr, 0, phy_reg,
+ db->chip_id);
+ if (db->chip_type
+ && (db->chip_id == PCI_DM9102_ID))
+ mdelay(20);
+ phy_write(BASE, db->phy_addr, 0, phy_reg,
+ db->chip_id);
+ }
+ }
+}
+#endif
+
+/*
+ * Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+ u16 phy_data, u32 chip_id)
+{
+ u16 i;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_DM9132_ID) {
+ ioaddr = iobase + 0x80 + offset * 4;
+ outw(phy_data, ioaddr);
+ } else {
+ /* DM9102/DM9102A Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send Phy addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ phy_addr & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* Send register addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ offset & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* written trasnition */
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+
+ /* Write a word data to PHY controller */
+ for (i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(ioaddr,
+ phy_data & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+ }
+}
+
+
+/*
+ * Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset,
+ u32 chip_id)
+{
+ int i;
+ u16 phy_data;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_DM9132_ID) {
+ /* DM9132 Chip */
+ ioaddr = iobase + 0x80 + offset * 4;
+ phy_data = inw(ioaddr);
+ } else {
+ /* DM9102/DM9102A Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_1);
+ phy_write_1bit(ioaddr, PHY_DATA_0);
+
+ /* Send Phy addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ phy_addr & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* Send register addres */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr,
+ offset & i ? PHY_DATA_1 :
+ PHY_DATA_0);
+
+ /* Skip transition state */
+ phy_read_1bit(ioaddr);
+
+ /* read 16bit data */
+ for (phy_data = 0, i = 0; i < 16; i++) {
+ phy_data <<= 1;
+ phy_data |= phy_read_1bit(ioaddr);
+ }
+ }
+
+ return phy_data;
+}
+
+
+/*
+ * Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
+{
+ outl(phy_data, ioaddr); /* MII Clock Low */
+ udelay(1);
+ outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ udelay(1);
+ outl(phy_data, ioaddr); /* MII Clock Low */
+ udelay(1);
+}
+
+
+/*
+ * Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr)
+{
+ u16 phy_data;
+
+ outl(0x50000, ioaddr);
+ udelay(1);
+ phy_data = (inl(ioaddr) >> 19) & 0x1;
+ outl(0x40000, ioaddr);
+ udelay(1);
+
+ return phy_data;
+}
+
+
+/*
+ * Parser SROM and media mode
+ */
+
+static void dmfe_parse_srom(struct nic *nic)
+{
+ unsigned char *srom = db->srom;
+ int dmfe_mode, tmp_reg;
+
+ /* Init CR15 */
+ db->cr15_data = CR15_DEFAULT;
+
+ /* Check SROM Version */
+ if (((int) srom[18] & 0xff) == SROM_V41_CODE) {
+ /* SROM V4.01 */
+ /* Get NIC support media mode */
+ db->NIC_capability = *(u16 *) (srom + 34);
+ db->PHY_reg4 = 0;
+ for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) {
+ switch (db->NIC_capability & tmp_reg) {
+ case 0x1:
+ db->PHY_reg4 |= 0x0020;
+ break;
+ case 0x2:
+ db->PHY_reg4 |= 0x0040;
+ break;
+ case 0x4:
+ db->PHY_reg4 |= 0x0080;
+ break;
+ case 0x8:
+ db->PHY_reg4 |= 0x0100;
+ break;
+ }
+ }
+
+ /* Media Mode Force or not check */
+ dmfe_mode = *((int *) srom + 34) & *((int *) srom + 36);
+ switch (dmfe_mode) {
+ case 0x4:
+ dmfe_media_mode = DMFE_100MHF;
+ break; /* 100MHF */
+ case 0x2:
+ dmfe_media_mode = DMFE_10MFD;
+ break; /* 10MFD */
+ case 0x8:
+ dmfe_media_mode = DMFE_100MFD;
+ break; /* 100MFD */
+ case 0x100:
+ case 0x200:
+ dmfe_media_mode = DMFE_1M_HPNA;
+ break; /* HomePNA */
+ }
+
+ /* Special Function setting */
+ /* VLAN function */
+ if ((SF_mode & 0x1) || (srom[43] & 0x80))
+ db->cr15_data |= 0x40;
+
+ /* Flow Control */
+ if ((SF_mode & 0x2) || (srom[40] & 0x1))
+ db->cr15_data |= 0x400;
+
+ /* TX pause packet */
+ if ((SF_mode & 0x4) || (srom[40] & 0xe))
+ db->cr15_data |= 0x9800;
+ }
+
+ /* Parse HPNA parameter */
+ db->HPNA_command = 1;
+
+ /* Accept remote command or not */
+ if (HPNA_rx_cmd == 0)
+ db->HPNA_command |= 0x8000;
+
+ /* Issue remote command & operation mode */
+ if (HPNA_tx_cmd == 1)
+ switch (HPNA_mode) { /* Issue Remote Command */
+ case 0:
+ db->HPNA_command |= 0x0904;
+ break;
+ case 1:
+ db->HPNA_command |= 0x0a00;
+ break;
+ case 2:
+ db->HPNA_command |= 0x0506;
+ break;
+ case 3:
+ db->HPNA_command |= 0x0602;
+ break;
+ } else
+ switch (HPNA_mode) { /* Don't Issue */
+ case 0:
+ db->HPNA_command |= 0x0004;
+ break;
+ case 1:
+ db->HPNA_command |= 0x0000;
+ break;
+ case 2:
+ db->HPNA_command |= 0x0006;
+ break;
+ case 3:
+ db->HPNA_command |= 0x0002;
+ break;
+ }
+
+ /* Check DM9801 or DM9802 present or not */
+ db->HPNA_present = 0;
+ update_cr6(db->cr6_data | 0x40000, BASE);
+ tmp_reg = phy_read(BASE, db->phy_addr, 3, db->chip_id);
+ if ((tmp_reg & 0xfff0) == 0xb900) {
+ /* DM9801 or DM9802 present */
+ db->HPNA_timer = 8;
+ if (phy_read(BASE, db->phy_addr, 31, db->chip_id) ==
+ 0x4404) {
+ /* DM9801 HomeRun */
+ db->HPNA_present = 1;
+ dmfe_program_DM9801(nic, tmp_reg);
+ } else {
+ /* DM9802 LongRun */
+ db->HPNA_present = 2;
+ dmfe_program_DM9802(nic);
+ }
+ }
+
+}
+
+/*
+ * Init HomeRun DM9801
+ */
+
+static void dmfe_program_DM9801(struct nic *nic __unused, int HPNA_rev)
+{
+ u32 reg17, reg25;
+
+ if (!HPNA_NoiseFloor)
+ HPNA_NoiseFloor = DM9801_NOISE_FLOOR;
+ switch (HPNA_rev) {
+ case 0xb900: /* DM9801 E3 */
+ db->HPNA_command |= 0x1000;
+ reg25 = phy_read(BASE, db->phy_addr, 24, db->chip_id);
+ reg25 = ((reg25 + HPNA_NoiseFloor) & 0xff) | 0xf000;
+ reg17 = phy_read(BASE, db->phy_addr, 17, db->chip_id);
+ break;
+ case 0xb901: /* DM9801 E4 */
+ reg25 = phy_read(BASE, db->phy_addr, 25, db->chip_id);
+ reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor;
+ reg17 = phy_read(BASE, db->phy_addr, 17, db->chip_id);
+ reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor + 3;
+ break;
+ case 0xb902: /* DM9801 E5 */
+ case 0xb903: /* DM9801 E6 */
+ default:
+ db->HPNA_command |= 0x1000;
+ reg25 = phy_read(BASE, db->phy_addr, 25, db->chip_id);
+ reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor - 5;
+ reg17 = phy_read(BASE, db->phy_addr, 17, db->chip_id);
+ reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor;
+ break;
+ }
+ phy_write(BASE, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+ phy_write(BASE, db->phy_addr, 17, reg17, db->chip_id);
+ phy_write(BASE, db->phy_addr, 25, reg25, db->chip_id);
+}
+
+
+/*
+ * Init HomeRun DM9802
+ */
+
+static void dmfe_program_DM9802(struct nic *nic __unused)
+{
+ u32 phy_reg;
+
+ if (!HPNA_NoiseFloor)
+ HPNA_NoiseFloor = DM9802_NOISE_FLOOR;
+ phy_write(BASE, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+ phy_reg = phy_read(BASE, db->phy_addr, 25, db->chip_id);
+ phy_reg = (phy_reg & 0xff00) + HPNA_NoiseFloor;
+ phy_write(BASE, db->phy_addr, 25, phy_reg, db->chip_id);
+}
+
+static struct nic_operations dmfe_operations = {
+ .connect = dummy_connect,
+ .poll = dmfe_poll,
+ .transmit = dmfe_transmit,
+ .irq = dmfe_irq,
+
+};
+
+static struct pci_device_id dmfe_nics[] = {
+ PCI_ROM(0x1282, 0x9100, "dmfe9100", "Davicom 9100", 0),
+ PCI_ROM(0x1282, 0x9102, "dmfe9102", "Davicom 9102", 0),
+ PCI_ROM(0x1282, 0x9009, "dmfe9009", "Davicom 9009", 0),
+ PCI_ROM(0x1282, 0x9132, "dmfe9132", "Davicom 9132", 0), /* Needs probably some fixing */
+};
+
+PCI_DRIVER ( dmfe_driver, dmfe_nics, PCI_NO_CLASS );
+
+DRIVER ( "DMFE/PCI", nic_driver, pci_driver, dmfe_driver,
+ dmfe_probe, dmfe_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/eepro.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/eepro.c
new file mode 100644
index 0000000..a248692
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/eepro.c
@@ -0,0 +1,637 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Intel EEPRO/10 NIC driver for Etherboot
+Adapted from Linux eepro.c from kernel 2.2.17
+
+This board accepts a 32 pin EEPROM (29C256), however a test with a
+27C010 shows that this EPROM also works in the socket, but it's not clear
+how repeatably. The two top address pins appear to be held low, thus
+the bottom 32kB of the 27C010 is visible in the CPU's address space.
+To be sure you could put 4 copies of the code in the 27C010, then
+it doesn't matter whether the extra lines are held low or high, just
+hopefully not floating as CMOS chips don't like floating inputs.
+
+Be careful with seating the EPROM as the socket on my board actually
+has 34 pins, the top row of 2 are not used.
+***************************************************************************/
+
+/*
+
+ timlegge 2005-05-18 remove the relocation changes cards that
+ write directly to the hardware don't need it
+*/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include <errno.h>
+#include "nic.h"
+#include <gpxe/isa.h>
+#include <gpxe/ethernet.h>
+
+/* Different 82595 chips */
+#define LAN595 0
+#define LAN595TX 1
+#define LAN595FX 2
+#define LAN595FX_10ISA 3
+
+#define SLOW_DOWN inb(0x80);
+
+/* The station (ethernet) address prefix, used for IDing the board. */
+#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */
+#define SA_ADDR1 0xaa
+#define SA_ADDR2 0x00
+
+#define GetBit(x,y) ((x & (1<<y))>>y)
+
+/* EEPROM Word 0: */
+#define ee_PnP 0 /* Plug 'n Play enable bit */
+#define ee_Word1 1 /* Word 1? */
+#define ee_BusWidth 2 /* 8/16 bit */
+#define ee_FlashAddr 3 /* Flash Address */
+#define ee_FlashMask 0x7 /* Mask */
+#define ee_AutoIO 6 /* */
+#define ee_reserved0 7 /* =0! */
+#define ee_Flash 8 /* Flash there? */
+#define ee_AutoNeg 9 /* Auto Negotiation enabled? */
+#define ee_IO0 10 /* IO Address LSB */
+#define ee_IO0Mask 0x /*...*/
+#define ee_IO1 15 /* IO MSB */
+
+/* EEPROM Word 1: */
+#define ee_IntSel 0 /* Interrupt */
+#define ee_IntMask 0x7
+#define ee_LI 3 /* Link Integrity 0= enabled */
+#define ee_PC 4 /* Polarity Correction 0= enabled */
+#define ee_TPE_AUI 5 /* PortSelection 1=TPE */
+#define ee_Jabber 6 /* Jabber prevention 0= enabled */
+#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */
+#define ee_SMOUT 8 /* SMout Pin Control 0= Input */
+#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */
+#define ee_reserved1 10 /* .. 12 =0! */
+#define ee_AltReady 13 /* Alternate Ready, 0=normal */
+#define ee_reserved2 14 /* =0! */
+#define ee_Duplex 15
+
+/* Word2,3,4: */
+#define ee_IA5 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA4 8 /*bit start for individual Addr Byte 5 */
+#define ee_IA3 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA2 8 /*bit start for individual Addr Byte 5 */
+#define ee_IA1 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA0 8 /*bit start for individual Addr Byte 5 */
+
+/* Word 5: */
+#define ee_BNC_TPE 0 /* 0=TPE */
+#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
+#define ee_BootTypeMask 0x3
+#define ee_NumConn 3 /* Number of Connections 0= One or Two */
+#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */
+#define ee_PortTPE 5
+#define ee_PortBNC 6
+#define ee_PortAUI 7
+#define ee_PowerMgt 10 /* 0= disabled */
+#define ee_CP 13 /* Concurrent Processing */
+#define ee_CPMask 0x7
+
+/* Word 6: */
+#define ee_Stepping 0 /* Stepping info */
+#define ee_StepMask 0x0F
+#define ee_BoardID 4 /* Manucaturer Board ID, reserved */
+#define ee_BoardMask 0x0FFF
+
+/* Word 7: */
+#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */
+#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */
+
+/*..*/
+#define ee_SIZE 0x40 /* total EEprom Size */
+#define ee_Checksum 0xBABA /* initial and final value for adding checksum */
+
+
+/* Card identification via EEprom: */
+#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */
+#define ee_addr_id 0x11 /* Word offset for Card ID */
+#define ee_addr_SN 0x12 /* Serial Number */
+#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */
+
+
+#define ee_vendor_intel0 0x25 /* Vendor ID Intel */
+#define ee_vendor_intel1 0xD4
+#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */
+#define ee_id_eepro10p1 0x31
+
+/* now this section could be used by both boards: the oldies and the ee10:
+ * ee10 uses tx buffer before of rx buffer and the oldies the inverse.
+ * (aris)
+ */
+#define RAM_SIZE 0x8000
+
+#define RCV_HEADER 8
+#define RCV_DEFAULT_RAM 0x6000
+#define RCV_RAM rcv_ram
+
+static unsigned rcv_ram = RCV_DEFAULT_RAM;
+
+#define XMT_HEADER 8
+#define XMT_RAM (RAM_SIZE - RCV_RAM)
+
+#define XMT_START ((rcv_start + RCV_RAM) % RAM_SIZE)
+
+#define RCV_LOWER_LIMIT (rcv_start >> 8)
+#define RCV_UPPER_LIMIT (((rcv_start + RCV_RAM) - 2) >> 8)
+#define XMT_LOWER_LIMIT (XMT_START >> 8)
+#define XMT_UPPER_LIMIT (((XMT_START + XMT_RAM) - 2) >> 8)
+
+#define RCV_START_PRO 0x00
+#define RCV_START_10 XMT_RAM
+ /* by default the old driver */
+static unsigned rcv_start = RCV_START_PRO;
+
+#define RCV_DONE 0x0008
+#define RX_OK 0x2000
+#define RX_ERROR 0x0d81
+
+#define TX_DONE_BIT 0x0080
+#define CHAIN_BIT 0x8000
+#define XMT_STATUS 0x02
+#define XMT_CHAIN 0x04
+#define XMT_COUNT 0x06
+
+#define BANK0_SELECT 0x00
+#define BANK1_SELECT 0x40
+#define BANK2_SELECT 0x80
+
+/* Bank 0 registers */
+#define COMMAND_REG 0x00 /* Register 0 */
+#define MC_SETUP 0x03
+#define XMT_CMD 0x04
+#define DIAGNOSE_CMD 0x07
+#define RCV_ENABLE_CMD 0x08
+#define RCV_DISABLE_CMD 0x0a
+#define STOP_RCV_CMD 0x0b
+#define RESET_CMD 0x0e
+#define POWER_DOWN_CMD 0x18
+#define RESUME_XMT_CMD 0x1c
+#define SEL_RESET_CMD 0x1e
+#define STATUS_REG 0x01 /* Register 1 */
+#define RX_INT 0x02
+#define TX_INT 0x04
+#define EXEC_STATUS 0x30
+#define ID_REG 0x02 /* Register 2 */
+#define R_ROBIN_BITS 0xc0 /* round robin counter */
+#define ID_REG_MASK 0x2c
+#define ID_REG_SIG 0x24
+#define AUTO_ENABLE 0x10
+#define INT_MASK_REG 0x03 /* Register 3 */
+#define RX_STOP_MASK 0x01
+#define RX_MASK 0x02
+#define TX_MASK 0x04
+#define EXEC_MASK 0x08
+#define ALL_MASK 0x0f
+#define IO_32_BIT 0x10
+#define RCV_BAR 0x04 /* The following are word (16-bit) registers */
+#define RCV_STOP 0x06
+
+#define XMT_BAR_PRO 0x0a
+#define XMT_BAR_10 0x0b
+static unsigned xmt_bar = XMT_BAR_PRO;
+
+#define HOST_ADDRESS_REG 0x0c
+#define IO_PORT 0x0e
+#define IO_PORT_32_BIT 0x0c
+
+/* Bank 1 registers */
+#define REG1 0x01
+#define WORD_WIDTH 0x02
+#define INT_ENABLE 0x80
+#define INT_NO_REG 0x02
+#define RCV_LOWER_LIMIT_REG 0x08
+#define RCV_UPPER_LIMIT_REG 0x09
+
+#define XMT_LOWER_LIMIT_REG_PRO 0x0a
+#define XMT_UPPER_LIMIT_REG_PRO 0x0b
+#define XMT_LOWER_LIMIT_REG_10 0x0b
+#define XMT_UPPER_LIMIT_REG_10 0x0a
+static unsigned xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
+static unsigned xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
+
+/* Bank 2 registers */
+#define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */
+#define XMT_Chain_ErrStop 0x40 /* Interrupt at the end of the chain even if there are errors */
+#define RCV_Discard_BadFrame 0x80 /* Throw bad frames away, and continue to receive others */
+#define REG2 0x02
+#define PRMSC_Mode 0x01
+#define Multi_IA 0x20
+#define REG3 0x03
+#define TPE_BIT 0x04
+#define BNC_BIT 0x20
+#define REG13 0x0d
+#define FDX 0x00
+#define A_N_ENABLE 0x02
+
+#define I_ADD_REG0 0x04
+#define I_ADD_REG1 0x05
+#define I_ADD_REG2 0x06
+#define I_ADD_REG3 0x07
+#define I_ADD_REG4 0x08
+#define I_ADD_REG5 0x09
+
+#define EEPROM_REG_PRO 0x0a
+#define EEPROM_REG_10 0x0b
+static unsigned eeprom_reg = EEPROM_REG_PRO;
+
+#define EESK 0x01
+#define EECS 0x02
+#define EEDI 0x04
+#define EEDO 0x08
+
+/* The horrible routine to read a word from the serial EEPROM. */
+/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
+
+/* The delay between EEPROM clock transitions. */
+#define eeprom_delay() { udelay(40); }
+#define EE_READ_CMD (6 << 6)
+
+/* do a full reset; data sheet asks for 250us delay */
+#define eepro_full_reset(ioaddr) outb(RESET_CMD, ioaddr); udelay(255);
+
+/* do a nice reset */
+#define eepro_sel_reset(ioaddr) \
+ do { \
+ outb ( SEL_RESET_CMD, ioaddr ); \
+ (void) SLOW_DOWN; \
+ (void) SLOW_DOWN; \
+ } while (0)
+
+/* clear all interrupts */
+#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)
+
+/* enable rx */
+#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)
+
+/* disable rx */
+#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)
+
+/* switch bank */
+#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)
+#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)
+#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)
+
+static unsigned int rx_start, tx_start;
+static int tx_last;
+static unsigned int tx_end;
+static int eepro = 0;
+static unsigned int mem_start, mem_end = RCV_DEFAULT_RAM / 1024;
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void eepro_reset(struct nic *nic)
+{
+ int temp_reg, i;
+
+ /* put the card in its initial state */
+ eepro_sw2bank2(nic->ioaddr); /* be careful, bank2 now */
+ temp_reg = inb(nic->ioaddr + eeprom_reg);
+ DBG("Stepping %d\n", temp_reg >> 5);
+ if (temp_reg & 0x10) /* check the TurnOff Enable bit */
+ outb(temp_reg & 0xEF, nic->ioaddr + eeprom_reg);
+ for (i = 0; i < ETH_ALEN; i++) /* fill the MAC address */
+ outb(nic->node_addr[i], nic->ioaddr + I_ADD_REG0 + i);
+ temp_reg = inb(nic->ioaddr + REG1);
+ /* setup Transmit Chaining and discard bad RCV frames */
+ outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop
+ | RCV_Discard_BadFrame, nic->ioaddr + REG1);
+ temp_reg = inb(nic->ioaddr + REG2); /* match broadcast */
+ outb(temp_reg | 0x14, nic->ioaddr + REG2);
+ temp_reg = inb(nic->ioaddr + REG3);
+ outb(temp_reg & 0x3F, nic->ioaddr + REG3); /* clear test mode */
+ /* set the receiving mode */
+ eepro_sw2bank1(nic->ioaddr); /* be careful, bank1 now */
+ /* initialise the RCV and XMT upper and lower limits */
+ outb(RCV_LOWER_LIMIT, nic->ioaddr + RCV_LOWER_LIMIT_REG);
+ outb(RCV_UPPER_LIMIT, nic->ioaddr + RCV_UPPER_LIMIT_REG);
+ outb(XMT_LOWER_LIMIT, nic->ioaddr + xmt_lower_limit_reg);
+ outb(XMT_UPPER_LIMIT, nic->ioaddr + xmt_upper_limit_reg);
+ eepro_sw2bank0(nic->ioaddr); /* Switch back to bank 0 */
+ eepro_clear_int(nic->ioaddr);
+ /* Initialise RCV */
+ outw(rx_start = (RCV_LOWER_LIMIT << 8), nic->ioaddr + RCV_BAR);
+ outw(((RCV_UPPER_LIMIT << 8) | 0xFE), nic->ioaddr + RCV_STOP);
+ /* Make sure 1st poll won't find a valid packet header */
+ outw((RCV_LOWER_LIMIT << 8), nic->ioaddr + HOST_ADDRESS_REG);
+ outw(0, nic->ioaddr + IO_PORT);
+ /* Intialise XMT */
+ outw((XMT_LOWER_LIMIT << 8), nic->ioaddr + xmt_bar);
+ eepro_sel_reset(nic->ioaddr);
+ tx_start = tx_end = (unsigned int) (XMT_LOWER_LIMIT << 8);
+ tx_last = 0;
+ eepro_en_rx(nic->ioaddr);
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int eepro_poll(struct nic *nic, int retrieve)
+{
+ unsigned int rcv_car = rx_start;
+ unsigned int rcv_event, rcv_status, rcv_next_frame, rcv_size;
+
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+#if 0
+ if ((inb(nic->ioaddr + STATUS_REG) & 0x40) == 0)
+ return (0);
+ outb(0x40, nic->ioaddr + STATUS_REG);
+#endif
+ outw(rcv_car, nic->ioaddr + HOST_ADDRESS_REG);
+ rcv_event = inw(nic->ioaddr + IO_PORT);
+ if (rcv_event != RCV_DONE)
+ return (0);
+
+ /* FIXME: I'm guessing this might not work with this card, since
+ it looks like once a rcv_event is started it must be completed.
+ maybe there's another way. */
+ if ( ! retrieve ) return 1;
+
+ rcv_status = inw(nic->ioaddr + IO_PORT);
+ rcv_next_frame = inw(nic->ioaddr + IO_PORT);
+ rcv_size = inw(nic->ioaddr + IO_PORT);
+#if 0
+ printf("%hX %hX %d %hhX\n", rcv_status, rcv_next_frame, rcv_size,
+ inb(nic->ioaddr + STATUS_REG));
+#endif
+ if ((rcv_status & (RX_OK|RX_ERROR)) != RX_OK) {
+ printf("Receive error %hX\n", rcv_status);
+ return (0);
+ }
+ rcv_size &= 0x3FFF;
+ insw(nic->ioaddr + IO_PORT, nic->packet, ((rcv_size + 3) >> 1));
+#if 0
+{
+ int i;
+ for (i = 0; i < 48; i++) {
+ printf("%hhX", nic->packet[i]);
+ putchar(i % 16 == 15 ? '\n' : ' ');
+ }
+}
+#endif
+ nic->packetlen = rcv_size;
+ rcv_car = (rx_start + RCV_HEADER + rcv_size);
+ rx_start = rcv_next_frame;
+/*
+ hex_dump(rcv_car, nic->packetlen);
+*/
+
+ if (rcv_car == 0)
+ rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);
+ outw(rcv_car - 1, nic->ioaddr + RCV_STOP);
+ return (1);
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void eepro_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ unsigned int status, tx_available, last, end, length;
+ unsigned short type;
+ int boguscount = 20;
+
+ length = s + ETH_HLEN;
+ if (tx_end > tx_start)
+ tx_available = XMT_RAM - (tx_end - tx_start);
+ else if (tx_end < tx_start)
+ tx_available = tx_start - tx_end;
+ else
+ tx_available = XMT_RAM;
+ last = tx_end;
+ end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
+ if (end >= (XMT_UPPER_LIMIT << 8)) {
+ last = (XMT_LOWER_LIMIT << 8);
+ end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
+ }
+ outw(last, nic->ioaddr + HOST_ADDRESS_REG);
+ outw(XMT_CMD, nic->ioaddr + IO_PORT);
+ outw(0, nic->ioaddr + IO_PORT);
+ outw(end, nic->ioaddr + IO_PORT);
+ outw(length, nic->ioaddr + IO_PORT);
+ outsw(nic->ioaddr + IO_PORT, d, ETH_ALEN / 2);
+ outsw(nic->ioaddr + IO_PORT, nic->node_addr, ETH_ALEN / 2);
+ type = htons(t);
+ outsw(nic->ioaddr + IO_PORT, &type, sizeof(type) / 2);
+ outsw(nic->ioaddr + IO_PORT, p, (s + 3) >> 1);
+ /* A dummy read to flush the DRAM write pipeline */
+ status = inw(nic->ioaddr + IO_PORT);
+ outw(last, nic->ioaddr + xmt_bar);
+ outb(XMT_CMD, nic->ioaddr);
+ tx_start = last;
+ tx_last = last;
+ tx_end = end;
+#if 0
+ printf("%d %d\n", tx_start, tx_end);
+#endif
+ while (boguscount > 0) {
+ if (((status = inw(nic->ioaddr + IO_PORT)) & TX_DONE_BIT) == 0) {
+ udelay(40);
+ boguscount--;
+ continue;
+ }
+ if ((status & 0x2000) == 0) {
+ DBG("Transmit status %hX\n", status);
+ }
+ }
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void eepro_disable ( struct nic *nic, struct isa_device *isa __unused ) {
+ eepro_sw2bank0(nic->ioaddr); /* Switch to bank 0 */
+ /* Flush the Tx and disable Rx */
+ outb(STOP_RCV_CMD, nic->ioaddr);
+ tx_start = tx_end = (XMT_LOWER_LIMIT << 8);
+ tx_last = 0;
+ /* Reset the 82595 */
+ eepro_full_reset(nic->ioaddr);
+}
+
+/**************************************************************************
+DISABLE - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void eepro_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static int read_eeprom(uint16_t ioaddr, int location)
+{
+ int i;
+ unsigned short retval = 0;
+ int ee_addr = ioaddr + eeprom_reg;
+ int read_cmd = location | EE_READ_CMD;
+ int ctrl_val = EECS;
+
+ if (eepro == LAN595FX_10ISA) {
+ eepro_sw2bank1(ioaddr);
+ outb(0x00, ioaddr + STATUS_REG);
+ }
+ eepro_sw2bank2(ioaddr);
+ outb(ctrl_val, ee_addr);
+ /* shift the read command bits out */
+ for (i = 8; i >= 0; i--) {
+ short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;
+ outb(outval, ee_addr);
+ outb(outval | EESK, ee_addr); /* EEPROM clock tick */
+ eeprom_delay();
+ outb(outval, ee_addr); /* finish EEPROM clock tick */
+ eeprom_delay();
+ }
+ outb(ctrl_val, ee_addr);
+ for (i = 16; i > 0; i--) {
+ outb(ctrl_val | EESK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
+ outb(ctrl_val, ee_addr);
+ eeprom_delay();
+ }
+ /* terminate the EEPROM access */
+ ctrl_val &= ~EECS;
+ outb(ctrl_val | EESK, ee_addr);
+ eeprom_delay();
+ outb(ctrl_val, ee_addr);
+ eeprom_delay();
+ eepro_sw2bank0(ioaddr);
+ return (retval);
+}
+
+static int eepro_probe1 ( isa_probe_addr_t ioaddr ) {
+ int id, counter;
+
+ id = inb(ioaddr + ID_REG);
+ if ((id & ID_REG_MASK) != ID_REG_SIG)
+ return (0);
+ counter = id & R_ROBIN_BITS;
+ if (((id = inb(ioaddr + ID_REG)) & R_ROBIN_BITS) != (counter + 0x40))
+ return (0);
+ /* yes the 82595 has been found */
+ return (1);
+}
+
+static struct nic_operations eepro_operations = {
+ .connect = dummy_connect,
+ .poll = eepro_poll,
+ .transmit = eepro_transmit,
+ .irq = eepro_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int eepro_probe ( struct nic *nic, struct isa_device *isa ) {
+
+ int i, l_eepro = 0;
+ union {
+ unsigned char caddr[ETH_ALEN];
+ unsigned short saddr[ETH_ALEN/2];
+ } station_addr;
+ const char *name;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+
+ station_addr.saddr[2] = read_eeprom(nic->ioaddr,2);
+ if ( ( station_addr.saddr[2] == 0x0000 ) ||
+ ( station_addr.saddr[2] == 0xFFFF ) ) {
+ l_eepro = 3;
+ eepro = LAN595FX_10ISA;
+ eeprom_reg= EEPROM_REG_10;
+ rcv_start = RCV_START_10;
+ xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
+ xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
+ station_addr.saddr[2] = read_eeprom(nic->ioaddr,2);
+ }
+ station_addr.saddr[1] = read_eeprom(nic->ioaddr,3);
+ station_addr.saddr[0] = read_eeprom(nic->ioaddr,4);
+ if (l_eepro)
+ name = "Intel EtherExpress 10 ISA";
+ else if (read_eeprom(nic->ioaddr,7) == ee_FX_INT2IRQ) {
+ name = "Intel EtherExpress Pro/10+ ISA";
+ l_eepro = 2;
+ } else if (station_addr.saddr[0] == SA_ADDR1) {
+ name = "Intel EtherExpress Pro/10 ISA";
+ l_eepro = 1;
+ } else {
+ l_eepro = 0;
+ name = "Intel 82595-based LAN card";
+ }
+ station_addr.saddr[0] = swap16(station_addr.saddr[0]);
+ station_addr.saddr[1] = swap16(station_addr.saddr[1]);
+ station_addr.saddr[2] = swap16(station_addr.saddr[2]);
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = station_addr.caddr[i];
+ }
+
+ DBG ( "%s ioaddr %#hX, addr %s", name, nic->ioaddr, eth_ntoa ( nic->node_addr ) );
+
+ mem_start = RCV_LOWER_LIMIT << 8;
+ if ((mem_end & 0x3F) < 3 || (mem_end & 0x3F) > 29)
+ mem_end = RCV_UPPER_LIMIT << 8;
+ else {
+ mem_end = mem_end * 1024 + (RCV_LOWER_LIMIT << 8);
+ rcv_ram = mem_end - (RCV_LOWER_LIMIT << 8);
+ }
+ printf(", Rx mem %dK, if %s\n", (mem_end - mem_start) >> 10,
+ GetBit(read_eeprom(nic->ioaddr,5), ee_BNC_TPE) ? "BNC" : "TP");
+
+ eepro_reset(nic);
+
+ /* point to NIC specific routines */
+ nic->nic_op = &eepro_operations;
+ return 1;
+}
+
+static isa_probe_addr_t eepro_probe_addrs[] = {
+ 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360,
+};
+
+ISA_DRIVER ( eepro_driver, eepro_probe_addrs, eepro_probe1,
+ GENERIC_ISAPNP_VENDOR, 0x828a );
+
+DRIVER ( "eepro", nic_driver, isa_driver, eepro_driver,
+ eepro_probe, eepro_disable );
+
+ISA_ROM ( "eepro", "Intel Etherexpress Pro/10" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/eepro100.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/eepro100.c
new file mode 100644
index 0000000..85d7571
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/eepro100.c
@@ -0,0 +1,853 @@
+/*
+ * eepro100.c -- This file implements the eepro100 driver for etherboot.
+ *
+ *
+ * Copyright (C) AW Computer Systems.
+ * written by R.E.Wolff -- R.E.Wolff@BitWizard.nl
+ *
+ *
+ * AW Computer Systems is contributing to the free software community
+ * by paying for this driver and then putting the result under GPL.
+ *
+ * If you need a Linux device driver, please contact BitWizard for a
+ * quote.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * date version by what
+ * Written: May 29 1997 V0.10 REW Initial revision.
+ * changes: May 31 1997 V0.90 REW Works!
+ * Jun 1 1997 V0.91 REW Cleanup
+ * Jun 2 1997 V0.92 REW Add some code documentation
+ * Jul 25 1997 V1.00 REW Tested by AW to work in a PROM
+ * Cleanup for publication
+ * Dez 11 2004 V1.10 Kiszka Add RX ring buffer support
+ *
+ * This is the etherboot intel etherexpress Pro/100B driver.
+ *
+ * It was written from scratch, with Donald Beckers eepro100.c kernel
+ * driver as a guideline. Mostly the 82557 related definitions and the
+ * lower level routines have been cut-and-pasted into this source.
+ *
+ * The driver was finished before Intel got the NDA out of the closet.
+ * I still don't have the docs.
+ *
+ *
+ * Datasheet is now published and available from
+ * ftp://download.intel.com/design/network/manuals/8255X_OpenSDM.pdf
+ * - Michael Brown
+ * */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* Philosophy of this driver.
+ *
+ * Probing:
+ *
+ * Using the pci.c functions of the Etherboot code, the 82557 chip is detected.
+ * It is verified that the BIOS initialized everything properly and if
+ * something is missing it is done now.
+ *
+ *
+ * Initialization:
+ *
+ *
+ * The chip is then initialized to "know" its ethernet address, and to
+ * start recieving packets. The Linux driver has a whole transmit and
+ * recieve ring of buffers. This is neat if you need high performance:
+ * you can write the buffers asynchronously to the chip reading the
+ * buffers and transmitting them over the network. Performance is NOT
+ * an issue here. We can boot a 400k kernel in about two
+ * seconds. (Theory: 0.4 seconds). Booting a system is going to take
+ * about half a minute anyway, so getting 10 times closer to the
+ * theoretical limit is going to make a difference of a few percent. */
+/* Not totally true: busy networks can cause packet drops due to RX
+ * buffer overflows. Fixed in V1.10 of this driver. [Kiszka] */
+/*
+ *
+ * Transmitting and recieving.
+ *
+ * We have only one transmit descriptor. It has two buffer descriptors:
+ * one for the header, and the other for the data.
+ * We have multiple receive buffers (currently: 4). The chip is told to
+ * receive packets and suspend itself once it ran on the last free buffer.
+ * The recieve (poll) routine simply looks at the current recieve buffer,
+ * picks the packet if any, and releases this buffer again (classic ring
+ * buffer concept). This helps to avoid packet drops on busy networks.
+ *
+ * Caveats:
+ *
+ * The Etherboot framework moves the code to the 48k segment from
+ * 0x94000 to 0xa0000. There is just a little room between the end of
+ * this driver and the 0xa0000 address. If you compile in too many
+ * features, this will overflow.
+ * The number under "hex" in the output of size that scrolls by while
+ * compiling should be less than 8000. Maybe even the stack is up there,
+ * so that you need even more headroom.
+ */
+
+/* The etherboot authors seem to dislike the argument ordering in
+ * outb macros that Linux uses. I disklike the confusion that this
+ * has caused even more.... This file uses the Linux argument ordering. */
+/* Sorry not us. It's inherited code from FreeBSD. [The authors] */
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/ethernet.h>
+#include <gpxe/pci.h>
+
+static int ioaddr;
+
+enum speedo_offsets {
+ SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
+ SCBPointer = 4, /* General purpose pointer. */
+ SCBPort = 8, /* Misc. commands and operands. */
+ SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
+ SCBCtrlMDI = 16, /* MDI interface control. */
+ SCBEarlyRx = 20, /* Early receive byte count. */
+};
+
+enum SCBCmdBits {
+ SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
+ SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
+ SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
+ /* The rest are Rx and Tx commands. */
+ CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
+ CUCmdBase=0x0060, /* CU Base address (set to zero) . */
+ CUDumpStats=0x0070, /* Dump then reset stats counters. */
+ RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
+ RxResumeNoResources=0x0007,
+};
+
+static int do_eeprom_cmd(int cmd, int cmd_len);
+void hd(void *where, int n);
+
+/***********************************************************************/
+/* I82557 related defines */
+/***********************************************************************/
+
+/* Serial EEPROM section.
+ A "bit" grungy, but we work our way through bit-by-bit :->. */
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_WRITE_0 0x4802
+#define EE_WRITE_1 0x4806
+#define EE_ENB (0x4800 | EE_CS)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_READ_CMD 6
+
+/* The SCB accepts the following controls for the Tx and Rx units: */
+#define CU_START 0x0010
+#define CU_RESUME 0x0020
+#define CU_STATSADDR 0x0040
+#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
+#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */
+#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
+
+#define RX_START 0x0001
+#define RX_RESUME 0x0002
+#define RX_ABORT 0x0004
+#define RX_ADDR_LOAD 0x0006
+#define RX_RESUMENR 0x0007
+#define INT_MASK 0x0100
+#define DRVR_INT 0x0200 /* Driver generated interrupt. */
+
+enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
+ S80C24, PhyUndefined, DP83840A=10, };
+
+/* Commands that can be put in a command list entry. */
+enum commands {
+ CmdNOp = 0,
+ CmdIASetup = 1,
+ CmdConfigure = 2,
+ CmdMulticastList = 3,
+ CmdTx = 4,
+ CmdTDR = 5,
+ CmdDump = 6,
+ CmdDiagnose = 7,
+
+ /* And some extra flags: */
+ CmdSuspend = 0x4000, /* Suspend after completion. */
+ CmdIntr = 0x2000, /* Interrupt after completion. */
+ CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */
+};
+
+/* How to wait for the command unit to accept a command.
+ Typically this takes 0 ticks. */
+static inline void wait_for_cmd_done(int cmd_ioaddr)
+{
+ int wait = 0;
+ int delayed_cmd;
+
+ do
+ if (inb(cmd_ioaddr) == 0) return;
+ while(++wait <= 100);
+ delayed_cmd = inb(cmd_ioaddr);
+ do
+ if (inb(cmd_ioaddr) == 0) break;
+ while(++wait <= 10000);
+ printf("Command %2.2x was not immediately accepted, %d ticks!\n",
+ delayed_cmd, wait);
+}
+
+/* Elements of the dump_statistics block. This block must be lword aligned. */
+static struct speedo_stats {
+ u32 tx_good_frames;
+ u32 tx_coll16_errs;
+ u32 tx_late_colls;
+ u32 tx_underruns;
+ u32 tx_lost_carrier;
+ u32 tx_deferred;
+ u32 tx_one_colls;
+ u32 tx_multi_colls;
+ u32 tx_total_colls;
+ u32 rx_good_frames;
+ u32 rx_crc_errs;
+ u32 rx_align_errs;
+ u32 rx_resource_errs;
+ u32 rx_overrun_errs;
+ u32 rx_colls_errs;
+ u32 rx_runt_errs;
+ u32 done_marker;
+} lstats;
+
+/* A speedo3 TX buffer descriptor with two buffers... */
+static struct TxFD {
+ volatile s16 status;
+ s16 command;
+ u32 link; /* void * */
+ u32 tx_desc_addr; /* (almost) Always points to the tx_buf_addr element. */
+ s32 count; /* # of TBD (=2), Tx start thresh., etc. */
+ /* This constitutes two "TBD" entries: hdr and data */
+ u32 tx_buf_addr0; /* void *, header of frame to be transmitted. */
+ s32 tx_buf_size0; /* Length of Tx hdr. */
+ u32 tx_buf_addr1; /* void *, data to be transmitted. */
+ s32 tx_buf_size1; /* Length of Tx data. */
+} txfd;
+
+struct RxFD { /* Receive frame descriptor. */
+ volatile s16 status;
+ s16 command;
+ u32 link; /* struct RxFD * */
+ u32 rx_buf_addr; /* void * */
+ u16 count;
+ u16 size;
+ char packet[1518];
+};
+
+static struct nic_operations eepro100_operations;
+
+#define RXFD_COUNT 4
+struct {
+ struct RxFD rxfds[RXFD_COUNT];
+} eepro100_bufs __shared;
+#define rxfds eepro100_bufs.rxfds
+static unsigned int rxfd = 0;
+
+static int congenb = 0; /* Enable congestion control in the DP83840. */
+static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
+static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
+static int txdmacount = 0; /* Tx DMA burst length, 0-127, default 0. */
+static int rxdmacount = 0; /* Rx DMA length, 0 means no preemption. */
+
+/* I don't understand a byte in this structure. It was copied from the
+ * Linux kernel initialization for the eepro100. -- REW */
+static struct ConfCmd {
+ s16 status;
+ s16 command;
+ u32 link;
+ unsigned char data[22];
+} confcmd = {
+ 0, 0, 0, /* filled in later */
+ {22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
+ 0, 0x2E, 0, 0x60, 0,
+ 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
+ 0x3f, 0x05, }
+};
+
+/***********************************************************************/
+/* Locally used functions */
+/***********************************************************************/
+
+/* Support function: mdio_write
+ *
+ * This probably writes to the "physical media interface chip".
+ * -- REW
+ */
+
+static int mdio_write(int phy_id, int location, int value)
+{
+ int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
+
+ outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
+ ioaddr + SCBCtrlMDI);
+ do {
+ udelay(16);
+
+ val = inl(ioaddr + SCBCtrlMDI);
+ if (--boguscnt < 0) {
+ printf(" mdio_write() timed out with val = %X.\n", val);
+ break;
+ }
+ } while (! (val & 0x10000000));
+ return val & 0xffff;
+}
+
+/* Support function: mdio_read
+ *
+ * This probably reads a register in the "physical media interface chip".
+ * -- REW
+ */
+static int mdio_read(int phy_id, int location)
+{
+ int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
+ outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
+ do {
+ udelay(16);
+
+ val = inl(ioaddr + SCBCtrlMDI);
+
+ if (--boguscnt < 0) {
+ printf( " mdio_read() timed out with val = %X.\n", val);
+ break;
+ }
+ } while (! (val & 0x10000000));
+ return val & 0xffff;
+}
+
+/* The fixes for the code were kindly provided by Dragan Stancevic
+ <visitor@valinux.com> to strictly follow Intel specifications of EEPROM
+ access timing.
+ The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
+ interval for serial EEPROM. However, it looks like that there is an
+ additional requirement dictating larger udelay's in the code below.
+ 2000/05/24 SAW */
+static int do_eeprom_cmd(int cmd, int cmd_len)
+{
+ unsigned retval = 0;
+ long ee_addr = ioaddr + SCBeeprom;
+
+ outw(EE_ENB, ee_addr); udelay(2);
+ outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
+
+ /* Shift the command bits out. */
+ do {
+ short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+ outw(dataval, ee_addr); udelay(2);
+ outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
+ retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ } while (--cmd_len >= 0);
+ outw(EE_ENB, ee_addr); udelay(2);
+
+ /* Terminate the EEPROM access. */
+ outw(EE_ENB & ~EE_CS, ee_addr);
+ return retval;
+}
+
+#if 0
+static inline void whereami (const char *str)
+{
+ printf ("%s\n", str);
+ sleep (2);
+}
+#else
+#define whereami(s)
+#endif
+
+static void eepro100_irq(struct nic *nic __unused, irq_action_t action)
+{
+ uint16_t enabled_mask = ( SCBMaskCmdDone | SCBMaskCmdIdle |
+ SCBMaskEarlyRx | SCBMaskFlowCtl );
+
+ switch ( action ) {
+ case DISABLE :
+ outw(SCBMaskAll, ioaddr + SCBCmd);
+ break;
+ case ENABLE :
+ outw(enabled_mask, ioaddr + SCBCmd);
+ break;
+ case FORCE :
+ outw(enabled_mask | SCBTriggerIntr, ioaddr + SCBCmd);
+ break;
+ }
+}
+
+/* function: eepro100_transmit
+ * This transmits a packet.
+ *
+ * Arguments: char d[6]: destination ethernet address.
+ * unsigned short t: ethernet protocol type.
+ * unsigned short s: size of the data-part of the packet.
+ * char *p: the data for the packet.
+ * returns: void.
+ */
+
+static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
+{
+ struct eth_hdr {
+ unsigned char dst_addr[ETH_ALEN];
+ unsigned char src_addr[ETH_ALEN];
+ unsigned short type;
+ } hdr;
+ unsigned short status;
+ int s1, s2;
+ unsigned long ct;
+
+ status = inw(ioaddr + SCBStatus);
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ outw(status & 0xfc00, ioaddr + SCBStatus);
+
+#ifdef DEBUG
+ printf ("transmitting type %hX packet (%d bytes). status = %hX, cmd=%hX\n",
+ t, s, status, inw (ioaddr + SCBCmd));
+#endif
+
+ memcpy (&hdr.dst_addr, d, ETH_ALEN);
+ memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);
+
+ hdr.type = htons (t);
+
+ txfd.status = 0;
+ txfd.command = CmdSuspend | CmdTx | CmdTxFlex;
+ txfd.link = virt_to_bus (&txfd);
+ txfd.count = 0x02208000;
+ txfd.tx_desc_addr = virt_to_bus(&txfd.tx_buf_addr0);
+
+ txfd.tx_buf_addr0 = virt_to_bus (&hdr);
+ txfd.tx_buf_size0 = sizeof (hdr);
+
+ txfd.tx_buf_addr1 = virt_to_bus (p);
+ txfd.tx_buf_size1 = s;
+
+#ifdef DEBUG
+ printf ("txfd: \n");
+ hd (&txfd, sizeof (txfd));
+#endif
+
+ outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
+ outb(CU_START, ioaddr + SCBCmd);
+ wait_for_cmd_done(ioaddr + SCBCmd);
+
+ s1 = inw (ioaddr + SCBStatus);
+
+ ct = currticks();
+ /* timeout 10 ms for transmit */
+ while (!txfd.status && ct + 10*1000)
+ /* Wait */;
+ s2 = inw (ioaddr + SCBStatus);
+
+#ifdef DEBUG
+ printf ("s1 = %hX, s2 = %hX.\n", s1, s2);
+#endif
+}
+
+/*
+ * Sometimes the receiver stops making progress. This routine knows how to
+ * get it going again, without losing packets or being otherwise nasty like
+ * a chip reset would be. Previously the driver had a whole sequence
+ * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
+ * do another, etc. But those things don't really matter. Separate logic
+ * in the ISR provides for allocating buffers--the other half of operation
+ * is just making sure the receiver is active. speedo_rx_soft_reset does that.
+ * This problem with the old, more involved algorithm is shown up under
+ * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
+ */
+static void
+speedo_rx_soft_reset(void)
+{
+ int i;
+
+
+#ifdef DEBUG
+ printf("reset\n");
+#endif
+ wait_for_cmd_done(ioaddr + SCBCmd);
+ /*
+ * Put the hardware into a known state.
+ */
+ outb(RX_ABORT, ioaddr + SCBCmd);
+
+ for (i = 0; i < RXFD_COUNT; i++) {
+ rxfds[i].status = 0;
+ rxfds[i].rx_buf_addr = 0xffffffff;
+ rxfds[i].count = 0;
+ rxfds[i].size = 1528;
+ }
+
+ wait_for_cmd_done(ioaddr + SCBCmd);
+
+ outl(virt_to_bus(&rxfds[rxfd]), ioaddr + SCBPointer);
+ outb(RX_START, ioaddr + SCBCmd);
+}
+
+/* function: eepro100_poll / eth_poll
+ * This receives a packet from the network.
+ *
+ * Arguments: none
+ *
+ * returns: 1 if a packet was received.
+ * 0 if no packet was received.
+ * side effects:
+ * returns the packet in the array nic->packet.
+ * returns the length of the packet in nic->packetlen.
+ */
+
+static int eepro100_poll(struct nic *nic, int retrieve)
+{
+ if (rxfds[rxfd].status) {
+ if (!retrieve)
+ return 1;
+#ifdef DEBUG
+ printf("Got a packet: Len = %d, rxfd = %d.\n",
+ rxfds[rxfd].count & 0x3fff, rxfd);
+#endif
+ /* First save the data from the rxfd */
+ nic->packetlen = rxfds[rxfd].count & 0x3fff;
+ memcpy(nic->packet, rxfds[rxfd].packet, nic->packetlen);
+
+ rxfds[rxfd].status = 0;
+ rxfds[rxfd].command = 0xc000;
+ rxfds[rxfd].rx_buf_addr = 0xFFFFFFFF;
+ rxfds[rxfd].count = 0;
+ rxfds[rxfd].size = 1528;
+ rxfds[(rxfd-1) % RXFD_COUNT].command = 0x0000;
+ rxfd = (rxfd+1) % RXFD_COUNT;
+
+#ifdef DEBUG
+ hd (nic->packet, 0x30);
+#endif
+
+ /* Acknowledge all conceivable interrupts */
+ outw(0xff00, ioaddr + SCBStatus);
+
+ return 1;
+ }
+
+ /*
+ * The chip may have suspended reception for various reasons.
+ * Check for that, and re-prime it should this be the case.
+ */
+ switch ((inw(ioaddr + SCBStatus) >> 2) & 0xf) {
+ case 0: /* Idle */
+ break;
+ case 1: /* Suspended */
+ case 2: /* No resources (RxFDs) */
+ case 9: /* Suspended with no more RBDs */
+ case 10: /* No resources due to no RBDs */
+ case 12: /* Ready with no RBDs */
+ speedo_rx_soft_reset();
+ break;
+ default:
+ /* reserved values */
+ break;
+ }
+ return 0;
+}
+
+/* function: eepro100_disable
+ * resets the card. This is used to allow Etherboot or Linux
+ * to probe the card again from a "virginal" state....
+ * Arguments: none
+ *
+ * returns: void.
+ */
+static void eepro100_disable ( struct nic *nic __unused ) {
+/* from eepro100_reset */
+ outl(0, ioaddr + SCBPort);
+/* from eepro100_disable */
+ /* See if this PartialReset solves the problem with interfering with
+ kernel operation after Etherboot hands over. - Ken 20001102 */
+ outl(2, ioaddr + SCBPort);
+
+ /* The following is from the Intel e100 driver.
+ * This hopefully solves the problem with hanging hard DOS images. */
+
+ /* wait for the reset to take effect */
+ udelay(20);
+
+ /* Mask off our interrupt line -- it is unmasked after reset */
+ {
+ u16 intr_status;
+ /* Disable interrupts on our PCI board by setting the mask bit */
+ outw(INT_MASK, ioaddr + SCBCmd);
+ intr_status = inw(ioaddr + SCBStatus);
+ /* ack and clear intrs */
+ outw(intr_status, ioaddr + SCBStatus);
+ inw(ioaddr + SCBStatus);
+ }
+}
+
+/* exported function: eepro100_probe / eth_probe
+ * initializes a card
+ *
+ * side effects:
+ * leaves the ioaddress of the 82557 chip in the variable ioaddr.
+ * leaves the 82557 initialized, and ready to recieve packets.
+ */
+
+static int eepro100_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ unsigned short sum = 0;
+ int i;
+ int read_cmd, ee_size;
+ int options;
+ int rx_mode;
+ unsigned long ct;
+
+ /* we cache only the first few words of the EEPROM data
+ be careful not to access beyond this array */
+ unsigned short eeprom[16];
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ adjust_pci_device(pci);
+
+ nic->ioaddr = pci->ioaddr;
+ nic->irqno = pci->irq;
+
+ ioaddr = nic->ioaddr;
+
+ if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000)
+ == 0xffe0000) {
+ ee_size = 0x100;
+ read_cmd = EE_READ_CMD << 24;
+ } else {
+ ee_size = 0x40;
+ read_cmd = EE_READ_CMD << 22;
+ }
+
+ for (i = 0, sum = 0; i < ee_size; i++) {
+ unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27);
+ if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))
+ eeprom[i] = value;
+ sum += value;
+ }
+
+ for (i=0;i<ETH_ALEN;i++) {
+ nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
+ }
+
+ DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ if (sum != 0xBABA)
+ printf("eepro100: Invalid EEPROM checksum %#hX, "
+ "check settings before activating this device!\n", sum);
+ outl(0, ioaddr + SCBPort);
+ udelay (10000);
+ whereami ("Got eeprom.");
+
+ /* Base = 0, disable all interrupts */
+ outl(0, ioaddr + SCBPointer);
+ outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);
+ wait_for_cmd_done(ioaddr + SCBCmd);
+ whereami ("set rx base addr.");
+
+ outl(virt_to_bus(&lstats), ioaddr + SCBPointer);
+ outb(CU_STATSADDR, ioaddr + SCBCmd);
+ wait_for_cmd_done(ioaddr + SCBCmd);
+ whereami ("set stats addr.");
+
+ /* INIT RX stuff. */
+ for (i = 0; i < RXFD_COUNT; i++) {
+ rxfds[i].status = 0x0000;
+ rxfds[i].command = 0x0000;
+ rxfds[i].rx_buf_addr = 0xFFFFFFFF;
+ rxfds[i].count = 0;
+ rxfds[i].size = 1528;
+ rxfds[i].link = virt_to_bus(&rxfds[i+1]);
+ }
+
+ rxfds[RXFD_COUNT-1].status = 0x0000;
+ rxfds[RXFD_COUNT-1].command = 0xC000;
+ rxfds[RXFD_COUNT-1].link = virt_to_bus(&rxfds[0]);
+
+ outl(virt_to_bus(&rxfds[0]), ioaddr + SCBPointer);
+ outb(RX_START, ioaddr + SCBCmd);
+ wait_for_cmd_done(ioaddr + SCBCmd);
+
+ whereami ("started RX process.");
+
+ /* INIT TX stuff. */
+
+ /* Base = 0 */
+ outl(0, ioaddr + SCBPointer);
+ outb(CU_CMD_BASE, ioaddr + SCBCmd);
+ wait_for_cmd_done(ioaddr + SCBCmd);
+
+ whereami ("set TX base addr.");
+
+ txfd.command = (CmdIASetup);
+ txfd.status = 0x0000;
+ txfd.link = virt_to_bus (&confcmd);
+
+ {
+ char *t = (char *)&txfd.tx_desc_addr;
+
+ for (i=0;i<ETH_ALEN;i++)
+ t[i] = nic->node_addr[i];
+ }
+
+#ifdef DEBUG
+ printf ("Setup_eaddr:\n");
+ hd (&txfd, 0x20);
+#endif
+ /* options = 0x40; */ /* 10mbps half duplex... */
+ options = 0x00; /* Autosense */
+
+#ifdef PROMISC
+ rx_mode = 3;
+#elif ALLMULTI
+ rx_mode = 1;
+#else
+ rx_mode = 0;
+#endif
+
+ if ( ((eeprom[6]>>8) & 0x3f) == DP83840
+ || ((eeprom[6]>>8) & 0x3f) == DP83840A) {
+ int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422;
+ if (congenb)
+ mdi_reg23 |= 0x0100;
+ printf(" DP83840 specific setup, setting register 23 to %hX.\n",
+ mdi_reg23);
+ mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);
+ }
+ whereami ("Done DP8340 special setup.");
+ if (options != 0) {
+ mdio_write(eeprom[6] & 0x1f, 0,
+ ((options & 0x20) ? 0x2000 : 0) | /* 100mbps? */
+ ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
+ whereami ("set mdio_register.");
+ }
+
+ confcmd.command = CmdSuspend | CmdConfigure;
+ confcmd.status = 0x0000;
+ confcmd.link = virt_to_bus (&txfd);
+ confcmd.data[1] = (txfifo << 4) | rxfifo;
+ confcmd.data[4] = rxdmacount;
+ confcmd.data[5] = txdmacount + 0x80;
+ confcmd.data[15] = (rx_mode & 2) ? 0x49: 0x48;
+ confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80;
+ confcmd.data[21] = (rx_mode & 1) ? 0x0D: 0x05;
+
+ outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
+ outb(CU_START, ioaddr + SCBCmd);
+ wait_for_cmd_done(ioaddr + SCBCmd);
+
+ whereami ("started TX thingy (config, iasetup).");
+
+ ct = currticks();
+ while (!txfd.status && ct + 10*1000 < currticks())
+ /* Wait */;
+
+ /* Read the status register once to disgard stale data */
+ mdio_read(eeprom[6] & 0x1f, 1);
+ /* Check to see if the network cable is plugged in.
+ * This allows for faster failure if there is nothing
+ * we can do.
+ */
+ if (!(mdio_read(eeprom[6] & 0x1f, 1) & (1 << 2))) {
+ printf("Valid link not established\n");
+ eepro100_disable(nic);
+ return 0;
+ }
+ nic->nic_op = &eepro100_operations;
+ return 1;
+}
+
+/*********************************************************************/
+
+#ifdef DEBUG
+
+/* Hexdump a number of bytes from memory... */
+void hd (void *where, int n)
+{
+ int i;
+
+ while (n > 0) {
+ printf ("%X ", where);
+ for (i=0;i < ( (n>16)?16:n);i++)
+ printf (" %hhX", ((char *)where)[i]);
+ printf ("\n");
+ n -= 16;
+ where += 16;
+ }
+}
+#endif
+
+static struct nic_operations eepro100_operations = {
+ .connect = dummy_connect,
+ .poll = eepro100_poll,
+ .transmit = eepro100_transmit,
+ .irq = eepro100_irq,
+
+};
+
+static struct pci_device_id eepro100_nics[] = {
+PCI_ROM(0x8086, 0x1029, "id1029", "Intel EtherExpressPro100 ID1029", 0),
+PCI_ROM(0x8086, 0x1030, "id1030", "Intel EtherExpressPro100 ID1030", 0),
+PCI_ROM(0x8086, 0x1031, "82801cam", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection", 0),
+PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1038, "id1038", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1039, "82562et", "Intel PRO100 VE 82562ET", 0),
+PCI_ROM(0x8086, 0x103a, "id103a", "Intel Corporation 82559 InBusiness 10/100", 0),
+PCI_ROM(0x8086, 0x103b, "82562etb", "Intel PRO100 VE 82562ETB", 0),
+PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection", 0),
+PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection", 0),
+PCI_ROM(0x8086, 0x1051, "prove", "Intel PRO/100 VE Network Connection", 0),
+PCI_ROM(0x8086, 0x1059, "82551qm", "Intel PRO/100 M Mobile Connection", 0),
+PCI_ROM(0x8086, 0x1209, "82559er", "Intel EtherExpressPro100 82559ER", 0),
+PCI_ROM(0x8086, 0x1227, "82865", "Intel 82865 EtherExpress PRO/100A", 0),
+PCI_ROM(0x8086, 0x1228, "82556", "Intel 82556 EtherExpress PRO/100 Smart", 0),
+PCI_ROM(0x8086, 0x1229, "eepro100", "Intel EtherExpressPro100", 0),
+PCI_ROM(0x8086, 0x2449, "82562em", "Intel EtherExpressPro100 82562EM", 0),
+PCI_ROM(0x8086, 0x2459, "82562-1", "Intel 82562 based Fast Ethernet Connection", 0),
+PCI_ROM(0x8086, 0x245d, "82562-2", "Intel 82562 based Fast Ethernet Connection", 0),
+PCI_ROM(0x8086, 0x1050, "82562ez", "Intel 82562EZ Network Connection", 0),
+PCI_ROM(0x8086, 0x1051, "eepro100-1051", "Intel 82801EB/ER (ICH5/ICH5R) Chipset Ethernet Controller", 0),
+PCI_ROM(0x8086, 0x1065, "82562-3", "Intel 82562 based Fast Ethernet Connection", 0),
+PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server", 0),
+PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server", 0),
+};
+
+/* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need
+ * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c)
+ * 2003/03/17 gbaum */
+
+
+PCI_DRIVER ( eepro100_driver, eepro100_nics, PCI_NO_CLASS );
+
+DRIVER ( "EEPRO100", nic_driver, pci_driver, eepro100_driver,
+ eepro100_probe, eepro100_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.c
new file mode 100644
index 0000000..aaa85f8
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.c
@@ -0,0 +1,539 @@
+
+/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Etherboot */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* 05/06/2003 timlegge Fixed relocation and implemented Multicast */
+#define LINUX_OUT_MACROS
+
+#include "etherboot.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include "nic.h"
+#include "console.h"
+#include "epic100.h"
+
+/* Condensed operations for readability */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+#define TX_RING_SIZE 2 /* use at least 2 buffers for TX */
+#define RX_RING_SIZE 2
+
+#define PKT_BUF_SZ 1536 /* Size of each temporary Tx/Rx buffer.*/
+
+/*
+#define DEBUG_RX
+#define DEBUG_TX
+#define DEBUG_EEPROM
+*/
+
+#define EPIC_DEBUG 0 /* debug level */
+
+/* The EPIC100 Rx and Tx buffer descriptors. */
+struct epic_rx_desc {
+ unsigned long status;
+ unsigned long bufaddr;
+ unsigned long buflength;
+ unsigned long next;
+};
+/* description of the tx descriptors control bits commonly used */
+#define TD_STDFLAGS TD_LASTDESC
+
+struct epic_tx_desc {
+ unsigned long status;
+ unsigned long bufaddr;
+ unsigned long buflength;
+ unsigned long next;
+};
+
+#define delay(nanosec) do { int _i = 3; while (--_i > 0) \
+ { __SLOW_DOWN_IO; }} while (0)
+
+static void epic100_open(void);
+static void epic100_init_ring(void);
+static void epic100_disable(struct nic *nic);
+static int epic100_poll(struct nic *nic, int retrieve);
+static void epic100_transmit(struct nic *nic, const char *destaddr,
+ unsigned int type, unsigned int len, const char *data);
+#ifdef DEBUG_EEPROM
+static int read_eeprom(int location);
+#endif
+static int mii_read(int phy_id, int location);
+static void epic100_irq(struct nic *nic, irq_action_t action);
+
+static struct nic_operations epic100_operations;
+
+static int ioaddr;
+
+static int command;
+static int intstat;
+static int intmask;
+static int genctl ;
+static int eectl ;
+static int test ;
+static int mmctl ;
+static int mmdata ;
+static int lan0 ;
+static int mc0 ;
+static int rxcon ;
+static int txcon ;
+static int prcdar ;
+static int ptcdar ;
+static int eththr ;
+
+static unsigned int cur_rx, cur_tx; /* The next free ring entry */
+#ifdef DEBUG_EEPROM
+static unsigned short eeprom[64];
+#endif
+static signed char phys[4]; /* MII device addresses. */
+struct {
+ struct epic_rx_desc rx_ring[RX_RING_SIZE]
+ __attribute__ ((aligned(4)));
+ struct epic_tx_desc tx_ring[TX_RING_SIZE]
+ __attribute__ ((aligned(4)));
+ unsigned char rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
+ unsigned char tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
+} epic100_bufs __shared;
+#define rx_ring epic100_bufs.rx_ring
+#define tx_ring epic100_bufs.tx_ring
+#define rx_packet epic100_bufs.rx_packet
+#define tx_packet epic100_bufs.tx_packet
+
+/***********************************************************************/
+/* Externally visible functions */
+/***********************************************************************/
+
+
+static int
+epic100_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+ unsigned short* ap;
+ unsigned int phy, phy_idx;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ /* Ideally we would detect all network cards in slot order. That would
+ be best done a central PCI probe dispatch, which wouldn't work
+ well with the current structure. So instead we detect just the
+ Epic cards in slot order. */
+
+ ioaddr = pci->ioaddr;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr & ~3;
+
+ /* compute all used static epic100 registers address */
+ command = ioaddr + COMMAND; /* Control Register */
+ intstat = ioaddr + INTSTAT; /* Interrupt Status */
+ intmask = ioaddr + INTMASK; /* Interrupt Mask */
+ genctl = ioaddr + GENCTL; /* General Control */
+ eectl = ioaddr + EECTL; /* EEPROM Control */
+ test = ioaddr + TEST; /* Test register (clocks) */
+ mmctl = ioaddr + MMCTL; /* MII Management Interface Control */
+ mmdata = ioaddr + MMDATA; /* MII Management Interface Data */
+ lan0 = ioaddr + LAN0; /* MAC address. (0x40-0x48) */
+ mc0 = ioaddr + MC0; /* Multicast Control */
+ rxcon = ioaddr + RXCON; /* Receive Control */
+ txcon = ioaddr + TXCON; /* Transmit Control */
+ prcdar = ioaddr + PRCDAR; /* PCI Receive Current Descr Address */
+ ptcdar = ioaddr + PTCDAR; /* PCI Transmit Current Descr Address */
+ eththr = ioaddr + ETHTHR; /* Early Transmit Threshold */
+
+ /* Reset the chip & bring it out of low-power mode. */
+ outl(GC_SOFT_RESET, genctl);
+
+ /* Disable ALL interrupts by setting the interrupt mask. */
+ outl(INTR_DISABLE, intmask);
+
+ /*
+ * set the internal clocks:
+ * Application Note 7.15 says:
+ * In order to set the CLOCK TEST bit in the TEST register,
+ * perform the following:
+ *
+ * Write 0x0008 to the test register at least sixteen
+ * consecutive times.
+ *
+ * The CLOCK TEST bit is Write-Only. Writing it several times
+ * consecutively insures a successful write to the bit...
+ */
+
+ for (i = 0; i < 16; i++) {
+ outl(0x00000008, test);
+ }
+
+#ifdef DEBUG_EEPROM
+{
+ unsigned short sum = 0;
+ unsigned short value;
+ for (i = 0; i < 64; i++) {
+ value = read_eeprom(i);
+ eeprom[i] = value;
+ sum += value;
+ }
+}
+
+#if (EPIC_DEBUG > 1)
+ printf("EEPROM contents\n");
+ for (i = 0; i < 64; i++) {
+ printf(" %hhX%s", eeprom[i], i % 16 == 15 ? "\n" : "");
+ }
+#endif
+#endif
+
+ /* This could also be read from the EEPROM. */
+ ap = (unsigned short*)nic->node_addr;
+ for (i = 0; i < 3; i++)
+ *ap++ = inw(lan0 + i*4);
+
+ DBG ( " I/O %4.4x %s ", ioaddr, eth_ntoa ( nic->node_addr ) );
+
+ /* Find the connected MII xcvrs. */
+ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) {
+ int mii_status = mii_read(phy, 0);
+
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ phys[phy_idx++] = phy;
+#if (EPIC_DEBUG > 1)
+ printf("MII transceiver found at address %d.\n", phy);
+#endif
+ }
+ }
+ if (phy_idx == 0) {
+#if (EPIC_DEBUG > 1)
+ printf("***WARNING***: No MII transceiver found!\n");
+#endif
+ /* Use the known PHY address of the EPII. */
+ phys[0] = 3;
+ }
+
+ epic100_open();
+ nic->nic_op = &epic100_operations;
+
+ return 1;
+}
+
+static void set_rx_mode(void)
+{
+ unsigned char mc_filter[8];
+ int i;
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+ outl(0x0C, rxcon);
+ for(i = 0; i < 4; i++)
+ outw(((unsigned short *)mc_filter)[i], mc0 + i*4);
+ return;
+}
+
+ static void
+epic100_open(void)
+{
+ int mii_reg5;
+ int full_duplex = 0;
+ unsigned long tmp;
+
+ epic100_init_ring();
+
+ /* Pull the chip out of low-power mode, and set for PCI read multiple. */
+ outl(GC_RX_FIFO_THR_64 | GC_MRC_READ_MULT | GC_ONE_COPY, genctl);
+
+ outl(TX_FIFO_THRESH, eththr);
+
+ tmp = TC_EARLY_TX_ENABLE | TX_SLOT_TIME;
+
+ mii_reg5 = mii_read(phys[0], 5);
+ if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
+ full_duplex = 1;
+ printf(" full-duplex mode");
+ tmp |= TC_LM_FULL_DPX;
+ } else
+ tmp |= TC_LM_NORMAL;
+
+ outl(tmp, txcon);
+
+ /* Give adress of RX and TX ring to the chip */
+ outl(virt_to_le32desc(&rx_ring), prcdar);
+ outl(virt_to_le32desc(&tx_ring), ptcdar);
+
+ /* Start the chip's Rx process: receive unicast and broadcast */
+ set_rx_mode();
+ outl(CR_START_RX | CR_QUEUE_RX, command);
+
+ putchar('\n');
+}
+
+/* Initialize the Rx and Tx rings. */
+ static void
+epic100_init_ring(void)
+{
+ int i;
+
+ cur_rx = cur_tx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].status = cpu_to_le32(RRING_OWN); /* Owned by Epic chip */
+ rx_ring[i].buflength = cpu_to_le32(PKT_BUF_SZ);
+ rx_ring[i].bufaddr = virt_to_bus(&rx_packet[i * PKT_BUF_SZ]);
+ rx_ring[i].next = virt_to_le32desc(&rx_ring[i + 1]) ;
+ }
+ /* Mark the last entry as wrapping the ring. */
+ rx_ring[i-1].next = virt_to_le32desc(&rx_ring[0]);
+
+ /*
+ *The Tx buffer descriptor is filled in as needed,
+ * but we do need to clear the ownership bit.
+ */
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ tx_ring[i].status = 0x0000; /* Owned by CPU */
+ tx_ring[i].buflength = 0x0000 | cpu_to_le32(TD_STDFLAGS << 16);
+ tx_ring[i].bufaddr = virt_to_bus(&tx_packet[i * PKT_BUF_SZ]);
+ tx_ring[i].next = virt_to_le32desc(&tx_ring[i + 1]);
+ }
+ tx_ring[i-1].next = virt_to_le32desc(&tx_ring[0]);
+}
+
+/* function: epic100_transmit
+ * This transmits a packet.
+ *
+ * Arguments: char d[6]: destination ethernet address.
+ * unsigned short t: ethernet protocol type.
+ * unsigned short s: size of the data-part of the packet.
+ * char *p: the data for the packet.
+ * returns: void.
+ */
+ static void
+epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
+ unsigned int len, const char *data)
+{
+ unsigned short nstype;
+ unsigned char *txp;
+ int entry;
+ unsigned long ct;
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = cur_tx % TX_RING_SIZE;
+
+ if ((tx_ring[entry].status & TRING_OWN) == TRING_OWN) {
+ printf("eth_transmit: Unable to transmit. status=%4.4lx. Resetting...\n",
+ tx_ring[entry].status);
+
+ epic100_open();
+ return;
+ }
+
+ txp = tx_packet + (entry * PKT_BUF_SZ);
+
+ memcpy(txp, destaddr, ETH_ALEN);
+ memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons(type);
+ memcpy(txp + 12, (char*)&nstype, 2);
+ memcpy(txp + ETH_HLEN, data, len);
+
+ len += ETH_HLEN;
+ len &= 0x0FFF;
+ while(len < ETH_ZLEN)
+ txp[len++] = '\0';
+ /*
+ * Caution: the write order is important here,
+ * set the base address with the "ownership"
+ * bits last.
+ */
+
+ tx_ring[entry].buflength |= cpu_to_le32(len);
+ tx_ring[entry].status = cpu_to_le32(len << 16) |
+ cpu_to_le32(TRING_OWN); /* Pass ownership to the chip. */
+
+ cur_tx++;
+
+ /* Trigger an immediate transmit demand. */
+ outl(CR_QUEUE_TX, command);
+
+ ct = currticks();
+ /* timeout 10 ms for transmit */
+ while ((le32_to_cpu(tx_ring[entry].status) & (TRING_OWN)) &&
+ ct + 10*1000 < currticks())
+ /* Wait */;
+
+ if ((le32_to_cpu(tx_ring[entry].status) & TRING_OWN) != 0)
+ printf("Oops, transmitter timeout, status=%4.4lX\n",
+ tx_ring[entry].status);
+}
+
+/* function: epic100_poll / eth_poll
+ * This receives a packet from the network.
+ *
+ * Arguments: none
+ *
+ * returns: 1 if a packet was received.
+ * 0 if no pacet was received.
+ * side effects:
+ * returns the packet in the array nic->packet.
+ * returns the length of the packet in nic->packetlen.
+ */
+
+ static int
+epic100_poll(struct nic *nic, int retrieve)
+{
+ int entry;
+ int retcode;
+ int status;
+ entry = cur_rx % RX_RING_SIZE;
+
+ if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN)
+ return (0);
+
+ if ( ! retrieve ) return 1;
+
+ status = le32_to_cpu(rx_ring[entry].status);
+ /* We own the next entry, it's a new packet. Send it up. */
+
+#if (EPIC_DEBUG > 4)
+ printf("epic_poll: entry %d status %hX\n", entry, status);
+#endif
+
+ cur_rx++;
+ if (status & 0x2000) {
+ printf("epic_poll: Giant packet\n");
+ retcode = 0;
+ } else if (status & 0x0006) {
+ /* Rx Frame errors are counted in hardware. */
+ printf("epic_poll: Frame received with errors\n");
+ retcode = 0;
+ } else {
+ /* Omit the four octet CRC from the length. */
+ nic->packetlen = le32_to_cpu((rx_ring[entry].buflength))- 4;
+ memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen);
+ retcode = 1;
+ }
+
+ /* Clear all error sources. */
+ outl(status & INTR_CLEARERRS, intstat);
+
+ /* Give the descriptor back to the chip */
+ rx_ring[entry].status = RRING_OWN;
+
+ /* Restart Receiver */
+ outl(CR_START_RX | CR_QUEUE_RX, command);
+
+ return retcode;
+}
+
+
+static void epic100_disable ( struct nic *nic __unused ) {
+ /* Soft reset the chip. */
+ outl(GC_SOFT_RESET, genctl);
+}
+
+static void epic100_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+#ifdef DEBUG_EEPROM
+/* Serial EEPROM section. */
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x08 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x09
+#define EE_DATA_READ 0x10 /* EEPROM chip data out. */
+#define EE_ENB (0x0001 | EE_CS)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << 6)
+#define EE_READ_CMD (6 << 6)
+#define EE_ERASE_CMD (7 << 6)
+
+#define eeprom_delay(n) delay(n)
+
+ static int
+read_eeprom(int location)
+{
+ int i;
+ int retval = 0;
+ int read_cmd = location | EE_READ_CMD;
+
+ outl(EE_ENB & ~EE_CS, eectl);
+ outl(EE_ENB, eectl);
+
+ /* Shift the read command bits out. */
+ for (i = 10; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, eectl);
+ eeprom_delay(100);
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, eectl);
+ eeprom_delay(150);
+ outl(EE_ENB | dataval, eectl); /* Finish EEPROM a clock tick. */
+ eeprom_delay(250);
+ }
+ outl(EE_ENB, eectl);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, eectl);
+ eeprom_delay(100);
+ retval = (retval << 1) | ((inl(eectl) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, eectl);
+ eeprom_delay(100);
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, eectl);
+ return retval;
+}
+#endif
+
+
+#define MII_READOP 1
+#define MII_WRITEOP 2
+
+ static int
+mii_read(int phy_id, int location)
+{
+ int i;
+
+ outl((phy_id << 9) | (location << 4) | MII_READOP, mmctl);
+ /* Typical operation takes < 50 ticks. */
+
+ for (i = 4000; i > 0; i--)
+ if ((inl(mmctl) & MII_READOP) == 0)
+ break;
+ return inw(mmdata);
+}
+
+static struct nic_operations epic100_operations = {
+ .connect = dummy_connect,
+ .poll = epic100_poll,
+ .transmit = epic100_transmit,
+ .irq = epic100_irq,
+
+};
+
+static struct pci_device_id epic100_nics[] = {
+PCI_ROM(0x10b8, 0x0005, "epic100", "SMC EtherPowerII", 0), /* SMC 83c170 EPIC/100 */
+PCI_ROM(0x10b8, 0x0006, "smc-83c175", "SMC EPIC/C 83c175", 0),
+};
+
+PCI_DRIVER ( epic100_driver, epic100_nics, PCI_NO_CLASS );
+
+DRIVER ( "EPIC100", nic_driver, pci_driver, epic100_driver,
+ epic100_probe, epic100_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.h
new file mode 100644
index 0000000..f290b10
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/epic100.h
@@ -0,0 +1,190 @@
+#ifndef _EPIC100_H_
+# define _EPIC100_H_
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef PCI_VENDOR_SMC
+# define PCI_VENDOR_SMC 0x10B8
+#endif
+
+#ifndef PCI_DEVICE_SMC_EPIC100
+# define PCI_DEVICE_SMC_EPIC100 0x0005
+#endif
+
+#define PCI_DEVICE_ID_NONE 0xFFFF
+
+/* Offsets to registers (using SMC names). */
+enum epic100_registers {
+ COMMAND= 0, /* Control Register */
+ INTSTAT= 4, /* Interrupt Status */
+ INTMASK= 8, /* Interrupt Mask */
+ GENCTL = 0x0C, /* General Control */
+ NVCTL = 0x10, /* Non Volatile Control */
+ EECTL = 0x14, /* EEPROM Control */
+ TEST = 0x1C, /* Test register: marked as reserved (see in source code) */
+ CRCCNT = 0x20, /* CRC Error Counter */
+ ALICNT = 0x24, /* Frame Alignment Error Counter */
+ MPCNT = 0x28, /* Missed Packet Counter */
+ MMCTL = 0x30, /* MII Management Interface Control */
+ MMDATA = 0x34, /* MII Management Interface Data */
+ MIICFG = 0x38, /* MII Configuration */
+ IPG = 0x3C, /* InterPacket Gap */
+ LAN0 = 0x40, /* MAC address. (0x40-0x48) */
+ IDCHK = 0x4C, /* BoardID/ Checksum */
+ MC0 = 0x50, /* Multicast filter table. (0x50-0x5c) */
+ RXCON = 0x60, /* Receive Control */
+ TXCON = 0x70, /* Transmit Control */
+ TXSTAT = 0x74, /* Transmit Status */
+ PRCDAR = 0x84, /* PCI Receive Current Descriptor Address */
+ PRSTAT = 0xA4, /* PCI Receive DMA Status */
+ PRCPTHR= 0xB0, /* PCI Receive Copy Threshold */
+ PTCDAR = 0xC4, /* PCI Transmit Current Descriptor Address */
+ ETHTHR = 0xDC /* Early Transmit Threshold */
+};
+
+/* Command register (CR_) bits */
+#define CR_STOP_RX (0x00000001)
+#define CR_START_RX (0x00000002)
+#define CR_QUEUE_TX (0x00000004)
+#define CR_QUEUE_RX (0x00000008)
+#define CR_NEXTFRAME (0x00000010)
+#define CR_STOP_TX_DMA (0x00000020)
+#define CR_STOP_RX_DMA (0x00000040)
+#define CR_TX_UGO (0x00000080)
+
+/* Interrupt register bits. NI means No Interrupt generated */
+
+#define INTR_RX_THR_STA (0x00400000) /* rx copy threshold status NI */
+#define INTR_RX_BUFF_EMPTY (0x00200000) /* rx buffers empty. NI */
+#define INTR_TX_IN_PROG (0x00100000) /* tx copy in progess. NI */
+#define INTR_RX_IN_PROG (0x00080000) /* rx copy in progress. NI */
+#define INTR_TXIDLE (0x00040000) /* tx idle. NI */
+#define INTR_RXIDLE (0x00020000) /* rx idle. NI */
+#define INTR_INTR_ACTIVE (0x00010000) /* Interrupt active. NI */
+#define INTR_RX_STATUS_OK (0x00008000) /* rx status valid. NI */
+#define INTR_PCI_TGT_ABT (0x00004000) /* PCI Target abort */
+#define INTR_PCI_MASTER_ABT (0x00002000) /* PCI Master abort */
+#define INTR_PCI_PARITY_ERR (0x00001000) /* PCI adress parity error */
+#define INTR_PCI_DATA_ERR (0x00000800) /* PCI data parity error */
+#define INTR_RX_THR_CROSSED (0x00000400) /* rx copy threshold crossed */
+#define INTR_CNTFULL (0x00000200) /* Counter overflow */
+#define INTR_TXUNDERRUN (0x00000100) /* tx underrun. */
+#define INTR_TXEMPTY (0x00000080) /* tx queue empty */
+#define INTR_TX_CH_COMPLETE (0x00000040) /* tx chain complete */
+#define INTR_TXDONE (0x00000020) /* tx complete (w or w/o err) */
+#define INTR_RXERROR (0x00000010) /* rx error (CRC) */
+#define INTR_RXOVERFLOW (0x00000008) /* rx buffer overflow */
+#define INTR_RX_QUEUE_EMPTY (0x00000004) /* rx queue empty. */
+#define INTR_RXHEADER (0x00000002) /* header copy complete */
+#define INTR_RXDONE (0x00000001) /* Receive copy complete */
+
+#define INTR_CLEARINTR (0x00007FFF)
+#define INTR_VALIDBITS (0x007FFFFF)
+#define INTR_DISABLE (0x00000000)
+#define INTR_CLEARERRS (0x00007F18)
+#define INTR_ABNINTR (INTR_CNTFULL | INTR_TXUNDERRUN | INTR_RXOVERFLOW)
+
+/* General Control (GC_) bits */
+
+#define GC_SOFT_RESET (0x00000001)
+#define GC_INTR_ENABLE (0x00000002)
+#define GC_SOFT_INTR (0x00000004)
+#define GC_POWER_DOWN (0x00000008)
+#define GC_ONE_COPY (0x00000010)
+#define GC_BIG_ENDIAN (0x00000020)
+#define GC_RX_PREEMPT_TX (0x00000040)
+#define GC_TX_PREEMPT_RX (0x00000080)
+
+/*
+ * Receive FIFO Threshold values
+ * Control the level at which the PCI burst state machine
+ * begins to empty the receive FIFO. Possible values: 0-3
+ *
+ * 0 => 32, 1 => 64, 2 => 96 3 => 128 bytes.
+ */
+#define GC_RX_FIFO_THR_32 (0x00000000)
+#define GC_RX_FIFO_THR_64 (0x00000100)
+#define GC_RX_FIFO_THR_96 (0x00000200)
+#define GC_RX_FIFO_THR_128 (0x00000300)
+
+/* Memory Read Control (MRC_) values */
+#define GC_MRC_MEM_READ (0x00000000)
+#define GC_MRC_READ_MULT (0x00000400)
+#define GC_MRC_READ_LINE (0x00000800)
+
+#define GC_SOFTBIT0 (0x00001000)
+#define GC_SOFTBIT1 (0x00002000)
+#define GC_RESET_PHY (0x00004000)
+
+/* Definitions of the Receive Control (RC_) register bits */
+
+#define RC_SAVE_ERRORED_PKT (0x00000001)
+#define RC_SAVE_RUNT_FRAMES (0x00000002)
+#define RC_RCV_BROADCAST (0x00000004)
+#define RC_RCV_MULTICAST (0x00000008)
+#define RC_RCV_INVERSE_PKT (0x00000010)
+#define RC_PROMISCUOUS_MODE (0x00000020)
+#define RC_MONITOR_MODE (0x00000040)
+#define RC_EARLY_RCV_ENABLE (0x00000080)
+
+/* description of the rx descriptors control bits */
+#define RD_FRAGLIST (0x0001) /* Desc points to a fragment list */
+#define RD_LLFORM (0x0002) /* Frag list format */
+#define RD_HDR_CPY (0x0004) /* Desc used for header copy */
+
+/* Definition of the Transmit CONTROL (TC) register bits */
+
+#define TC_EARLY_TX_ENABLE (0x00000001)
+
+/* Loopback Mode (LM_) Select valuesbits */
+#define TC_LM_NORMAL (0x00000000)
+#define TC_LM_INTERNAL (0x00000002)
+#define TC_LM_EXTERNAL (0x00000004)
+#define TC_LM_FULL_DPX (0x00000006)
+
+#define TX_SLOT_TIME (0x00000078)
+
+/* Bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
+
+/* description of rx descriptors status bits */
+#define RRING_PKT_INTACT (0x0001)
+#define RRING_ALIGN_ERR (0x0002)
+#define RRING_CRC_ERR (0x0004)
+#define RRING_MISSED_PKT (0x0008)
+#define RRING_MULTICAST (0x0010)
+#define RRING_BROADCAST (0x0020)
+#define RRING_RECEIVER_DISABLE (0x0040)
+#define RRING_STATUS_VALID (0x1000)
+#define RRING_FRAGLIST_ERR (0x2000)
+#define RRING_HDR_COPIED (0x4000)
+#define RRING_OWN (0x8000)
+
+/* error summary */
+#define RRING_ERROR (RRING_ALIGN_ERR|RRING_CRC_ERR)
+
+/* description of tx descriptors status bits */
+#define TRING_PKT_INTACT (0x0001) /* pkt transmitted. */
+#define TRING_PKT_NONDEFER (0x0002) /* pkt xmitted w/o deferring */
+#define TRING_COLL (0x0004) /* pkt xmitted w collisions */
+#define TRING_CARR (0x0008) /* carrier sense lost */
+#define TRING_UNDERRUN (0x0010) /* DMA underrun */
+#define TRING_HB_COLL (0x0020) /* Collision detect Heartbeat */
+#define TRING_WIN_COLL (0x0040) /* out of window collision */
+#define TRING_DEFERRED (0x0080) /* Deferring */
+#define TRING_COLL_COUNT (0x0F00) /* collision counter (mask) */
+#define TRING_COLL_EXCESS (0x1000) /* tx aborted: excessive colls */
+#define TRING_OWN (0x8000) /* desc ownership bit */
+
+/* error summary */
+#define TRING_ABORT (TRING_COLL_EXCESS|TRING_WIN_COLL|TRING_UNDERRUN)
+#define TRING_ERROR (TRING_DEFERRED|TRING_WIN_COLL|TRING_UNDERRUN|TRING_CARR/*|TRING_COLL*/ )
+
+/* description of the tx descriptors control bits */
+#define TD_FRAGLIST (0x0001) /* Desc points to a fragment list */
+#define TD_LLFORM (0x0002) /* Frag list format */
+#define TD_IAF (0x0004) /* Generate Interrupt after tx */
+#define TD_NOCRC (0x0008) /* No CRC generated */
+#define TD_LASTDESC (0x0010) /* Last desc for this frame */
+
+#endif /* _EPIC100_H_ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.c
new file mode 100644
index 0000000..c4296b9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.c
@@ -0,0 +1,4236 @@
+/**************************************************************************
+ *
+ * Etherboot driver for Level 5 Etherfabric network cards
+ *
+ * Written by Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Copyright Fen Systems Ltd. 2005
+ * Copyright Level 5 Networks Inc. 2005
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ **************************************************************************
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <console.h>
+#include <gpxe/io.h>
+#include <gpxe/pci.h>
+#include <gpxe/malloc.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/timer.h>
+#include <mii.h>
+#include "etherfabric.h"
+#include "etherfabric_nic.h"
+
+/**************************************************************************
+ *
+ * Constants and macros
+ *
+ **************************************************************************
+ */
+
+#define EFAB_REGDUMP(...)
+#define EFAB_TRACE(...) DBGP(__VA_ARGS__)
+
+// printf() is not allowed within drivers. Use DBG() instead.
+#define EFAB_LOG(...) DBG(__VA_ARGS__)
+#define EFAB_ERR(...) DBG(__VA_ARGS__)
+
+#define FALCON_USE_IO_BAR 0
+
+#define HZ 100
+#define EFAB_BYTE 1
+
+/**************************************************************************
+ *
+ * Hardware data structures and sizing
+ *
+ **************************************************************************
+ */
+extern int __invalid_queue_size;
+#define FQS(_prefix, _x) \
+ ( ( (_x) == 512 ) ? _prefix ## _SIZE_512 : \
+ ( ( (_x) == 1024 ) ? _prefix ## _SIZE_1K : \
+ ( ( (_x) == 2048 ) ? _prefix ## _SIZE_2K : \
+ ( ( (_x) == 4096) ? _prefix ## _SIZE_4K : \
+ __invalid_queue_size ) ) ) )
+
+
+#define EFAB_MAX_FRAME_LEN(mtu) \
+ ( ( ( ( mtu ) + 4/* FCS */ ) + 7 ) & ~7 )
+
+/**************************************************************************
+ *
+ * GMII routines
+ *
+ **************************************************************************
+ */
+
+static void falcon_mdio_write (struct efab_nic *efab, int device,
+ int location, int value );
+static int falcon_mdio_read ( struct efab_nic *efab, int device, int location );
+
+/* GMII registers */
+#define GMII_PSSR 0x11 /* PHY-specific status register */
+
+/* Pseudo extensions to the link partner ability register */
+#define LPA_EF_1000FULL 0x00020000
+#define LPA_EF_1000HALF 0x00010000
+#define LPA_EF_10000FULL 0x00040000
+#define LPA_EF_10000HALF 0x00080000
+
+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+#define LPA_EF_1000 ( LPA_EF_1000FULL | LPA_EF_1000HALF )
+#define LPA_EF_10000 ( LPA_EF_10000FULL | LPA_EF_10000HALF )
+#define LPA_EF_DUPLEX ( LPA_10FULL | LPA_100FULL | LPA_EF_1000FULL | \
+ LPA_EF_10000FULL )
+
+/* Mask of bits not associated with speed or duplexity. */
+#define LPA_OTHER ~( LPA_10FULL | LPA_10HALF | LPA_100FULL | \
+ LPA_100HALF | LPA_EF_1000FULL | LPA_EF_1000HALF )
+
+/* PHY-specific status register */
+#define PSSR_LSTATUS 0x0400 /* Bit 10 - link status */
+
+/**
+ * Retrieve GMII autonegotiation advertised abilities
+ *
+ */
+static unsigned int
+gmii_autoneg_advertised ( struct efab_nic *efab )
+{
+ unsigned int mii_advertise;
+ unsigned int gmii_advertise;
+
+ /* Extended bits are in bits 8 and 9 of MII_CTRL1000 */
+ mii_advertise = falcon_mdio_read ( efab, 0, MII_ADVERTISE );
+ gmii_advertise = ( ( falcon_mdio_read ( efab, 0, MII_CTRL1000 ) >> 8 )
+ & 0x03 );
+ return ( ( gmii_advertise << 16 ) | mii_advertise );
+}
+
+/**
+ * Retrieve GMII autonegotiation link partner abilities
+ *
+ */
+static unsigned int
+gmii_autoneg_lpa ( struct efab_nic *efab )
+{
+ unsigned int mii_lpa;
+ unsigned int gmii_lpa;
+
+ /* Extended bits are in bits 10 and 11 of MII_STAT1000 */
+ mii_lpa = falcon_mdio_read ( efab, 0, MII_LPA );
+ gmii_lpa = ( falcon_mdio_read ( efab, 0, MII_STAT1000 ) >> 10 ) & 0x03;
+ return ( ( gmii_lpa << 16 ) | mii_lpa );
+}
+
+/**
+ * Calculate GMII autonegotiated link technology
+ *
+ */
+static unsigned int
+gmii_nway_result ( unsigned int negotiated )
+{
+ unsigned int other_bits;
+
+ /* Mask out the speed and duplexity bits */
+ other_bits = negotiated & LPA_OTHER;
+
+ if ( negotiated & LPA_EF_1000FULL )
+ return ( other_bits | LPA_EF_1000FULL );
+ else if ( negotiated & LPA_EF_1000HALF )
+ return ( other_bits | LPA_EF_1000HALF );
+ else if ( negotiated & LPA_100FULL )
+ return ( other_bits | LPA_100FULL );
+ else if ( negotiated & LPA_100BASE4 )
+ return ( other_bits | LPA_100BASE4 );
+ else if ( negotiated & LPA_100HALF )
+ return ( other_bits | LPA_100HALF );
+ else if ( negotiated & LPA_10FULL )
+ return ( other_bits | LPA_10FULL );
+ else return ( other_bits | LPA_10HALF );
+}
+
+/**
+ * Check GMII PHY link status
+ *
+ */
+static int
+gmii_link_ok ( struct efab_nic *efab )
+{
+ int status;
+ int phy_status;
+
+ /* BMSR is latching - it returns "link down" if the link has
+ * been down at any point since the last read. To get a
+ * real-time status, we therefore read the register twice and
+ * use the result of the second read.
+ */
+ (void) falcon_mdio_read ( efab, 0, MII_BMSR );
+ status = falcon_mdio_read ( efab, 0, MII_BMSR );
+
+ /* Read the PHY-specific Status Register. This is
+ * non-latching, so we need do only a single read.
+ */
+ phy_status = falcon_mdio_read ( efab, 0, GMII_PSSR );
+
+ return ( ( status & BMSR_LSTATUS ) && ( phy_status & PSSR_LSTATUS ) );
+}
+
+/**************************************************************************
+ *
+ * MDIO routines
+ *
+ **************************************************************************
+ */
+
+/* Numbering of the MDIO Manageable Devices (MMDs) */
+/* Physical Medium Attachment/ Physical Medium Dependent sublayer */
+#define MDIO_MMD_PMAPMD (1)
+/* WAN Interface Sublayer */
+#define MDIO_MMD_WIS (2)
+/* Physical Coding Sublayer */
+#define MDIO_MMD_PCS (3)
+/* PHY Extender Sublayer */
+#define MDIO_MMD_PHYXS (4)
+/* Extender Sublayer */
+#define MDIO_MMD_DTEXS (5)
+/* Transmission convergence */
+#define MDIO_MMD_TC (6)
+/* Auto negotiation */
+#define MDIO_MMD_AN (7)
+
+/* Generic register locations */
+#define MDIO_MMDREG_CTRL1 (0)
+#define MDIO_MMDREG_STAT1 (1)
+#define MDIO_MMDREG_DEVS0 (5)
+#define MDIO_MMDREG_STAT2 (8)
+
+/* Bits in MMDREG_CTRL1 */
+/* Reset */
+#define MDIO_MMDREG_CTRL1_RESET_LBN (15)
+#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1)
+
+/* Bits in MMDREG_STAT1 */
+#define MDIO_MMDREG_STAT1_FAULT_LBN (7)
+#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1)
+
+/* Link state */
+#define MDIO_MMDREG_STAT1_LINK_LBN (2)
+#define MDIO_MMDREG_STAT1_LINK_WIDTH (1)
+
+/* Bits in MMDREG_DEVS0. */
+#define DEV_PRESENT_BIT(_b) (1 << _b)
+
+#define MDIO_MMDREG_DEVS0_DTEXS DEV_PRESENT_BIT(MDIO_MMD_DTEXS)
+#define MDIO_MMDREG_DEVS0_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
+#define MDIO_MMDREG_DEVS0_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS)
+#define MDIO_MMDREG_DEVS0_WIS DEV_PRESENT_BIT(MDIO_MMD_WIS)
+#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
+
+#define MDIO_MMDREG_DEVS0_AN DEV_PRESENT_BIT(MDIO_MMD_AN)
+
+/* Bits in MMDREG_STAT2 */
+#define MDIO_MMDREG_STAT2_PRESENT_VAL (2)
+#define MDIO_MMDREG_STAT2_PRESENT_LBN (14)
+#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2)
+
+/* PHY XGXS lane state */
+#define MDIO_PHYXS_LANE_STATE (0x18)
+#define MDIO_PHYXS_LANE_ALIGNED_LBN (12)
+#define MDIO_PHYXS_LANE_SYNC0_LBN (0)
+#define MDIO_PHYXS_LANE_SYNC1_LBN (1)
+#define MDIO_PHYXS_LANE_SYNC2_LBN (2)
+#define MDIO_PHYXS_LANE_SYNC3_LBN (3)
+
+/* This ought to be ridiculous overkill. We expect it to fail rarely */
+#define MDIO45_RESET_TRIES 100
+#define MDIO45_RESET_SPINTIME 10
+
+static int
+mdio_clause45_wait_reset_mmds ( struct efab_nic* efab )
+{
+ int tries = MDIO45_RESET_TRIES;
+ int in_reset;
+
+ while(tries) {
+ int mask = efab->phy_op->mmds;
+ int mmd = 0;
+ in_reset = 0;
+ while(mask) {
+ if (mask & 1) {
+ int stat = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_CTRL1 );
+ if (stat < 0) {
+ EFAB_ERR("Failed to read status of MMD %d\n",
+ mmd );
+ in_reset = 1;
+ break;
+ }
+ if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))
+ in_reset |= (1 << mmd);
+ }
+ mask = mask >> 1;
+ mmd++;
+ }
+ if (!in_reset)
+ break;
+ tries--;
+ mdelay ( MDIO45_RESET_SPINTIME );
+ }
+ if (in_reset != 0) {
+ EFAB_ERR("Not all MMDs came out of reset in time. MMDs "
+ "still in reset: %x\n", in_reset);
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int
+mdio_clause45_reset_mmd ( struct efab_nic *efab, int mmd )
+{
+ int tries = MDIO45_RESET_TRIES;
+ int ctrl;
+
+ falcon_mdio_write ( efab, mmd, MDIO_MMDREG_CTRL1,
+ ( 1 << MDIO_MMDREG_CTRL1_RESET_LBN ) );
+
+ /* Wait for the reset bit to clear. */
+ do {
+ mdelay ( MDIO45_RESET_SPINTIME );
+
+ ctrl = falcon_mdio_read ( efab, mmd, MDIO_MMDREG_CTRL1 );
+ if ( ~ctrl & ( 1 << MDIO_MMDREG_CTRL1_RESET_LBN ) )
+ return 0;
+ } while ( --tries );
+
+ EFAB_ERR ( "Failed to reset mmd %d\n", mmd );
+
+ return -ETIMEDOUT;
+}
+
+static int
+mdio_clause45_links_ok(struct efab_nic *efab )
+{
+ int status, good;
+ int ok = 1;
+ int mmd = 0;
+ int mmd_mask = efab->phy_op->mmds;
+
+ while (mmd_mask) {
+ if (mmd_mask & 1) {
+ /* Double reads because link state is latched, and a
+ * read moves the current state into the register */
+ status = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_STAT1 );
+ status = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_STAT1 );
+
+ good = status & (1 << MDIO_MMDREG_STAT1_LINK_LBN);
+ ok = ok && good;
+ }
+ mmd_mask = (mmd_mask >> 1);
+ mmd++;
+ }
+ return ok;
+}
+
+static int
+mdio_clause45_check_mmds ( struct efab_nic *efab )
+{
+ int mmd = 0;
+ int devices = falcon_mdio_read ( efab, MDIO_MMD_PHYXS,
+ MDIO_MMDREG_DEVS0 );
+ int mmd_mask = efab->phy_op->mmds;
+
+ /* Check all the expected MMDs are present */
+ if ( devices < 0 ) {
+ EFAB_ERR ( "Failed to read devices present\n" );
+ return -EIO;
+ }
+ if ( ( devices & mmd_mask ) != mmd_mask ) {
+ EFAB_ERR ( "required MMDs not present: got %x, wanted %x\n",
+ devices, mmd_mask );
+ return -EIO;
+ }
+
+ /* Check all required MMDs are responding and happy. */
+ while ( mmd_mask ) {
+ if ( mmd_mask & 1 ) {
+ efab_dword_t reg;
+ int status;
+ reg.opaque = falcon_mdio_read ( efab, mmd,
+ MDIO_MMDREG_STAT2 );
+ status = EFAB_DWORD_FIELD ( reg,
+ MDIO_MMDREG_STAT2_PRESENT );
+ if ( status != MDIO_MMDREG_STAT2_PRESENT_VAL ) {
+
+
+ return -EIO;
+ }
+ }
+ mmd_mask >>= 1;
+ mmd++;
+ }
+
+ return 0;
+}
+
+/* I/O BAR address register */
+#define FCN_IOM_IND_ADR_REG 0x0
+
+/* I/O BAR data register */
+#define FCN_IOM_IND_DAT_REG 0x4
+
+/* Address region register */
+#define FCN_ADR_REGION_REG_KER 0x00
+#define FCN_ADR_REGION0_LBN 0
+#define FCN_ADR_REGION0_WIDTH 18
+#define FCN_ADR_REGION1_LBN 32
+#define FCN_ADR_REGION1_WIDTH 18
+#define FCN_ADR_REGION2_LBN 64
+#define FCN_ADR_REGION2_WIDTH 18
+#define FCN_ADR_REGION3_LBN 96
+#define FCN_ADR_REGION3_WIDTH 18
+
+/* Interrupt enable register */
+#define FCN_INT_EN_REG_KER 0x0010
+#define FCN_MEM_PERR_INT_EN_KER_LBN 5
+#define FCN_MEM_PERR_INT_EN_KER_WIDTH 1
+#define FCN_KER_INT_CHAR_LBN 4
+#define FCN_KER_INT_CHAR_WIDTH 1
+#define FCN_KER_INT_KER_LBN 3
+#define FCN_KER_INT_KER_WIDTH 1
+#define FCN_ILL_ADR_ERR_INT_EN_KER_LBN 2
+#define FCN_ILL_ADR_ERR_INT_EN_KER_WIDTH 1
+#define FCN_SRM_PERR_INT_EN_KER_LBN 1
+#define FCN_SRM_PERR_INT_EN_KER_WIDTH 1
+#define FCN_DRV_INT_EN_KER_LBN 0
+#define FCN_DRV_INT_EN_KER_WIDTH 1
+
+/* Interrupt status register */
+#define FCN_INT_ADR_REG_KER 0x0030
+#define FCN_INT_ADR_KER_LBN 0
+#define FCN_INT_ADR_KER_WIDTH EFAB_DMA_TYPE_WIDTH ( 64 )
+
+/* Interrupt status register (B0 only) */
+#define INT_ISR0_B0 0x90
+#define INT_ISR1_B0 0xA0
+
+/* Interrupt acknowledge register (A0/A1 only) */
+#define FCN_INT_ACK_KER_REG_A1 0x0050
+#define INT_ACK_DUMMY_DATA_LBN 0
+#define INT_ACK_DUMMY_DATA_WIDTH 32
+
+/* Interrupt acknowledge work-around register (A0/A1 only )*/
+#define WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 0x0070
+
+/* Hardware initialisation register */
+#define FCN_HW_INIT_REG_KER 0x00c0
+#define FCN_BCSR_TARGET_MASK_LBN 101
+#define FCN_BCSR_TARGET_MASK_WIDTH 4
+
+/* SPI host command register */
+#define FCN_EE_SPI_HCMD_REG 0x0100
+#define FCN_EE_SPI_HCMD_CMD_EN_LBN 31
+#define FCN_EE_SPI_HCMD_CMD_EN_WIDTH 1
+#define FCN_EE_WR_TIMER_ACTIVE_LBN 28
+#define FCN_EE_WR_TIMER_ACTIVE_WIDTH 1
+#define FCN_EE_SPI_HCMD_SF_SEL_LBN 24
+#define FCN_EE_SPI_HCMD_SF_SEL_WIDTH 1
+#define FCN_EE_SPI_EEPROM 0
+#define FCN_EE_SPI_FLASH 1
+#define FCN_EE_SPI_HCMD_DABCNT_LBN 16
+#define FCN_EE_SPI_HCMD_DABCNT_WIDTH 5
+#define FCN_EE_SPI_HCMD_READ_LBN 15
+#define FCN_EE_SPI_HCMD_READ_WIDTH 1
+#define FCN_EE_SPI_READ 1
+#define FCN_EE_SPI_WRITE 0
+#define FCN_EE_SPI_HCMD_DUBCNT_LBN 12
+#define FCN_EE_SPI_HCMD_DUBCNT_WIDTH 2
+#define FCN_EE_SPI_HCMD_ADBCNT_LBN 8
+#define FCN_EE_SPI_HCMD_ADBCNT_WIDTH 2
+#define FCN_EE_SPI_HCMD_ENC_LBN 0
+#define FCN_EE_SPI_HCMD_ENC_WIDTH 8
+
+/* SPI host address register */
+#define FCN_EE_SPI_HADR_REG 0x0110
+#define FCN_EE_SPI_HADR_DUBYTE_LBN 24
+#define FCN_EE_SPI_HADR_DUBYTE_WIDTH 8
+#define FCN_EE_SPI_HADR_ADR_LBN 0
+#define FCN_EE_SPI_HADR_ADR_WIDTH 24
+
+/* SPI host data register */
+#define FCN_EE_SPI_HDATA_REG 0x0120
+#define FCN_EE_SPI_HDATA3_LBN 96
+#define FCN_EE_SPI_HDATA3_WIDTH 32
+#define FCN_EE_SPI_HDATA2_LBN 64
+#define FCN_EE_SPI_HDATA2_WIDTH 32
+#define FCN_EE_SPI_HDATA1_LBN 32
+#define FCN_EE_SPI_HDATA1_WIDTH 32
+#define FCN_EE_SPI_HDATA0_LBN 0
+#define FCN_EE_SPI_HDATA0_WIDTH 32
+
+/* VPD Config 0 Register register */
+#define FCN_EE_VPD_CFG_REG 0x0140
+#define FCN_EE_VPD_EN_LBN 0
+#define FCN_EE_VPD_EN_WIDTH 1
+#define FCN_EE_VPD_EN_AD9_MODE_LBN 1
+#define FCN_EE_VPD_EN_AD9_MODE_WIDTH 1
+#define FCN_EE_EE_CLOCK_DIV_LBN 112
+#define FCN_EE_EE_CLOCK_DIV_WIDTH 7
+#define FCN_EE_SF_CLOCK_DIV_LBN 120
+#define FCN_EE_SF_CLOCK_DIV_WIDTH 7
+
+
+/* NIC status register */
+#define FCN_NIC_STAT_REG 0x0200
+#define FCN_ONCHIP_SRAM_LBN 16
+#define FCN_ONCHIP_SRAM_WIDTH 1
+#define FCN_SF_PRST_LBN 9
+#define FCN_SF_PRST_WIDTH 1
+#define FCN_EE_PRST_LBN 8
+#define FCN_EE_PRST_WIDTH 1
+#define FCN_EE_STRAP_LBN 7
+#define FCN_EE_STRAP_WIDTH 1
+#define FCN_PCI_PCIX_MODE_LBN 4
+#define FCN_PCI_PCIX_MODE_WIDTH 3
+#define FCN_PCI_PCIX_MODE_PCI33_DECODE 0
+#define FCN_PCI_PCIX_MODE_PCI66_DECODE 1
+#define FCN_PCI_PCIX_MODE_PCIX66_DECODE 5
+#define FCN_PCI_PCIX_MODE_PCIX100_DECODE 6
+#define FCN_PCI_PCIX_MODE_PCIX133_DECODE 7
+#define FCN_STRAP_ISCSI_EN_LBN 3
+#define FCN_STRAP_ISCSI_EN_WIDTH 1
+#define FCN_STRAP_PINS_LBN 0
+#define FCN_STRAP_PINS_WIDTH 3
+#define FCN_STRAP_10G_LBN 2
+#define FCN_STRAP_10G_WIDTH 1
+#define FCN_STRAP_DUAL_PORT_LBN 1
+#define FCN_STRAP_DUAL_PORT_WIDTH 1
+#define FCN_STRAP_PCIE_LBN 0
+#define FCN_STRAP_PCIE_WIDTH 1
+
+/* Falcon revisions */
+#define FALCON_REV_A0 0
+#define FALCON_REV_A1 1
+#define FALCON_REV_B0 2
+
+/* GPIO control register */
+#define FCN_GPIO_CTL_REG_KER 0x0210
+#define FCN_GPIO_CTL_REG_KER 0x0210
+
+#define FCN_GPIO3_OEN_LBN 27
+#define FCN_GPIO3_OEN_WIDTH 1
+#define FCN_GPIO2_OEN_LBN 26
+#define FCN_GPIO2_OEN_WIDTH 1
+#define FCN_GPIO1_OEN_LBN 25
+#define FCN_GPIO1_OEN_WIDTH 1
+#define FCN_GPIO0_OEN_LBN 24
+#define FCN_GPIO0_OEN_WIDTH 1
+
+#define FCN_GPIO3_OUT_LBN 19
+#define FCN_GPIO3_OUT_WIDTH 1
+#define FCN_GPIO2_OUT_LBN 18
+#define FCN_GPIO2_OUT_WIDTH 1
+#define FCN_GPIO1_OUT_LBN 17
+#define FCN_GPIO1_OUT_WIDTH 1
+#define FCN_GPIO0_OUT_LBN 16
+#define FCN_GPIO0_OUT_WIDTH 1
+
+#define FCN_GPIO3_IN_LBN 11
+#define FCN_GPIO3_IN_WIDTH 1
+#define FCN_GPIO2_IN_LBN 10
+#define FCN_GPIO2_IN_WIDTH 1
+#define FCN_GPIO1_IN_LBN 9
+#define FCN_GPIO1_IN_WIDTH 1
+#define FCN_GPIO0_IN_LBN 8
+#define FCN_GPIO0_IN_WIDTH 1
+
+#define FCN_FLASH_PRESENT_LBN 7
+#define FCN_FLASH_PRESENT_WIDTH 1
+#define FCN_EEPROM_PRESENT_LBN 6
+#define FCN_EEPROM_PRESENT_WIDTH 1
+#define FCN_BOOTED_USING_NVDEVICE_LBN 3
+#define FCN_BOOTED_USING_NVDEVICE_WIDTH 1
+
+/* Defines for extra non-volatile storage */
+#define FCN_NV_MAGIC_NUMBER 0xFA1C
+
+/* Global control register */
+#define FCN_GLB_CTL_REG_KER 0x0220
+#define FCN_EXT_PHY_RST_CTL_LBN 63
+#define FCN_EXT_PHY_RST_CTL_WIDTH 1
+#define FCN_PCIE_SD_RST_CTL_LBN 61
+#define FCN_PCIE_SD_RST_CTL_WIDTH 1
+#define FCN_PCIE_STCK_RST_CTL_LBN 59
+#define FCN_PCIE_STCK_RST_CTL_WIDTH 1
+#define FCN_PCIE_NSTCK_RST_CTL_LBN 58
+#define FCN_PCIE_NSTCK_RST_CTL_WIDTH 1
+#define FCN_PCIE_CORE_RST_CTL_LBN 57
+#define FCN_PCIE_CORE_RST_CTL_WIDTH 1
+#define FCN_EE_RST_CTL_LBN 49
+#define FCN_EE_RST_CTL_WIDTH 1
+#define FCN_RST_EXT_PHY_LBN 31
+#define FCN_RST_EXT_PHY_WIDTH 1
+#define FCN_EXT_PHY_RST_DUR_LBN 1
+#define FCN_EXT_PHY_RST_DUR_WIDTH 3
+#define FCN_SWRST_LBN 0
+#define FCN_SWRST_WIDTH 1
+#define INCLUDE_IN_RESET 0
+#define EXCLUDE_FROM_RESET 1
+
+/* FPGA build version */
+#define FCN_ALTERA_BUILD_REG_KER 0x0300
+#define FCN_VER_MAJOR_LBN 24
+#define FCN_VER_MAJOR_WIDTH 8
+#define FCN_VER_MINOR_LBN 16
+#define FCN_VER_MINOR_WIDTH 8
+#define FCN_VER_BUILD_LBN 0
+#define FCN_VER_BUILD_WIDTH 16
+#define FCN_VER_ALL_LBN 0
+#define FCN_VER_ALL_WIDTH 32
+
+/* Spare EEPROM bits register (flash 0x390) */
+#define FCN_SPARE_REG_KER 0x310
+#define FCN_MEM_PERR_EN_TX_DATA_LBN 72
+#define FCN_MEM_PERR_EN_TX_DATA_WIDTH 2
+
+/* Timer table for kernel access */
+#define FCN_TIMER_CMD_REG_KER 0x420
+#define FCN_TIMER_MODE_LBN 12
+#define FCN_TIMER_MODE_WIDTH 2
+#define FCN_TIMER_MODE_DIS 0
+#define FCN_TIMER_MODE_INT_HLDOFF 1
+#define FCN_TIMER_VAL_LBN 0
+#define FCN_TIMER_VAL_WIDTH 12
+
+/* Receive configuration register */
+#define FCN_RX_CFG_REG_KER 0x800
+#define FCN_RX_XOFF_EN_LBN 0
+#define FCN_RX_XOFF_EN_WIDTH 1
+
+/* SRAM receive descriptor cache configuration register */
+#define FCN_SRM_RX_DC_CFG_REG_KER 0x610
+#define FCN_SRM_RX_DC_BASE_ADR_LBN 0
+#define FCN_SRM_RX_DC_BASE_ADR_WIDTH 21
+
+/* SRAM transmit descriptor cache configuration register */
+#define FCN_SRM_TX_DC_CFG_REG_KER 0x620
+#define FCN_SRM_TX_DC_BASE_ADR_LBN 0
+#define FCN_SRM_TX_DC_BASE_ADR_WIDTH 21
+
+/* SRAM configuration register */
+#define FCN_SRM_CFG_REG_KER 0x630
+#define FCN_SRAM_OOB_ADR_INTEN_LBN 5
+#define FCN_SRAM_OOB_ADR_INTEN_WIDTH 1
+#define FCN_SRAM_OOB_BUF_INTEN_LBN 4
+#define FCN_SRAM_OOB_BUF_INTEN_WIDTH 1
+#define FCN_SRAM_OOB_BT_INIT_EN_LBN 3
+#define FCN_SRAM_OOB_BT_INIT_EN_WIDTH 1
+#define FCN_SRM_NUM_BANK_LBN 2
+#define FCN_SRM_NUM_BANK_WIDTH 1
+#define FCN_SRM_BANK_SIZE_LBN 0
+#define FCN_SRM_BANK_SIZE_WIDTH 2
+#define FCN_SRM_NUM_BANKS_AND_BANK_SIZE_LBN 0
+#define FCN_SRM_NUM_BANKS_AND_BANK_SIZE_WIDTH 3
+
+#define FCN_RX_CFG_REG_KER 0x800
+#define FCN_RX_INGR_EN_B0_LBN 47
+#define FCN_RX_INGR_EN_B0_WIDTH 1
+#define FCN_RX_USR_BUF_SIZE_B0_LBN 19
+#define FCN_RX_USR_BUF_SIZE_B0_WIDTH 9
+#define FCN_RX_XON_MAC_TH_B0_LBN 10
+#define FCN_RX_XON_MAC_TH_B0_WIDTH 9
+#define FCN_RX_XOFF_MAC_TH_B0_LBN 1
+#define FCN_RX_XOFF_MAC_TH_B0_WIDTH 9
+#define FCN_RX_XOFF_MAC_EN_B0_LBN 0
+#define FCN_RX_XOFF_MAC_EN_B0_WIDTH 1
+#define FCN_RX_USR_BUF_SIZE_A1_LBN 11
+#define FCN_RX_USR_BUF_SIZE_A1_WIDTH 9
+#define FCN_RX_XON_MAC_TH_A1_LBN 6
+#define FCN_RX_XON_MAC_TH_A1_WIDTH 5
+#define FCN_RX_XOFF_MAC_TH_A1_LBN 1
+#define FCN_RX_XOFF_MAC_TH_A1_WIDTH 5
+#define FCN_RX_XOFF_MAC_EN_A1_LBN 0
+#define FCN_RX_XOFF_MAC_EN_A1_WIDTH 1
+
+#define FCN_RX_USR_BUF_SIZE_A1_LBN 11
+#define FCN_RX_USR_BUF_SIZE_A1_WIDTH 9
+#define FCN_RX_XOFF_MAC_EN_A1_LBN 0
+#define FCN_RX_XOFF_MAC_EN_A1_WIDTH 1
+
+/* Receive filter control register */
+#define FCN_RX_FILTER_CTL_REG_KER 0x810
+#define FCN_UDP_FULL_SRCH_LIMIT_LBN 32
+#define FCN_UDP_FULL_SRCH_LIMIT_WIDTH 8
+#define FCN_NUM_KER_LBN 24
+#define FCN_NUM_KER_WIDTH 2
+#define FCN_UDP_WILD_SRCH_LIMIT_LBN 16
+#define FCN_UDP_WILD_SRCH_LIMIT_WIDTH 8
+#define FCN_TCP_WILD_SRCH_LIMIT_LBN 8
+#define FCN_TCP_WILD_SRCH_LIMIT_WIDTH 8
+#define FCN_TCP_FULL_SRCH_LIMIT_LBN 0
+#define FCN_TCP_FULL_SRCH_LIMIT_WIDTH 8
+
+/* RX queue flush register */
+#define FCN_RX_FLUSH_DESCQ_REG_KER 0x0820
+#define FCN_RX_FLUSH_DESCQ_CMD_LBN 24
+#define FCN_RX_FLUSH_DESCQ_CMD_WIDTH 1
+#define FCN_RX_FLUSH_DESCQ_LBN 0
+#define FCN_RX_FLUSH_DESCQ_WIDTH 12
+
+/* Receive descriptor update register */
+#define FCN_RX_DESC_UPD_REG_KER 0x0830
+#define FCN_RX_DESC_WPTR_LBN 96
+#define FCN_RX_DESC_WPTR_WIDTH 12
+#define FCN_RX_DESC_UPD_REG_KER_DWORD ( FCN_RX_DESC_UPD_REG_KER + 12 )
+#define FCN_RX_DESC_WPTR_DWORD_LBN 0
+#define FCN_RX_DESC_WPTR_DWORD_WIDTH 12
+
+/* Receive descriptor cache configuration register */
+#define FCN_RX_DC_CFG_REG_KER 0x840
+#define FCN_RX_DC_SIZE_LBN 0
+#define FCN_RX_DC_SIZE_WIDTH 2
+
+#define FCN_RX_SELF_RST_REG_KER 0x890
+#define FCN_RX_ISCSI_DIS_LBN 17
+#define FCN_RX_ISCSI_DIS_WIDTH 1
+#define FCN_RX_NODESC_WAIT_DIS_LBN 9
+#define FCN_RX_NODESC_WAIT_DIS_WIDTH 1
+#define FCN_RX_RECOVERY_EN_LBN 8
+#define FCN_RX_RECOVERY_EN_WIDTH 1
+
+/* TX queue flush register */
+#define FCN_TX_FLUSH_DESCQ_REG_KER 0x0a00
+#define FCN_TX_FLUSH_DESCQ_CMD_LBN 12
+#define FCN_TX_FLUSH_DESCQ_CMD_WIDTH 1
+#define FCN_TX_FLUSH_DESCQ_LBN 0
+#define FCN_TX_FLUSH_DESCQ_WIDTH 12
+
+/* Transmit configuration register 2 */
+#define FCN_TX_CFG2_REG_KER 0xa80
+#define FCN_TX_DIS_NON_IP_EV_LBN 17
+#define FCN_TX_DIS_NON_IP_EV_WIDTH 1
+
+/* Transmit descriptor update register */
+#define FCN_TX_DESC_UPD_REG_KER 0x0a10
+#define FCN_TX_DESC_WPTR_LBN 96
+#define FCN_TX_DESC_WPTR_WIDTH 12
+#define FCN_TX_DESC_UPD_REG_KER_DWORD ( FCN_TX_DESC_UPD_REG_KER + 12 )
+#define FCN_TX_DESC_WPTR_DWORD_LBN 0
+#define FCN_TX_DESC_WPTR_DWORD_WIDTH 12
+
+/* Transmit descriptor cache configuration register */
+#define FCN_TX_DC_CFG_REG_KER 0xa20
+#define FCN_TX_DC_SIZE_LBN 0
+#define FCN_TX_DC_SIZE_WIDTH 2
+
+/* PHY management transmit data register */
+#define FCN_MD_TXD_REG_KER 0xc00
+#define FCN_MD_TXD_LBN 0
+#define FCN_MD_TXD_WIDTH 16
+
+/* PHY management receive data register */
+#define FCN_MD_RXD_REG_KER 0xc10
+#define FCN_MD_RXD_LBN 0
+#define FCN_MD_RXD_WIDTH 16
+
+/* PHY management configuration & status register */
+#define FCN_MD_CS_REG_KER 0xc20
+#define FCN_MD_GC_LBN 4
+#define FCN_MD_GC_WIDTH 1
+#define FCN_MD_RIC_LBN 2
+#define FCN_MD_RIC_WIDTH 1
+#define FCN_MD_RDC_LBN 1
+#define FCN_MD_RDC_WIDTH 1
+#define FCN_MD_WRC_LBN 0
+#define FCN_MD_WRC_WIDTH 1
+
+/* PHY management PHY address register */
+#define FCN_MD_PHY_ADR_REG_KER 0xc30
+#define FCN_MD_PHY_ADR_LBN 0
+#define FCN_MD_PHY_ADR_WIDTH 16
+
+/* PHY management ID register */
+#define FCN_MD_ID_REG_KER 0xc40
+#define FCN_MD_PRT_ADR_LBN 11
+#define FCN_MD_PRT_ADR_WIDTH 5
+#define FCN_MD_DEV_ADR_LBN 6
+#define FCN_MD_DEV_ADR_WIDTH 5
+
+/* PHY management status & mask register */
+#define FCN_MD_STAT_REG_KER 0xc50
+#define FCN_MD_PINT_LBN 4
+#define FCN_MD_PINT_WIDTH 1
+#define FCN_MD_DONE_LBN 3
+#define FCN_MD_DONE_WIDTH 1
+#define FCN_MD_BSERR_LBN 2
+#define FCN_MD_BSERR_WIDTH 1
+#define FCN_MD_LNFL_LBN 1
+#define FCN_MD_LNFL_WIDTH 1
+#define FCN_MD_BSY_LBN 0
+#define FCN_MD_BSY_WIDTH 1
+
+/* Port 0 and 1 MAC control registers */
+#define FCN_MAC0_CTRL_REG_KER 0xc80
+#define FCN_MAC1_CTRL_REG_KER 0xc90
+#define FCN_MAC_XOFF_VAL_LBN 16
+#define FCN_MAC_XOFF_VAL_WIDTH 16
+#define FCN_MAC_BCAD_ACPT_LBN 4
+#define FCN_MAC_BCAD_ACPT_WIDTH 1
+#define FCN_MAC_UC_PROM_LBN 3
+#define FCN_MAC_UC_PROM_WIDTH 1
+#define FCN_MAC_LINK_STATUS_LBN 2
+#define FCN_MAC_LINK_STATUS_WIDTH 1
+#define FCN_MAC_SPEED_LBN 0
+#define FCN_MAC_SPEED_WIDTH 2
+
+/* 10Gig Xaui XGXS Default Values */
+#define XX_TXDRV_DEQ_DEFAULT 0xe /* deq=.6 */
+#define XX_TXDRV_DTX_DEFAULT 0x5 /* 1.25 */
+#define XX_SD_CTL_DRV_DEFAULT 0 /* 20mA */
+
+/* GMAC registers */
+#define FALCON_GMAC_REGBANK 0xe00
+#define FALCON_GMAC_REGBANK_SIZE 0x200
+#define FALCON_GMAC_REG_SIZE 0x10
+
+/* XGMAC registers */
+#define FALCON_XMAC_REGBANK 0x1200
+#define FALCON_XMAC_REGBANK_SIZE 0x200
+#define FALCON_XMAC_REG_SIZE 0x10
+
+/* XGMAC address register low */
+#define FCN_XM_ADR_LO_REG_MAC 0x00
+#define FCN_XM_ADR_3_LBN 24
+#define FCN_XM_ADR_3_WIDTH 8
+#define FCN_XM_ADR_2_LBN 16
+#define FCN_XM_ADR_2_WIDTH 8
+#define FCN_XM_ADR_1_LBN 8
+#define FCN_XM_ADR_1_WIDTH 8
+#define FCN_XM_ADR_0_LBN 0
+#define FCN_XM_ADR_0_WIDTH 8
+
+/* XGMAC address register high */
+#define FCN_XM_ADR_HI_REG_MAC 0x01
+#define FCN_XM_ADR_5_LBN 8
+#define FCN_XM_ADR_5_WIDTH 8
+#define FCN_XM_ADR_4_LBN 0
+#define FCN_XM_ADR_4_WIDTH 8
+
+/* XGMAC global configuration - port 0*/
+#define FCN_XM_GLB_CFG_REG_MAC 0x02
+#define FCN_XM_RX_STAT_EN_LBN 11
+#define FCN_XM_RX_STAT_EN_WIDTH 1
+#define FCN_XM_TX_STAT_EN_LBN 10
+#define FCN_XM_TX_STAT_EN_WIDTH 1
+#define FCN_XM_RX_JUMBO_MODE_LBN 6
+#define FCN_XM_RX_JUMBO_MODE_WIDTH 1
+#define FCN_XM_CORE_RST_LBN 0
+#define FCN_XM_CORE_RST_WIDTH 1
+
+/* XGMAC transmit configuration - port 0 */
+#define FCN_XM_TX_CFG_REG_MAC 0x03
+#define FCN_XM_IPG_LBN 16
+#define FCN_XM_IPG_WIDTH 4
+#define FCN_XM_FCNTL_LBN 10
+#define FCN_XM_FCNTL_WIDTH 1
+#define FCN_XM_TXCRC_LBN 8
+#define FCN_XM_TXCRC_WIDTH 1
+#define FCN_XM_AUTO_PAD_LBN 5
+#define FCN_XM_AUTO_PAD_WIDTH 1
+#define FCN_XM_TX_PRMBL_LBN 2
+#define FCN_XM_TX_PRMBL_WIDTH 1
+#define FCN_XM_TXEN_LBN 1
+#define FCN_XM_TXEN_WIDTH 1
+
+/* XGMAC receive configuration - port 0 */
+#define FCN_XM_RX_CFG_REG_MAC 0x04
+#define FCN_XM_PASS_CRC_ERR_LBN 25
+#define FCN_XM_PASS_CRC_ERR_WIDTH 1
+#define FCN_XM_AUTO_DEPAD_LBN 8
+#define FCN_XM_AUTO_DEPAD_WIDTH 1
+#define FCN_XM_RXEN_LBN 1
+#define FCN_XM_RXEN_WIDTH 1
+
+/* XGMAC management interrupt mask register */
+#define FCN_XM_MGT_INT_MSK_REG_MAC_B0 0x5
+#define FCN_XM_MSK_PRMBLE_ERR_LBN 2
+#define FCN_XM_MSK_PRMBLE_ERR_WIDTH 1
+#define FCN_XM_MSK_RMTFLT_LBN 1
+#define FCN_XM_MSK_RMTFLT_WIDTH 1
+#define FCN_XM_MSK_LCLFLT_LBN 0
+#define FCN_XM_MSK_LCLFLT_WIDTH 1
+
+/* XGMAC flow control register */
+#define FCN_XM_FC_REG_MAC 0x7
+#define FCN_XM_PAUSE_TIME_LBN 16
+#define FCN_XM_PAUSE_TIME_WIDTH 16
+#define FCN_XM_DIS_FCNTL_LBN 0
+#define FCN_XM_DIS_FCNTL_WIDTH 1
+
+/* XGMAC transmit parameter register */
+#define FCN_XM_TX_PARAM_REG_MAC 0x0d
+#define FCN_XM_TX_JUMBO_MODE_LBN 31
+#define FCN_XM_TX_JUMBO_MODE_WIDTH 1
+#define FCN_XM_MAX_TX_FRM_SIZE_LBN 16
+#define FCN_XM_MAX_TX_FRM_SIZE_WIDTH 14
+#define FCN_XM_ACPT_ALL_MCAST_LBN 11
+#define FCN_XM_ACPT_ALL_MCAST_WIDTH 1
+
+/* XGMAC receive parameter register */
+#define FCN_XM_RX_PARAM_REG_MAC 0x0e
+#define FCN_XM_MAX_RX_FRM_SIZE_LBN 0
+#define FCN_XM_MAX_RX_FRM_SIZE_WIDTH 14
+
+/* XGMAC management interrupt status register */
+#define FCN_XM_MGT_INT_REG_MAC_B0 0x0f
+#define FCN_XM_PRMBLE_ERR 2
+#define FCN_XM_PRMBLE_WIDTH 1
+#define FCN_XM_RMTFLT_LBN 1
+#define FCN_XM_RMTFLT_WIDTH 1
+#define FCN_XM_LCLFLT_LBN 0
+#define FCN_XM_LCLFLT_WIDTH 1
+
+/* XAUI XGXS core status register */
+#define FCN_XX_ALIGN_DONE_LBN 20
+#define FCN_XX_ALIGN_DONE_WIDTH 1
+#define FCN_XX_CORE_STAT_REG_MAC 0x16
+#define FCN_XX_SYNC_STAT_LBN 16
+#define FCN_XX_SYNC_STAT_WIDTH 4
+#define FCN_XX_SYNC_STAT_DECODE_SYNCED 0xf
+#define FCN_XX_COMMA_DET_LBN 12
+#define FCN_XX_COMMA_DET_WIDTH 4
+#define FCN_XX_COMMA_DET_RESET 0xf
+#define FCN_XX_CHARERR_LBN 4
+#define FCN_XX_CHARERR_WIDTH 4
+#define FCN_XX_CHARERR_RESET 0xf
+#define FCN_XX_DISPERR_LBN 0
+#define FCN_XX_DISPERR_WIDTH 4
+#define FCN_XX_DISPERR_RESET 0xf
+
+/* XGXS/XAUI powerdown/reset register */
+#define FCN_XX_PWR_RST_REG_MAC 0x10
+#define FCN_XX_PWRDND_EN_LBN 15
+#define FCN_XX_PWRDND_EN_WIDTH 1
+#define FCN_XX_PWRDNC_EN_LBN 14
+#define FCN_XX_PWRDNC_EN_WIDTH 1
+#define FCN_XX_PWRDNB_EN_LBN 13
+#define FCN_XX_PWRDNB_EN_WIDTH 1
+#define FCN_XX_PWRDNA_EN_LBN 12
+#define FCN_XX_PWRDNA_EN_WIDTH 1
+#define FCN_XX_RSTPLLCD_EN_LBN 9
+#define FCN_XX_RSTPLLCD_EN_WIDTH 1
+#define FCN_XX_RSTPLLAB_EN_LBN 8
+#define FCN_XX_RSTPLLAB_EN_WIDTH 1
+#define FCN_XX_RESETD_EN_LBN 7
+#define FCN_XX_RESETD_EN_WIDTH 1
+#define FCN_XX_RESETC_EN_LBN 6
+#define FCN_XX_RESETC_EN_WIDTH 1
+#define FCN_XX_RESETB_EN_LBN 5
+#define FCN_XX_RESETB_EN_WIDTH 1
+#define FCN_XX_RESETA_EN_LBN 4
+#define FCN_XX_RESETA_EN_WIDTH 1
+#define FCN_XX_RSTXGXSRX_EN_LBN 2
+#define FCN_XX_RSTXGXSRX_EN_WIDTH 1
+#define FCN_XX_RSTXGXSTX_EN_LBN 1
+#define FCN_XX_RSTXGXSTX_EN_WIDTH 1
+#define FCN_XX_RST_XX_EN_LBN 0
+#define FCN_XX_RST_XX_EN_WIDTH 1
+
+
+/* XGXS/XAUI powerdown/reset control register */
+#define FCN_XX_SD_CTL_REG_MAC 0x11
+#define FCN_XX_TERMADJ1_LBN 17
+#define FCN_XX_TERMADJ1_WIDTH 1
+#define FCN_XX_TERMADJ0_LBN 16
+#define FCN_XX_TERMADJ0_WIDTH 1
+#define FCN_XX_HIDRVD_LBN 15
+#define FCN_XX_HIDRVD_WIDTH 1
+#define FCN_XX_LODRVD_LBN 14
+#define FCN_XX_LODRVD_WIDTH 1
+#define FCN_XX_HIDRVC_LBN 13
+#define FCN_XX_HIDRVC_WIDTH 1
+#define FCN_XX_LODRVC_LBN 12
+#define FCN_XX_LODRVC_WIDTH 1
+#define FCN_XX_HIDRVB_LBN 11
+#define FCN_XX_HIDRVB_WIDTH 1
+#define FCN_XX_LODRVB_LBN 10
+#define FCN_XX_LODRVB_WIDTH 1
+#define FCN_XX_HIDRVA_LBN 9
+#define FCN_XX_HIDRVA_WIDTH 1
+#define FCN_XX_LODRVA_LBN 8
+#define FCN_XX_LODRVA_WIDTH 1
+#define FCN_XX_LPBKD_LBN 3
+#define FCN_XX_LPBKD_WIDTH 1
+#define FCN_XX_LPBKC_LBN 2
+#define FCN_XX_LPBKC_WIDTH 1
+#define FCN_XX_LPBKB_LBN 1
+#define FCN_XX_LPBKB_WIDTH 1
+#define FCN_XX_LPBKA_LBN 0
+#define FCN_XX_LPBKA_WIDTH 1
+
+#define FCN_XX_TXDRV_CTL_REG_MAC 0x12
+#define FCN_XX_DEQD_LBN 28
+#define FCN_XX_DEQD_WIDTH 4
+#define FCN_XX_DEQC_LBN 24
+#define FCN_XX_DEQC_WIDTH 4
+#define FCN_XX_DEQB_LBN 20
+#define FCN_XX_DEQB_WIDTH 4
+#define FCN_XX_DEQA_LBN 16
+#define FCN_XX_DEQA_WIDTH 4
+#define FCN_XX_DTXD_LBN 12
+#define FCN_XX_DTXD_WIDTH 4
+#define FCN_XX_DTXC_LBN 8
+#define FCN_XX_DTXC_WIDTH 4
+#define FCN_XX_DTXB_LBN 4
+#define FCN_XX_DTXB_WIDTH 4
+#define FCN_XX_DTXA_LBN 0
+#define FCN_XX_DTXA_WIDTH 4
+
+/* Receive filter table */
+#define FCN_RX_FILTER_TBL0 0xF00000
+
+/* Receive descriptor pointer table */
+#define FCN_RX_DESC_PTR_TBL_KER_A1 0x11800
+#define FCN_RX_DESC_PTR_TBL_KER_B0 0xF40000
+#define FCN_RX_ISCSI_DDIG_EN_LBN 88
+#define FCN_RX_ISCSI_DDIG_EN_WIDTH 1
+#define FCN_RX_ISCSI_HDIG_EN_LBN 87
+#define FCN_RX_ISCSI_HDIG_EN_WIDTH 1
+#define FCN_RX_DESCQ_BUF_BASE_ID_LBN 36
+#define FCN_RX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define FCN_RX_DESCQ_EVQ_ID_LBN 24
+#define FCN_RX_DESCQ_EVQ_ID_WIDTH 12
+#define FCN_RX_DESCQ_OWNER_ID_LBN 10
+#define FCN_RX_DESCQ_OWNER_ID_WIDTH 14
+#define FCN_RX_DESCQ_SIZE_LBN 3
+#define FCN_RX_DESCQ_SIZE_WIDTH 2
+#define FCN_RX_DESCQ_SIZE_4K 3
+#define FCN_RX_DESCQ_SIZE_2K 2
+#define FCN_RX_DESCQ_SIZE_1K 1
+#define FCN_RX_DESCQ_SIZE_512 0
+#define FCN_RX_DESCQ_TYPE_LBN 2
+#define FCN_RX_DESCQ_TYPE_WIDTH 1
+#define FCN_RX_DESCQ_JUMBO_LBN 1
+#define FCN_RX_DESCQ_JUMBO_WIDTH 1
+#define FCN_RX_DESCQ_EN_LBN 0
+#define FCN_RX_DESCQ_EN_WIDTH 1
+
+/* Transmit descriptor pointer table */
+#define FCN_TX_DESC_PTR_TBL_KER_A1 0x11900
+#define FCN_TX_DESC_PTR_TBL_KER_B0 0xF50000
+#define FCN_TX_NON_IP_DROP_DIS_B0_LBN 91
+#define FCN_TX_NON_IP_DROP_DIS_B0_WIDTH 1
+#define FCN_TX_DESCQ_EN_LBN 88
+#define FCN_TX_DESCQ_EN_WIDTH 1
+#define FCN_TX_ISCSI_DDIG_EN_LBN 87
+#define FCN_TX_ISCSI_DDIG_EN_WIDTH 1
+#define FCN_TX_ISCSI_HDIG_EN_LBN 86
+#define FCN_TX_ISCSI_HDIG_EN_WIDTH 1
+#define FCN_TX_DESCQ_BUF_BASE_ID_LBN 36
+#define FCN_TX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define FCN_TX_DESCQ_EVQ_ID_LBN 24
+#define FCN_TX_DESCQ_EVQ_ID_WIDTH 12
+#define FCN_TX_DESCQ_OWNER_ID_LBN 10
+#define FCN_TX_DESCQ_OWNER_ID_WIDTH 14
+#define FCN_TX_DESCQ_SIZE_LBN 3
+#define FCN_TX_DESCQ_SIZE_WIDTH 2
+#define FCN_TX_DESCQ_SIZE_4K 3
+#define FCN_TX_DESCQ_SIZE_2K 2
+#define FCN_TX_DESCQ_SIZE_1K 1
+#define FCN_TX_DESCQ_SIZE_512 0
+#define FCN_TX_DESCQ_TYPE_LBN 1
+#define FCN_TX_DESCQ_TYPE_WIDTH 2
+#define FCN_TX_DESCQ_FLUSH_LBN 0
+#define FCN_TX_DESCQ_FLUSH_WIDTH 1
+
+/* Event queue pointer */
+#define FCN_EVQ_PTR_TBL_KER_A1 0x11a00
+#define FCN_EVQ_PTR_TBL_KER_B0 0xf60000
+#define FCN_EVQ_EN_LBN 23
+#define FCN_EVQ_EN_WIDTH 1
+#define FCN_EVQ_SIZE_LBN 20
+#define FCN_EVQ_SIZE_WIDTH 3
+#define FCN_EVQ_SIZE_32K 6
+#define FCN_EVQ_SIZE_16K 5
+#define FCN_EVQ_SIZE_8K 4
+#define FCN_EVQ_SIZE_4K 3
+#define FCN_EVQ_SIZE_2K 2
+#define FCN_EVQ_SIZE_1K 1
+#define FCN_EVQ_SIZE_512 0
+#define FCN_EVQ_BUF_BASE_ID_LBN 0
+#define FCN_EVQ_BUF_BASE_ID_WIDTH 20
+
+/* RSS indirection table */
+#define FCN_RX_RSS_INDIR_TBL_B0 0xFB0000
+
+/* Event queue read pointer */
+#define FCN_EVQ_RPTR_REG_KER_A1 0x11b00
+#define FCN_EVQ_RPTR_REG_KER_B0 0xfa0000
+#define FCN_EVQ_RPTR_LBN 0
+#define FCN_EVQ_RPTR_WIDTH 14
+#define FCN_EVQ_RPTR_REG_KER_DWORD_A1 ( FCN_EVQ_RPTR_REG_KER_A1 + 0 )
+#define FCN_EVQ_RPTR_REG_KER_DWORD_B0 ( FCN_EVQ_RPTR_REG_KER_B0 + 0 )
+#define FCN_EVQ_RPTR_DWORD_LBN 0
+#define FCN_EVQ_RPTR_DWORD_WIDTH 14
+
+/* Special buffer descriptors */
+#define FCN_BUF_FULL_TBL_KER_A1 0x18000
+#define FCN_BUF_FULL_TBL_KER_B0 0x800000
+#define FCN_IP_DAT_BUF_SIZE_LBN 50
+#define FCN_IP_DAT_BUF_SIZE_WIDTH 1
+#define FCN_IP_DAT_BUF_SIZE_8K 1
+#define FCN_IP_DAT_BUF_SIZE_4K 0
+#define FCN_BUF_ADR_FBUF_LBN 14
+#define FCN_BUF_ADR_FBUF_WIDTH 34
+#define FCN_BUF_OWNER_ID_FBUF_LBN 0
+#define FCN_BUF_OWNER_ID_FBUF_WIDTH 14
+
+/** Offset of a GMAC register within Falcon */
+#define FALCON_GMAC_REG( efab, mac_reg ) \
+ ( FALCON_GMAC_REGBANK + \
+ ( (mac_reg) * FALCON_GMAC_REG_SIZE ) )
+
+/** Offset of an XMAC register within Falcon */
+#define FALCON_XMAC_REG( efab_port, mac_reg ) \
+ ( FALCON_XMAC_REGBANK + \
+ ( (mac_reg) * FALCON_XMAC_REG_SIZE ) )
+
+#define FCN_MAC_DATA_LBN 0
+#define FCN_MAC_DATA_WIDTH 32
+
+/* Transmit descriptor */
+#define FCN_TX_KER_PORT_LBN 63
+#define FCN_TX_KER_PORT_WIDTH 1
+#define FCN_TX_KER_BYTE_CNT_LBN 48
+#define FCN_TX_KER_BYTE_CNT_WIDTH 14
+#define FCN_TX_KER_BUF_ADR_LBN 0
+#define FCN_TX_KER_BUF_ADR_WIDTH EFAB_DMA_TYPE_WIDTH ( 46 )
+
+
+/* Receive descriptor */
+#define FCN_RX_KER_BUF_SIZE_LBN 48
+#define FCN_RX_KER_BUF_SIZE_WIDTH 14
+#define FCN_RX_KER_BUF_ADR_LBN 0
+#define FCN_RX_KER_BUF_ADR_WIDTH EFAB_DMA_TYPE_WIDTH ( 46 )
+
+/* Event queue entries */
+#define FCN_EV_CODE_LBN 60
+#define FCN_EV_CODE_WIDTH 4
+#define FCN_RX_IP_EV_DECODE 0
+#define FCN_TX_IP_EV_DECODE 2
+#define FCN_DRIVER_EV_DECODE 5
+
+/* Receive events */
+#define FCN_RX_EV_PKT_OK_LBN 56
+#define FCN_RX_EV_PKT_OK_WIDTH 1
+#define FCN_RX_PORT_LBN 30
+#define FCN_RX_PORT_WIDTH 1
+#define FCN_RX_EV_BYTE_CNT_LBN 16
+#define FCN_RX_EV_BYTE_CNT_WIDTH 14
+#define FCN_RX_EV_DESC_PTR_LBN 0
+#define FCN_RX_EV_DESC_PTR_WIDTH 12
+
+/* Transmit events */
+#define FCN_TX_EV_DESC_PTR_LBN 0
+#define FCN_TX_EV_DESC_PTR_WIDTH 12
+
+/*******************************************************************************
+ *
+ *
+ * Low-level hardware access
+ *
+ *
+ *******************************************************************************/
+
+#define FCN_REVISION_REG(efab, reg) \
+ ( ( efab->pci_revision == FALCON_REV_B0 ) ? reg ## _B0 : reg ## _A1 )
+
+#define EFAB_SET_OWORD_FIELD_VER(efab, reg, field, val) \
+ if ( efab->pci_revision == FALCON_REV_B0 ) \
+ EFAB_SET_OWORD_FIELD ( reg, field ## _B0, val ); \
+ else \
+ EFAB_SET_OWORD_FIELD ( reg, field ## _A1, val );
+
+#if FALCON_USE_IO_BAR
+
+/* Write dword via the I/O BAR */
+static inline void _falcon_writel ( struct efab_nic *efab, uint32_t value,
+ unsigned int reg ) {
+ outl ( reg, efab->iobase + FCN_IOM_IND_ADR_REG );
+ outl ( value, efab->iobase + FCN_IOM_IND_DAT_REG );
+}
+
+/* Read dword via the I/O BAR */
+static inline uint32_t _falcon_readl ( struct efab_nic *efab,
+ unsigned int reg ) {
+ outl ( reg, efab->iobase + FCN_IOM_IND_ADR_REG );
+ return inl ( efab->iobase + FCN_IOM_IND_DAT_REG );
+}
+
+#else /* FALCON_USE_IO_BAR */
+
+#define _falcon_writel( efab, value, reg ) \
+ writel ( (value), (efab)->membase + (reg) )
+#define _falcon_readl( efab, reg ) readl ( (efab)->membase + (reg) )
+
+#endif /* FALCON_USE_IO_BAR */
+
+/**
+ * Write to a Falcon register
+ *
+ */
+static inline void
+falcon_write ( struct efab_nic *efab, efab_oword_t *value, unsigned int reg )
+{
+
+ EFAB_REGDUMP ( "Writing register %x with " EFAB_OWORD_FMT "\n",
+ reg, EFAB_OWORD_VAL ( *value ) );
+
+ _falcon_writel ( efab, value->u32[0], reg + 0 );
+ _falcon_writel ( efab, value->u32[1], reg + 4 );
+ _falcon_writel ( efab, value->u32[2], reg + 8 );
+ wmb();
+ _falcon_writel ( efab, value->u32[3], reg + 12 );
+ wmb();
+}
+
+/**
+ * Write to Falcon SRAM
+ *
+ */
+static inline void
+falcon_write_sram ( struct efab_nic *efab, efab_qword_t *value,
+ unsigned int index )
+{
+ unsigned int reg = ( FCN_REVISION_REG ( efab, FCN_BUF_FULL_TBL_KER ) +
+ ( index * sizeof ( *value ) ) );
+
+ EFAB_REGDUMP ( "Writing SRAM register %x with " EFAB_QWORD_FMT "\n",
+ reg, EFAB_QWORD_VAL ( *value ) );
+
+ _falcon_writel ( efab, value->u32[0], reg + 0 );
+ _falcon_writel ( efab, value->u32[1], reg + 4 );
+ wmb();
+}
+
+/**
+ * Write dword to Falcon register that allows partial writes
+ *
+ */
+static inline void
+falcon_writel ( struct efab_nic *efab, efab_dword_t *value, unsigned int reg )
+{
+ EFAB_REGDUMP ( "Writing partial register %x with " EFAB_DWORD_FMT "\n",
+ reg, EFAB_DWORD_VAL ( *value ) );
+ _falcon_writel ( efab, value->u32[0], reg );
+}
+
+/**
+ * Read from a Falcon register
+ *
+ */
+static inline void
+falcon_read ( struct efab_nic *efab, efab_oword_t *value, unsigned int reg )
+{
+ value->u32[0] = _falcon_readl ( efab, reg + 0 );
+ wmb();
+ value->u32[1] = _falcon_readl ( efab, reg + 4 );
+ value->u32[2] = _falcon_readl ( efab, reg + 8 );
+ value->u32[3] = _falcon_readl ( efab, reg + 12 );
+
+ EFAB_REGDUMP ( "Read from register %x, got " EFAB_OWORD_FMT "\n",
+ reg, EFAB_OWORD_VAL ( *value ) );
+}
+
+/**
+ * Read from Falcon SRAM
+ *
+ */
+static inline void
+falcon_read_sram ( struct efab_nic *efab, efab_qword_t *value,
+ unsigned int index )
+{
+ unsigned int reg = ( FCN_REVISION_REG ( efab, FCN_BUF_FULL_TBL_KER ) +
+ ( index * sizeof ( *value ) ) );
+
+ value->u32[0] = _falcon_readl ( efab, reg + 0 );
+ value->u32[1] = _falcon_readl ( efab, reg + 4 );
+ EFAB_REGDUMP ( "Read from SRAM register %x, got " EFAB_QWORD_FMT "\n",
+ reg, EFAB_QWORD_VAL ( *value ) );
+}
+
+/**
+ * Read dword from a portion of a Falcon register
+ *
+ */
+static inline void
+falcon_readl ( struct efab_nic *efab, efab_dword_t *value, unsigned int reg )
+{
+ value->u32[0] = _falcon_readl ( efab, reg );
+ EFAB_REGDUMP ( "Read from register %x, got " EFAB_DWORD_FMT "\n",
+ reg, EFAB_DWORD_VAL ( *value ) );
+}
+
+#define FCN_DUMP_REG( efab, _reg ) do { \
+ efab_oword_t reg; \
+ falcon_read ( efab, &reg, _reg ); \
+ EFAB_LOG ( #_reg " = " EFAB_OWORD_FMT "\n", \
+ EFAB_OWORD_VAL ( reg ) ); \
+ } while ( 0 );
+
+#define FCN_DUMP_MAC_REG( efab, _mac_reg ) do { \
+ efab_dword_t reg; \
+ efab->mac_op->mac_readl ( efab, &reg, _mac_reg ); \
+ EFAB_LOG ( #_mac_reg " = " EFAB_DWORD_FMT "\n", \
+ EFAB_DWORD_VAL ( reg ) ); \
+ } while ( 0 );
+
+/**
+ * See if an event is present
+ *
+ * @v event Falcon event structure
+ * @ret True An event is pending
+ * @ret False No event is pending
+ *
+ * We check both the high and low dword of the event for all ones. We
+ * wrote all ones when we cleared the event, and no valid event can
+ * have all ones in either its high or low dwords. This approach is
+ * robust against reordering.
+ *
+ * Note that using a single 64-bit comparison is incorrect; even
+ * though the CPU read will be atomic, the DMA write may not be.
+ */
+static inline int
+falcon_event_present ( falcon_event_t* event )
+{
+ return ( ! ( EFAB_DWORD_IS_ALL_ONES ( event->dword[0] ) |
+ EFAB_DWORD_IS_ALL_ONES ( event->dword[1] ) ) );
+}
+
+static void
+falcon_eventq_read_ack ( struct efab_nic *efab, struct efab_ev_queue *ev_queue )
+{
+ efab_dword_t reg;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_EVQ_RPTR_DWORD, ev_queue->read_ptr );
+ falcon_writel ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_EVQ_RPTR_REG_KER_DWORD ) );
+}
+
+#if 0
+/**
+ * Dump register contents (for debugging)
+ *
+ * Marked as static inline so that it will not be compiled in if not
+ * used.
+ */
+static inline void
+falcon_dump_regs ( struct efab_nic *efab )
+{
+ FCN_DUMP_REG ( efab, FCN_INT_EN_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_INT_ADR_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_GLB_CTL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_TIMER_CMD_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_SRM_RX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_SRM_TX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_RX_FILTER_CTL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_RX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_TX_DC_CFG_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_MAC0_CTRL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_MAC1_CTRL_REG_KER );
+ FCN_DUMP_REG ( efab, FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+ FCN_DUMP_REG ( efab, FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+ FCN_DUMP_REG ( efab, FCN_REVISION_REG ( efab, FCN_EVQ_PTR_TBL_KER ) );
+ FCN_DUMP_MAC_REG ( efab, GM_CFG1_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_CFG2_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_MAX_FLEN_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_MII_MGMT_CFG_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_ADR1_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GM_ADR2_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG0_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG1_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG2_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG3_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG4_REG_MAC );
+ FCN_DUMP_MAC_REG ( efab, GMF_CFG5_REG_MAC );
+}
+#endif
+
+static void
+falcon_interrupts ( struct efab_nic *efab, int enabled, int force )
+{
+ efab_oword_t int_en_reg_ker;
+
+ EFAB_POPULATE_OWORD_2 ( int_en_reg_ker,
+ FCN_KER_INT_KER, force,
+ FCN_DRV_INT_EN_KER, enabled );
+ falcon_write ( efab, &int_en_reg_ker, FCN_INT_EN_REG_KER );
+}
+
+/*******************************************************************************
+ *
+ *
+ * SPI access
+ *
+ *
+ *******************************************************************************/
+
+
+/** Maximum length for a single SPI transaction */
+#define FALCON_SPI_MAX_LEN 16
+
+static int
+falcon_spi_wait ( struct efab_nic *efab )
+{
+ efab_oword_t reg;
+ int count;
+
+ count = 0;
+ do {
+ udelay ( 100 );
+ falcon_read ( efab, &reg, FCN_EE_SPI_HCMD_REG );
+ if ( EFAB_OWORD_FIELD ( reg, FCN_EE_SPI_HCMD_CMD_EN ) == 0 )
+ return 0;
+ } while ( ++count < 1000 );
+
+ EFAB_ERR ( "Timed out waiting for SPI\n" );
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_spi_rw ( struct spi_bus* bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void* data_out, void *data_in, size_t len )
+{
+ struct efab_nic *efab = container_of ( bus, struct efab_nic, spi_bus );
+ int address_len, rc, device_id, read_cmd;
+ efab_oword_t reg;
+
+ /* falcon_init_spi_device() should have reduced the block size
+ * down so this constraint holds */
+ assert ( len <= FALCON_SPI_MAX_LEN );
+
+ /* Is this the FLASH or EEPROM device? */
+ if ( device == &efab->spi_flash )
+ device_id = FCN_EE_SPI_FLASH;
+ else if ( device == &efab->spi_eeprom )
+ device_id = FCN_EE_SPI_EEPROM;
+ else {
+ EFAB_ERR ( "Unknown device %p\n", device );
+ return -EINVAL;
+ }
+
+ EFAB_TRACE ( "Executing spi command %d on device %d at %d for %zd bytes\n",
+ command, device_id, address, len );
+
+ /* The bus must be idle */
+ rc = falcon_spi_wait ( efab );
+ if ( rc )
+ goto fail1;
+
+ /* Copy data out */
+ if ( data_out ) {
+ memcpy ( &reg, data_out, len );
+ falcon_write ( efab, &reg, FCN_EE_SPI_HDATA_REG );
+ }
+
+ /* Program address register */
+ if ( address >= 0 ) {
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_EE_SPI_HADR_ADR, address );
+ falcon_write ( efab, &reg, FCN_EE_SPI_HADR_REG );
+ }
+
+ /* Issue command */
+ address_len = ( address >= 0 ) ? device->address_len / 8 : 0;
+ read_cmd = ( data_in ? FCN_EE_SPI_READ : FCN_EE_SPI_WRITE );
+ EFAB_POPULATE_OWORD_7 ( reg,
+ FCN_EE_SPI_HCMD_CMD_EN, 1,
+ FCN_EE_SPI_HCMD_SF_SEL, device_id,
+ FCN_EE_SPI_HCMD_DABCNT, len,
+ FCN_EE_SPI_HCMD_READ, read_cmd,
+ FCN_EE_SPI_HCMD_DUBCNT, 0,
+ FCN_EE_SPI_HCMD_ADBCNT, address_len,
+ FCN_EE_SPI_HCMD_ENC, command );
+ falcon_write ( efab, &reg, FCN_EE_SPI_HCMD_REG );
+
+ /* Wait for the command to complete */
+ rc = falcon_spi_wait ( efab );
+ if ( rc )
+ goto fail2;
+
+ /* Copy data in */
+ if ( data_in ) {
+ falcon_read ( efab, &reg, FCN_EE_SPI_HDATA_REG );
+ memcpy ( data_in, &reg, len );
+ }
+
+ return 0;
+
+fail2:
+fail1:
+ EFAB_ERR ( "Failed SPI command %d to device %d address 0x%x len 0x%zx\n",
+ command, device_id, address, len );
+
+ return rc;
+}
+
+/** Portion of EEPROM available for non-volatile options */
+static struct nvo_fragment falcon_nvo_fragments[] = {
+ { 0x100, 0xf0 },
+ { 0, 0 }
+};
+
+/*******************************************************************************
+ *
+ *
+ * Falcon bit-bashed I2C interface
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_i2c_bit_write ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data )
+{
+ struct efab_nic *efab = container_of ( basher, struct efab_nic,
+ i2c_bb.basher );
+ efab_oword_t reg;
+
+ falcon_read ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+ switch ( bit_id ) {
+ case I2C_BIT_SCL:
+ EFAB_SET_OWORD_FIELD ( reg, FCN_GPIO0_OEN, ( data ? 0 : 1 ) );
+ break;
+ case I2C_BIT_SDA:
+ EFAB_SET_OWORD_FIELD ( reg, FCN_GPIO3_OEN, ( data ? 0 : 1 ) );
+ break;
+ default:
+ EFAB_ERR ( "%s bit=%d\n", __func__, bit_id );
+ break;
+ }
+
+ falcon_write ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+}
+
+static int
+falcon_i2c_bit_read ( struct bit_basher *basher, unsigned int bit_id )
+{
+ struct efab_nic *efab = container_of ( basher, struct efab_nic,
+ i2c_bb.basher );
+ efab_oword_t reg;
+
+ falcon_read ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+ switch ( bit_id ) {
+ case I2C_BIT_SCL:
+ return EFAB_OWORD_FIELD ( reg, FCN_GPIO0_IN );
+ break;
+ case I2C_BIT_SDA:
+ return EFAB_OWORD_FIELD ( reg, FCN_GPIO3_IN );
+ break;
+ default:
+ EFAB_ERR ( "%s bit=%d\n", __func__, bit_id );
+ break;
+ }
+
+ return -1;
+}
+
+static struct bit_basher_operations falcon_i2c_bit_ops = {
+ .read = falcon_i2c_bit_read,
+ .write = falcon_i2c_bit_write,
+};
+
+
+/*******************************************************************************
+ *
+ *
+ * MDIO access
+ *
+ *
+ *******************************************************************************/
+
+static int
+falcon_gmii_wait ( struct efab_nic *efab )
+{
+ efab_dword_t md_stat;
+ int count;
+
+ /* wait upto 10ms */
+ for (count = 0; count < 1000; count++) {
+ falcon_readl ( efab, &md_stat, FCN_MD_STAT_REG_KER );
+ if ( EFAB_DWORD_FIELD ( md_stat, FCN_MD_BSY ) == 0 ) {
+ if ( EFAB_DWORD_FIELD ( md_stat, FCN_MD_LNFL ) != 0 ||
+ EFAB_DWORD_FIELD ( md_stat, FCN_MD_BSERR ) != 0 ) {
+ EFAB_ERR ( "Error from GMII access "
+ EFAB_DWORD_FMT"\n",
+ EFAB_DWORD_VAL ( md_stat ));
+ return -EIO;
+ }
+ return 0;
+ }
+ udelay(10);
+ }
+
+ EFAB_ERR ( "Timed out waiting for GMII\n" );
+ return -ETIMEDOUT;
+}
+
+static void
+falcon_mdio_write ( struct efab_nic *efab, int device,
+ int location, int value )
+{
+ efab_oword_t reg;
+
+ EFAB_TRACE ( "Writing GMII %d register %02x with %04x\n",
+ device, location, value );
+
+ /* Check MII not currently being accessed */
+ if ( falcon_gmii_wait ( efab ) )
+ return;
+
+ /* Write the address/ID register */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_MD_PHY_ADR, location );
+ falcon_write ( efab, &reg, FCN_MD_PHY_ADR_REG_KER );
+
+ if ( efab->phy_10g ) {
+ /* clause45 */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, device );
+ }
+ else {
+ /* clause22 */
+ assert ( device == 0 );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, location );
+ }
+ falcon_write ( efab, &reg, FCN_MD_ID_REG_KER );
+
+
+ /* Write data */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_MD_TXD, value );
+ falcon_write ( efab, &reg, FCN_MD_TXD_REG_KER );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_WRC, 1,
+ FCN_MD_GC, ( efab->phy_10g ? 0 : 1 ) );
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+
+ /* Wait for data to be written */
+ if ( falcon_gmii_wait ( efab ) ) {
+ /* Abort the write operation */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_WRC, 0,
+ FCN_MD_GC, 1);
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+ udelay(10);
+ }
+}
+
+static int
+falcon_mdio_read ( struct efab_nic *efab, int device, int location )
+{
+ efab_oword_t reg;
+ int value;
+
+ /* Check MII not currently being accessed */
+ if ( falcon_gmii_wait ( efab ) )
+ return -1;
+
+ if ( efab->phy_10g ) {
+ /* clause45 */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_MD_PHY_ADR, location );
+ falcon_write ( efab, &reg, FCN_MD_PHY_ADR_REG_KER );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, device );
+ falcon_write ( efab, &reg, FCN_MD_ID_REG_KER);
+
+ /* request data to be read */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_RDC, 1,
+ FCN_MD_GC, 0 );
+ }
+ else {
+ /* clause22 */
+ assert ( device == 0 );
+
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_PRT_ADR, efab->phy_addr,
+ FCN_MD_DEV_ADR, location );
+ falcon_write ( efab, &reg, FCN_MD_ID_REG_KER );
+
+ /* Request data to be read */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_RIC, 1,
+ FCN_MD_GC, 1 );
+ }
+
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+
+ /* Wait for data to become available */
+ if ( falcon_gmii_wait ( efab ) ) {
+ /* Abort the read operation */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_MD_RIC, 0,
+ FCN_MD_GC, 1 );
+ falcon_write ( efab, &reg, FCN_MD_CS_REG_KER );
+ udelay ( 10 );
+ value = -1;
+ }
+ else {
+ /* Read the data */
+ falcon_read ( efab, &reg, FCN_MD_RXD_REG_KER );
+ value = EFAB_OWORD_FIELD ( reg, FCN_MD_RXD );
+ }
+
+ EFAB_TRACE ( "Read from GMII %d register %02x, got %04x\n",
+ device, location, value );
+
+ return value;
+}
+
+/*******************************************************************************
+ *
+ *
+ * MAC wrapper
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_reconfigure_mac_wrapper ( struct efab_nic *efab )
+{
+ efab_oword_t reg;
+ int link_speed;
+
+ if ( efab->link_options & LPA_EF_10000 ) {
+ link_speed = 0x3;
+ } else if ( efab->link_options & LPA_EF_1000 ) {
+ link_speed = 0x2;
+ } else if ( efab->link_options & LPA_100 ) {
+ link_speed = 0x1;
+ } else {
+ link_speed = 0x0;
+ }
+ EFAB_POPULATE_OWORD_5 ( reg,
+ FCN_MAC_XOFF_VAL, 0xffff /* datasheet */,
+ FCN_MAC_BCAD_ACPT, 1,
+ FCN_MAC_UC_PROM, 0,
+ FCN_MAC_LINK_STATUS, 1,
+ FCN_MAC_SPEED, link_speed );
+
+ falcon_write ( efab, &reg, FCN_MAC0_CTRL_REG_KER );
+}
+
+/*******************************************************************************
+ *
+ *
+ * GMAC handling
+ *
+ *
+ *******************************************************************************/
+
+/* GMAC configuration register 1 */
+#define GM_CFG1_REG_MAC 0x00
+#define GM_SW_RST_LBN 31
+#define GM_SW_RST_WIDTH 1
+#define GM_RX_FC_EN_LBN 5
+#define GM_RX_FC_EN_WIDTH 1
+#define GM_TX_FC_EN_LBN 4
+#define GM_TX_FC_EN_WIDTH 1
+#define GM_RX_EN_LBN 2
+#define GM_RX_EN_WIDTH 1
+#define GM_TX_EN_LBN 0
+#define GM_TX_EN_WIDTH 1
+
+/* GMAC configuration register 2 */
+#define GM_CFG2_REG_MAC 0x01
+#define GM_PAMBL_LEN_LBN 12
+#define GM_PAMBL_LEN_WIDTH 4
+#define GM_IF_MODE_LBN 8
+#define GM_IF_MODE_WIDTH 2
+#define GM_PAD_CRC_EN_LBN 2
+#define GM_PAD_CRC_EN_WIDTH 1
+#define GM_FD_LBN 0
+#define GM_FD_WIDTH 1
+
+/* GMAC maximum frame length register */
+#define GM_MAX_FLEN_REG_MAC 0x04
+#define GM_MAX_FLEN_LBN 0
+#define GM_MAX_FLEN_WIDTH 16
+
+/* GMAC MII management configuration register */
+#define GM_MII_MGMT_CFG_REG_MAC 0x08
+#define GM_MGMT_CLK_SEL_LBN 0
+#define GM_MGMT_CLK_SEL_WIDTH 3
+
+/* GMAC MII management command register */
+#define GM_MII_MGMT_CMD_REG_MAC 0x09
+#define GM_MGMT_SCAN_CYC_LBN 1
+#define GM_MGMT_SCAN_CYC_WIDTH 1
+#define GM_MGMT_RD_CYC_LBN 0
+#define GM_MGMT_RD_CYC_WIDTH 1
+
+/* GMAC MII management address register */
+#define GM_MII_MGMT_ADR_REG_MAC 0x0a
+#define GM_MGMT_PHY_ADDR_LBN 8
+#define GM_MGMT_PHY_ADDR_WIDTH 5
+#define GM_MGMT_REG_ADDR_LBN 0
+#define GM_MGMT_REG_ADDR_WIDTH 5
+
+/* GMAC MII management control register */
+#define GM_MII_MGMT_CTL_REG_MAC 0x0b
+#define GM_MGMT_CTL_LBN 0
+#define GM_MGMT_CTL_WIDTH 16
+
+/* GMAC MII management status register */
+#define GM_MII_MGMT_STAT_REG_MAC 0x0c
+#define GM_MGMT_STAT_LBN 0
+#define GM_MGMT_STAT_WIDTH 16
+
+/* GMAC MII management indicators register */
+#define GM_MII_MGMT_IND_REG_MAC 0x0d
+#define GM_MGMT_BUSY_LBN 0
+#define GM_MGMT_BUSY_WIDTH 1
+
+/* GMAC station address register 1 */
+#define GM_ADR1_REG_MAC 0x10
+#define GM_HWADDR_5_LBN 24
+#define GM_HWADDR_5_WIDTH 8
+#define GM_HWADDR_4_LBN 16
+#define GM_HWADDR_4_WIDTH 8
+#define GM_HWADDR_3_LBN 8
+#define GM_HWADDR_3_WIDTH 8
+#define GM_HWADDR_2_LBN 0
+#define GM_HWADDR_2_WIDTH 8
+
+/* GMAC station address register 2 */
+#define GM_ADR2_REG_MAC 0x11
+#define GM_HWADDR_1_LBN 24
+#define GM_HWADDR_1_WIDTH 8
+#define GM_HWADDR_0_LBN 16
+#define GM_HWADDR_0_WIDTH 8
+
+/* GMAC FIFO configuration register 0 */
+#define GMF_CFG0_REG_MAC 0x12
+#define GMF_FTFENREQ_LBN 12
+#define GMF_FTFENREQ_WIDTH 1
+#define GMF_STFENREQ_LBN 11
+#define GMF_STFENREQ_WIDTH 1
+#define GMF_FRFENREQ_LBN 10
+#define GMF_FRFENREQ_WIDTH 1
+#define GMF_SRFENREQ_LBN 9
+#define GMF_SRFENREQ_WIDTH 1
+#define GMF_WTMENREQ_LBN 8
+#define GMF_WTMENREQ_WIDTH 1
+
+/* GMAC FIFO configuration register 1 */
+#define GMF_CFG1_REG_MAC 0x13
+#define GMF_CFGFRTH_LBN 16
+#define GMF_CFGFRTH_WIDTH 5
+#define GMF_CFGXOFFRTX_LBN 0
+#define GMF_CFGXOFFRTX_WIDTH 16
+
+/* GMAC FIFO configuration register 2 */
+#define GMF_CFG2_REG_MAC 0x14
+#define GMF_CFGHWM_LBN 16
+#define GMF_CFGHWM_WIDTH 6
+#define GMF_CFGLWM_LBN 0
+#define GMF_CFGLWM_WIDTH 6
+
+/* GMAC FIFO configuration register 3 */
+#define GMF_CFG3_REG_MAC 0x15
+#define GMF_CFGHWMFT_LBN 16
+#define GMF_CFGHWMFT_WIDTH 6
+#define GMF_CFGFTTH_LBN 0
+#define GMF_CFGFTTH_WIDTH 6
+
+/* GMAC FIFO configuration register 4 */
+#define GMF_CFG4_REG_MAC 0x16
+#define GMF_HSTFLTRFRM_PAUSE_LBN 12
+#define GMF_HSTFLTRFRM_PAUSE_WIDTH 12
+
+/* GMAC FIFO configuration register 5 */
+#define GMF_CFG5_REG_MAC 0x17
+#define GMF_CFGHDPLX_LBN 22
+#define GMF_CFGHDPLX_WIDTH 1
+#define GMF_CFGBYTMODE_LBN 19
+#define GMF_CFGBYTMODE_WIDTH 1
+#define GMF_HSTDRPLT64_LBN 18
+#define GMF_HSTDRPLT64_WIDTH 1
+#define GMF_HSTFLTRFRMDC_PAUSE_LBN 12
+#define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1
+
+static void
+falcon_gmac_writel ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ EFAB_POPULATE_OWORD_1 ( temp, FCN_MAC_DATA,
+ EFAB_DWORD_FIELD ( *value, FCN_MAC_DATA ) );
+ falcon_write ( efab, &temp, FALCON_GMAC_REG ( efab, mac_reg ) );
+}
+
+static void
+falcon_gmac_readl ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ falcon_read ( efab, &temp, FALCON_GMAC_REG ( efab, mac_reg ) );
+ EFAB_POPULATE_DWORD_1 ( *value, FCN_MAC_DATA,
+ EFAB_OWORD_FIELD ( temp, FCN_MAC_DATA ) );
+}
+
+static void
+mentormac_reset ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+
+ /* Take into reset */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_SW_RST, 1 );
+ falcon_gmac_writel ( efab, &reg, GM_CFG1_REG_MAC );
+ udelay ( 1000 );
+
+ /* Take out of reset */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_SW_RST, 0 );
+ falcon_gmac_writel ( efab, &reg, GM_CFG1_REG_MAC );
+ udelay ( 1000 );
+
+ /* Configure GMII interface so PHY is accessible. Note that
+ * GMII interface is connected only to port 0, and that on
+ * Falcon this is a no-op.
+ */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_MGMT_CLK_SEL, 0x4 );
+ falcon_gmac_writel ( efab, &reg, GM_MII_MGMT_CFG_REG_MAC );
+ udelay ( 10 );
+}
+
+static void
+mentormac_init ( struct efab_nic *efab )
+{
+ int pause, if_mode, full_duplex, bytemode, half_duplex;
+ efab_dword_t reg;
+
+ /* Configuration register 1 */
+ pause = ( efab->link_options & LPA_PAUSE_CAP ) ? 1 : 0;
+ if ( ! ( efab->link_options & LPA_EF_DUPLEX ) ) {
+ /* Half-duplex operation requires TX flow control */
+ pause = 1;
+ }
+ EFAB_POPULATE_DWORD_4 ( reg,
+ GM_TX_EN, 1,
+ GM_TX_FC_EN, pause,
+ GM_RX_EN, 1,
+ GM_RX_FC_EN, 1 );
+ falcon_gmac_writel ( efab, &reg, GM_CFG1_REG_MAC );
+ udelay ( 10 );
+
+ /* Configuration register 2 */
+ if_mode = ( efab->link_options & LPA_EF_1000 ) ? 2 : 1;
+ full_duplex = ( efab->link_options & LPA_EF_DUPLEX ) ? 1 : 0;
+ EFAB_POPULATE_DWORD_4 ( reg,
+ GM_IF_MODE, if_mode,
+ GM_PAD_CRC_EN, 1,
+ GM_FD, full_duplex,
+ GM_PAMBL_LEN, 0x7 /* ? */ );
+ falcon_gmac_writel ( efab, &reg, GM_CFG2_REG_MAC );
+ udelay ( 10 );
+
+ /* Max frame len register */
+ EFAB_POPULATE_DWORD_1 ( reg, GM_MAX_FLEN,
+ EFAB_MAX_FRAME_LEN ( ETH_FRAME_LEN ) );
+ falcon_gmac_writel ( efab, &reg, GM_MAX_FLEN_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 0 */
+ EFAB_POPULATE_DWORD_5 ( reg,
+ GMF_FTFENREQ, 1,
+ GMF_STFENREQ, 1,
+ GMF_FRFENREQ, 1,
+ GMF_SRFENREQ, 1,
+ GMF_WTMENREQ, 1 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG0_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 1 */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GMF_CFGFRTH, 0x12,
+ GMF_CFGXOFFRTX, 0xffff );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG1_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 2 */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GMF_CFGHWM, 0x3f,
+ GMF_CFGLWM, 0xa );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG2_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 3 */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GMF_CFGHWMFT, 0x1c,
+ GMF_CFGFTTH, 0x08 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG3_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 4 */
+ EFAB_POPULATE_DWORD_1 ( reg, GMF_HSTFLTRFRM_PAUSE, 1 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG4_REG_MAC );
+ udelay ( 10 );
+
+ /* FIFO configuration register 5 */
+ bytemode = ( efab->link_options & LPA_EF_1000 ) ? 1 : 0;
+ half_duplex = ( efab->link_options & LPA_EF_DUPLEX ) ? 0 : 1;
+ falcon_gmac_readl ( efab, &reg, GMF_CFG5_REG_MAC );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_CFGBYTMODE, bytemode );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_CFGHDPLX, half_duplex );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_HSTDRPLT64, half_duplex );
+ EFAB_SET_DWORD_FIELD ( reg, GMF_HSTFLTRFRMDC_PAUSE, 0 );
+ falcon_gmac_writel ( efab, &reg, GMF_CFG5_REG_MAC );
+ udelay ( 10 );
+
+ /* MAC address */
+ EFAB_POPULATE_DWORD_4 ( reg,
+ GM_HWADDR_5, efab->mac_addr[5],
+ GM_HWADDR_4, efab->mac_addr[4],
+ GM_HWADDR_3, efab->mac_addr[3],
+ GM_HWADDR_2, efab->mac_addr[2] );
+ falcon_gmac_writel ( efab, &reg, GM_ADR1_REG_MAC );
+ udelay ( 10 );
+ EFAB_POPULATE_DWORD_2 ( reg,
+ GM_HWADDR_1, efab->mac_addr[1],
+ GM_HWADDR_0, efab->mac_addr[0] );
+ falcon_gmac_writel ( efab, &reg, GM_ADR2_REG_MAC );
+ udelay ( 10 );
+}
+
+static int
+falcon_init_gmac ( struct efab_nic *efab )
+{
+ /* Reset the MAC */
+ mentormac_reset ( efab );
+
+ /* Initialise PHY */
+ efab->phy_op->init ( efab );
+
+ /* check the link is up */
+ if ( !efab->link_up )
+ return -EAGAIN;
+
+ /* Initialise MAC */
+ mentormac_init ( efab );
+
+ /* reconfigure the MAC wrapper */
+ falcon_reconfigure_mac_wrapper ( efab );
+
+ return 0;
+}
+
+static struct efab_mac_operations falcon_gmac_operations = {
+ .init = falcon_init_gmac,
+};
+
+
+/*******************************************************************************
+ *
+ *
+ * XMAC handling
+ *
+ *
+ *******************************************************************************/
+
+/**
+ * Write dword to a Falcon XMAC register
+ *
+ */
+static void
+falcon_xmac_writel ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ EFAB_POPULATE_OWORD_1 ( temp, FCN_MAC_DATA,
+ EFAB_DWORD_FIELD ( *value, FCN_MAC_DATA ) );
+ falcon_write ( efab, &temp,
+ FALCON_XMAC_REG ( efab, mac_reg ) );
+}
+
+/**
+ * Read dword from a Falcon XMAC register
+ *
+ */
+static void
+falcon_xmac_readl ( struct efab_nic *efab, efab_dword_t *value,
+ unsigned int mac_reg )
+{
+ efab_oword_t temp;
+
+ falcon_read ( efab, &temp,
+ FALCON_XMAC_REG ( efab, mac_reg ) );
+ EFAB_POPULATE_DWORD_1 ( *value, FCN_MAC_DATA,
+ EFAB_OWORD_FIELD ( temp, FCN_MAC_DATA ) );
+}
+
+/**
+ * Configure Falcon XAUI output
+ */
+static void
+falcon_setup_xaui ( struct efab_nic *efab )
+{
+ efab_dword_t sdctl, txdrv;
+
+ falcon_xmac_readl ( efab, &sdctl, FCN_XX_SD_CTL_REG_MAC );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVD, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVC, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVB, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT );
+ EFAB_SET_DWORD_FIELD ( sdctl, FCN_XX_LODRVA, XX_SD_CTL_DRV_DEFAULT );
+ falcon_xmac_writel ( efab, &sdctl, FCN_XX_SD_CTL_REG_MAC );
+
+ EFAB_POPULATE_DWORD_8 ( txdrv,
+ FCN_XX_DEQD, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DEQC, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DEQB, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DEQA, XX_TXDRV_DEQ_DEFAULT,
+ FCN_XX_DTXD, XX_TXDRV_DTX_DEFAULT,
+ FCN_XX_DTXC, XX_TXDRV_DTX_DEFAULT,
+ FCN_XX_DTXB, XX_TXDRV_DTX_DEFAULT,
+ FCN_XX_DTXA, XX_TXDRV_DTX_DEFAULT);
+ falcon_xmac_writel ( efab, &txdrv, FCN_XX_TXDRV_CTL_REG_MAC);
+}
+
+static int
+falcon_xgmii_status ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+
+ if ( efab->pci_revision < FALCON_REV_B0 )
+ return 1;
+ /* The ISR latches, so clear it and re-read */
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_REG_MAC_B0 );
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_REG_MAC_B0 );
+
+ if ( EFAB_DWORD_FIELD ( reg, FCN_XM_LCLFLT ) ||
+ EFAB_DWORD_FIELD ( reg, FCN_XM_RMTFLT ) ) {
+ EFAB_TRACE ( "MGT_INT: "EFAB_DWORD_FMT"\n",
+ EFAB_DWORD_VAL ( reg ) );
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+falcon_mask_status_intr ( struct efab_nic *efab, int enable )
+{
+ efab_dword_t reg;
+
+ if ( efab->pci_revision < FALCON_REV_B0 )
+ return;
+
+ /* Flush the ISR */
+ if ( enable )
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_REG_MAC_B0 );
+
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_MSK_RMTFLT, !enable,
+ FCN_XM_MSK_LCLFLT, !enable);
+ falcon_xmac_readl ( efab, &reg, FCN_XM_MGT_INT_MSK_REG_MAC_B0 );
+}
+
+/**
+ * Reset 10G MAC connected to port
+ *
+ */
+static int
+falcon_reset_xmac ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int count;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_XM_CORE_RST, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_GLB_CFG_REG_MAC );
+
+ for ( count = 0 ; count < 1000 ; count++ ) {
+ udelay ( 10 );
+ falcon_xmac_readl ( efab, &reg,
+ FCN_XM_GLB_CFG_REG_MAC );
+ if ( EFAB_DWORD_FIELD ( reg, FCN_XM_CORE_RST ) == 0 )
+ return 0;
+ }
+ return -ETIMEDOUT;
+}
+
+
+static int
+falcon_reset_xaui ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int count;
+
+ if (!efab->is_asic)
+ return 0;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_XX_RST_XX_EN, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XX_PWR_RST_REG_MAC );
+
+ /* Give some time for the link to establish */
+ for (count = 0; count < 1000; count++) { /* wait upto 10ms */
+ falcon_xmac_readl ( efab, &reg, FCN_XX_PWR_RST_REG_MAC );
+ if ( EFAB_DWORD_FIELD ( reg, FCN_XX_RST_XX_EN ) == 0 ) {
+ falcon_setup_xaui ( efab );
+ return 0;
+ }
+ udelay(10);
+ }
+ EFAB_ERR ( "timed out waiting for XAUI/XGXS reset\n" );
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_xaui_link_ok ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int align_done, lane_status, sync;
+ int has_phyxs;
+ int link_ok = 1;
+
+ /* Read Falcon XAUI side */
+ if ( efab->is_asic ) {
+ /* Read link status */
+ falcon_xmac_readl ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+ align_done = EFAB_DWORD_FIELD ( reg, FCN_XX_ALIGN_DONE );
+
+ sync = EFAB_DWORD_FIELD ( reg, FCN_XX_SYNC_STAT );
+ sync = ( sync == FCN_XX_SYNC_STAT_DECODE_SYNCED );
+
+ link_ok = align_done && sync;
+ }
+
+ /* Clear link status ready for next read */
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_COMMA_DET, FCN_XX_COMMA_DET_RESET );
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_CHARERR, FCN_XX_CHARERR_RESET);
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_DISPERR, FCN_XX_DISPERR_RESET);
+ falcon_xmac_writel ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+
+ has_phyxs = ( efab->phy_op->mmds & ( 1 << MDIO_MMD_PHYXS ) );
+ if ( link_ok && has_phyxs ) {
+ lane_status = falcon_mdio_read ( efab, MDIO_MMD_PHYXS,
+ MDIO_PHYXS_LANE_STATE );
+ link_ok = ( lane_status & ( 1 << MDIO_PHYXS_LANE_ALIGNED_LBN ) );
+
+ if (!link_ok )
+ EFAB_LOG ( "XGXS lane status: %x\n", lane_status );
+ }
+
+ return link_ok;
+}
+
+/**
+ * Initialise XMAC
+ *
+ */
+static void
+falcon_reconfigure_xmac ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+ int max_frame_len;
+
+ /* Configure MAC - cut-thru mode is hard wired on */
+ EFAB_POPULATE_DWORD_3 ( reg,
+ FCN_XM_RX_JUMBO_MODE, 1,
+ FCN_XM_TX_STAT_EN, 1,
+ FCN_XM_RX_STAT_EN, 1);
+ falcon_xmac_writel ( efab, &reg, FCN_XM_GLB_CFG_REG_MAC );
+
+ /* Configure TX */
+ EFAB_POPULATE_DWORD_6 ( reg,
+ FCN_XM_TXEN, 1,
+ FCN_XM_TX_PRMBL, 1,
+ FCN_XM_AUTO_PAD, 1,
+ FCN_XM_TXCRC, 1,
+ FCN_XM_FCNTL, 1,
+ FCN_XM_IPG, 0x3 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_TX_CFG_REG_MAC );
+
+ /* Configure RX */
+ EFAB_POPULATE_DWORD_4 ( reg,
+ FCN_XM_RXEN, 1,
+ FCN_XM_AUTO_DEPAD, 0,
+ FCN_XM_ACPT_ALL_MCAST, 1,
+ FCN_XM_PASS_CRC_ERR, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_RX_CFG_REG_MAC );
+
+ /* Set frame length */
+ max_frame_len = EFAB_MAX_FRAME_LEN ( ETH_FRAME_LEN );
+ EFAB_POPULATE_DWORD_1 ( reg,
+ FCN_XM_MAX_RX_FRM_SIZE, max_frame_len );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_RX_PARAM_REG_MAC );
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_MAX_TX_FRM_SIZE, max_frame_len,
+ FCN_XM_TX_JUMBO_MODE, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_TX_PARAM_REG_MAC );
+
+ /* Enable flow control receipt */
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_PAUSE_TIME, 0xfffe,
+ FCN_XM_DIS_FCNTL, 0 );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_FC_REG_MAC );
+
+ /* Set MAC address */
+ EFAB_POPULATE_DWORD_4 ( reg,
+ FCN_XM_ADR_0, efab->mac_addr[0],
+ FCN_XM_ADR_1, efab->mac_addr[1],
+ FCN_XM_ADR_2, efab->mac_addr[2],
+ FCN_XM_ADR_3, efab->mac_addr[3] );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_ADR_LO_REG_MAC );
+ EFAB_POPULATE_DWORD_2 ( reg,
+ FCN_XM_ADR_4, efab->mac_addr[4],
+ FCN_XM_ADR_5, efab->mac_addr[5] );
+ falcon_xmac_writel ( efab, &reg, FCN_XM_ADR_HI_REG_MAC );
+}
+
+static int
+falcon_init_xmac ( struct efab_nic *efab )
+{
+ int count, rc;
+
+ /* Mask the PHY management interrupt */
+ falcon_mask_status_intr ( efab, 0 );
+
+ /* Initialise the PHY to instantiate the clock. */
+ rc = efab->phy_op->init ( efab );
+ if ( rc ) {
+ EFAB_ERR ( "unable to initialise PHY\n" );
+ goto fail1;
+ }
+
+ falcon_reset_xaui ( efab );
+
+ /* Give the PHY and MAC time to faff */
+ mdelay ( 100 );
+
+ /* Reset and reconfigure the XMAC */
+ rc = falcon_reset_xmac ( efab );
+ if ( rc )
+ goto fail2;
+ falcon_reconfigure_xmac ( efab );
+ falcon_reconfigure_mac_wrapper ( efab );
+ /**
+ * Now wait for the link to come up. This may take a while
+ * for some slower PHY's.
+ */
+ for (count=0; count<50; count++) {
+ int link_ok = 1;
+
+ /* Wait a while for the link to come up. */
+ mdelay ( 100 );
+ if ((count % 5) == 0)
+ putchar ( '.' );
+
+ /* Does the PHY think the wire-side link is up? */
+ link_ok = mdio_clause45_links_ok ( efab );
+ /* Ensure the XAUI link to the PHY is good */
+ if ( link_ok ) {
+ link_ok = falcon_xaui_link_ok ( efab );
+ if ( !link_ok )
+ falcon_reset_xaui ( efab );
+ }
+
+ /* Check fault indication */
+ if ( link_ok )
+ link_ok = falcon_xgmii_status ( efab );
+
+ efab->link_up = link_ok;
+ if ( link_ok ) {
+ /* unmask the status interrupt */
+ falcon_mask_status_intr ( efab, 1 );
+ return 0;
+ }
+ }
+
+ /* Link failed to come up, but initialisation was fine. */
+ rc = -ETIMEDOUT;
+
+fail2:
+fail1:
+ return rc;
+}
+
+static struct efab_mac_operations falcon_xmac_operations = {
+ .init = falcon_init_xmac,
+};
+
+/*******************************************************************************
+ *
+ *
+ * Null PHY handling
+ *
+ *
+ *******************************************************************************/
+
+static int
+falcon_xaui_phy_init ( struct efab_nic *efab )
+{
+ /* CX4 is always 10000FD only */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* There is no PHY! */
+ return 0;
+}
+
+static struct efab_phy_operations falcon_xaui_phy_ops = {
+ .init = falcon_xaui_phy_init,
+ .mmds = 0,
+};
+
+
+/*******************************************************************************
+ *
+ *
+ * Alaska PHY
+ *
+ *
+ *******************************************************************************/
+
+/**
+ * Initialise Alaska PHY
+ *
+ */
+static int
+alaska_init ( struct efab_nic *efab )
+{
+ unsigned int advertised, lpa;
+
+ /* Read link up status */
+ efab->link_up = gmii_link_ok ( efab );
+
+ if ( ! efab->link_up )
+ return -EIO;
+
+ /* Determine link options from PHY. */
+ advertised = gmii_autoneg_advertised ( efab );
+ lpa = gmii_autoneg_lpa ( efab );
+ efab->link_options = gmii_nway_result ( advertised & lpa );
+
+ return 0;
+}
+
+static struct efab_phy_operations falcon_alaska_phy_ops = {
+ .init = alaska_init,
+};
+
+/*******************************************************************************
+ *
+ *
+ * xfp
+ *
+ *
+ *******************************************************************************/
+
+#define XFP_REQUIRED_DEVS ( MDIO_MMDREG_DEVS0_PCS | \
+ MDIO_MMDREG_DEVS0_PMAPMD | \
+ MDIO_MMDREG_DEVS0_PHYXS )
+
+static int
+falcon_xfp_phy_init ( struct efab_nic *efab )
+{
+ int rc;
+
+ /* Optical link is always 10000FD only */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* Reset the PHY */
+ rc = mdio_clause45_reset_mmd ( efab, MDIO_MMD_PHYXS );
+ if ( rc )
+ return rc;
+
+ return 0;
+}
+
+static struct efab_phy_operations falcon_xfp_phy_ops = {
+ .init = falcon_xfp_phy_init,
+ .mmds = XFP_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * txc43128
+ *
+ *
+ *******************************************************************************/
+
+/* Command register */
+#define TXC_GLRGS_GLCMD (0xc004)
+#define TXC_GLCMD_LMTSWRST_LBN (14)
+
+/* Amplitude on lanes 0+1, 2+3 */
+#define TXC_ALRGS_ATXAMP0 (0xc041)
+#define TXC_ALRGS_ATXAMP1 (0xc042)
+/* Bit position of value for lane 0+2, 1+3 */
+#define TXC_ATXAMP_LANE02_LBN (3)
+#define TXC_ATXAMP_LANE13_LBN (11)
+
+#define TXC_ATXAMP_1280_mV (0)
+#define TXC_ATXAMP_1200_mV (8)
+#define TXC_ATXAMP_1120_mV (12)
+#define TXC_ATXAMP_1060_mV (14)
+#define TXC_ATXAMP_0820_mV (25)
+#define TXC_ATXAMP_0720_mV (26)
+#define TXC_ATXAMP_0580_mV (27)
+#define TXC_ATXAMP_0440_mV (28)
+
+#define TXC_ATXAMP_0820_BOTH ( (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) | \
+ (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN) )
+
+#define TXC_ATXAMP_DEFAULT (0x6060) /* From databook */
+
+/* Preemphasis on lanes 0+1, 2+3 */
+#define TXC_ALRGS_ATXPRE0 (0xc043)
+#define TXC_ALRGS_ATXPRE1 (0xc044)
+
+#define TXC_ATXPRE_NONE (0)
+#define TXC_ATXPRE_DEFAULT (0x1010) /* From databook */
+
+#define TXC_REQUIRED_DEVS ( MDIO_MMDREG_DEVS0_PCS | \
+ MDIO_MMDREG_DEVS0_PMAPMD | \
+ MDIO_MMDREG_DEVS0_PHYXS )
+
+static int
+falcon_txc_logic_reset ( struct efab_nic *efab )
+{
+ int val;
+ int tries = 50;
+
+ val = falcon_mdio_read ( efab, MDIO_MMD_PCS, TXC_GLRGS_GLCMD );
+ val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
+ falcon_mdio_write ( efab, MDIO_MMD_PCS, TXC_GLRGS_GLCMD, val );
+
+ while ( tries--) {
+ val = falcon_mdio_read ( efab, MDIO_MMD_PCS, TXC_GLRGS_GLCMD );
+ if ( ~val & ( 1 << TXC_GLCMD_LMTSWRST_LBN ) )
+ return 0;
+ udelay(1);
+ }
+
+ EFAB_ERR ( "logic reset failed\n" );
+
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_txc_phy_init ( struct efab_nic *efab )
+{
+ int rc;
+
+ /* CX4 is always 10000FD only */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* reset the phy */
+ rc = mdio_clause45_reset_mmd ( efab, MDIO_MMD_PMAPMD );
+ if ( rc )
+ goto fail1;
+
+ rc = mdio_clause45_check_mmds ( efab );
+ if ( rc )
+ goto fail2;
+
+ /* Turn amplitude down and preemphasis off on the host side
+ * (PHY<->MAC) as this is believed less likely to upset falcon
+ * and no adverse effects have been noted. It probably also
+ * saves a picowatt or two */
+
+ /* Turn off preemphasis */
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0,
+ TXC_ATXPRE_NONE );
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1,
+ TXC_ATXPRE_NONE );
+
+ /* Turn down the amplitude */
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXAMP0,
+ TXC_ATXAMP_0820_BOTH );
+ falcon_mdio_write ( efab, MDIO_MMD_PHYXS, TXC_ALRGS_ATXAMP1,
+ TXC_ATXAMP_0820_BOTH );
+
+ /* Set the line side amplitude and preemphasis to the databook
+ * defaults as an erratum causes them to be 0 on at least some
+ * PHY rev.s */
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXPRE0,
+ TXC_ATXPRE_DEFAULT );
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXPRE1,
+ TXC_ATXPRE_DEFAULT );
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXAMP0,
+ TXC_ATXAMP_DEFAULT );
+ falcon_mdio_write ( efab, MDIO_MMD_PMAPMD, TXC_ALRGS_ATXAMP1,
+ TXC_ATXAMP_DEFAULT );
+
+ rc = falcon_txc_logic_reset ( efab );
+ if ( rc )
+ goto fail3;
+
+ return 0;
+
+fail3:
+fail2:
+fail1:
+ return rc;
+}
+
+static struct efab_phy_operations falcon_txc_phy_ops = {
+ .init = falcon_txc_phy_init,
+ .mmds = TXC_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * tenxpress
+ *
+ *
+ *******************************************************************************/
+
+
+#define TENXPRESS_REQUIRED_DEVS ( MDIO_MMDREG_DEVS0_PMAPMD | \
+ MDIO_MMDREG_DEVS0_PCS | \
+ MDIO_MMDREG_DEVS0_PHYXS )
+
+#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */
+#define CLK312_EN_LBN 3
+#define CLK312_EN_WIDTH 1
+
+#define PCS_CLOCK_CTRL_REG 0xd801
+#define PLL312_RST_N_LBN 2
+
+/* Special Software reset register */
+#define PMA_PMD_EXT_CTRL_REG 49152
+#define PMA_PMD_EXT_SSR_LBN 15
+
+/* Boot status register */
+#define PCS_BOOT_STATUS_REG 0xd000
+#define PCS_BOOT_FATAL_ERR_LBN 0
+#define PCS_BOOT_PROGRESS_LBN 1
+#define PCS_BOOT_PROGRESS_WIDTH 2
+#define PCS_BOOT_COMPLETE_LBN 3
+
+#define PCS_SOFT_RST2_REG 0xd806
+#define SERDES_RST_N_LBN 13
+#define XGXS_RST_N_LBN 12
+
+static int
+falcon_tenxpress_check_c11 ( struct efab_nic *efab )
+{
+ int count;
+ uint32_t boot_stat;
+
+ /* Check that the C11 CPU has booted */
+ for (count=0; count<10; count++) {
+ boot_stat = falcon_mdio_read ( efab, MDIO_MMD_PCS,
+ PCS_BOOT_STATUS_REG );
+ if ( boot_stat & ( 1 << PCS_BOOT_COMPLETE_LBN ) )
+ return 0;
+
+ udelay(10);
+ }
+
+ EFAB_ERR ( "C11 failed to boot\n" );
+ return -ETIMEDOUT;
+}
+
+static int
+falcon_tenxpress_phy_init ( struct efab_nic *efab )
+{
+ int rc, reg;
+
+ /* 10XPRESS is always 10000FD (at the moment) */
+ efab->link_options = LPA_EF_10000FULL;
+
+ /* Wait for the blocks to come out of reset */
+ rc = mdio_clause45_wait_reset_mmds ( efab );
+ if ( rc )
+ goto fail1;
+
+ rc = mdio_clause45_check_mmds ( efab );
+ if ( rc )
+ goto fail2;
+
+ /* Turn on the clock */
+ reg = (1 << CLK312_EN_LBN);
+ falcon_mdio_write ( efab, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, reg);
+
+ /* Wait 200ms for the PHY to boot */
+ mdelay(200);
+
+ rc = falcon_tenxpress_check_c11 ( efab );
+ if ( rc )
+ goto fail3;
+
+ return 0;
+
+fail3:
+fail2:
+fail1:
+ return rc;
+}
+
+static struct efab_phy_operations falcon_tenxpress_phy_ops = {
+ .init = falcon_tenxpress_phy_init,
+ .mmds = TENXPRESS_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * PM8358
+ *
+ *
+ *******************************************************************************/
+
+/* The PM8358 just presents a DTE XS */
+#define PM8358_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_DTEXS)
+
+/* PHY-specific definitions */
+/* Master ID and Global Performance Monitor Update */
+#define PMC_MASTER_REG (0xd000)
+/* Analog Tx Rx settings under software control */
+#define PMC_MASTER_ANLG_CTRL (1<< 11)
+
+/* Master Configuration register 2 */
+#define PMC_MCONF2_REG (0xd002)
+/* Drive Tx off centre of data eye (1) vs. clock edge (0) */
+#define PMC_MCONF2_TEDGE (1 << 2)
+/* Drive Rx off centre of data eye (1) vs. clock edge (0) */
+#define PMC_MCONF2_REDGE (1 << 3)
+
+/* Analog Rx settings */
+#define PMC_ANALOG_RX_CFG0 (0xd025)
+#define PMC_ANALOG_RX_CFG1 (0xd02d)
+#define PMC_ANALOG_RX_CFG2 (0xd035)
+#define PMC_ANALOG_RX_CFG3 (0xd03d)
+
+
+#define PMC_ANALOG_RX_TERM (1 << 15) /* Bit 15 of RX CFG: 0 for 100 ohms float,
+ 1 for 50 to 1.2V */
+#define PMC_ANALOG_RX_EQ_MASK (3 << 8)
+#define PMC_ANALOG_RX_EQ_NONE (0 << 8)
+#define PMC_ANALOG_RX_EQ_HALF (1 << 8)
+#define PMC_ANALOG_RX_EQ_FULL (2 << 8)
+#define PMC_ANALOG_RX_EQ_RSVD (3 << 8)
+
+static int
+falcon_pm8358_phy_init ( struct efab_nic *efab )
+{
+ int rc, reg, i;
+
+ /* This is a XAUI retimer part */
+ efab->link_options = LPA_EF_10000FULL;
+
+ rc = mdio_clause45_reset_mmd ( efab, MDIO_MMDREG_DEVS0_DTEXS );
+ if ( rc )
+ return rc;
+
+ /* Enable software control of analogue settings */
+ reg = falcon_mdio_read ( efab, MDIO_MMD_DTEXS, PMC_MASTER_REG );
+ reg |= PMC_MASTER_ANLG_CTRL;
+ falcon_mdio_write ( efab, MDIO_MMD_DTEXS, PMC_MASTER_REG, reg );
+
+ /* Turn rx eq on for all channels */
+ for (i=0; i< 3; i++) {
+ /* The analog CFG registers are evenly spaced 8 apart */
+ uint16_t addr = PMC_ANALOG_RX_CFG0 + 8*i;
+ reg = falcon_mdio_read ( efab, MDIO_MMD_DTEXS, addr );
+ reg = ( reg & ~PMC_ANALOG_RX_EQ_MASK ) | PMC_ANALOG_RX_EQ_FULL;
+ falcon_mdio_write ( efab, MDIO_MMD_DTEXS, addr, reg );
+ }
+
+ /* Set TEDGE, clear REDGE */
+ reg = falcon_mdio_read ( efab, MDIO_MMD_DTEXS, PMC_MCONF2_REG );
+ reg = ( reg & ~PMC_MCONF2_REDGE) | PMC_MCONF2_TEDGE;
+ falcon_mdio_write ( efab, MDIO_MMD_DTEXS, PMC_MCONF2_REG, reg );
+
+ return 0;
+}
+
+static struct efab_phy_operations falcon_pm8358_phy_ops = {
+ .init = falcon_pm8358_phy_init,
+ .mmds = PM8358_REQUIRED_DEVS,
+};
+
+/*******************************************************************************
+ *
+ *
+ * SFE4001 support
+ *
+ *
+ *******************************************************************************/
+
+#define MAX_TEMP_THRESH 90
+
+/* I2C Expander */
+#define PCA9539 0x74
+
+#define P0_IN 0x00
+#define P0_OUT 0x02
+#define P0_CONFIG 0x06
+
+#define P0_EN_1V0X_LBN 0
+#define P0_EN_1V0X_WIDTH 1
+#define P0_EN_1V2_LBN 1
+#define P0_EN_1V2_WIDTH 1
+#define P0_EN_2V5_LBN 2
+#define P0_EN_2V5_WIDTH 1
+#define P0_EN_3V3X_LBN 3
+#define P0_EN_3V3X_WIDTH 1
+#define P0_EN_5V_LBN 4
+#define P0_EN_5V_WIDTH 1
+#define P0_X_TRST_LBN 6
+#define P0_X_TRST_WIDTH 1
+
+#define P1_IN 0x01
+#define P1_CONFIG 0x07
+
+#define P1_AFE_PWD_LBN 0
+#define P1_AFE_PWD_WIDTH 1
+#define P1_DSP_PWD25_LBN 1
+#define P1_DSP_PWD25_WIDTH 1
+#define P1_SPARE_LBN 4
+#define P1_SPARE_WIDTH 4
+
+/* Temperature Sensor */
+#define MAX6647 0x4e
+
+#define RSL 0x02
+#define RLHN 0x05
+#define WLHO 0x0b
+
+static struct i2c_device i2c_pca9539 = {
+ .dev_addr = PCA9539,
+ .dev_addr_len = 1,
+ .word_addr_len = 1,
+};
+
+
+static struct i2c_device i2c_max6647 = {
+ .dev_addr = MAX6647,
+ .dev_addr_len = 1,
+ .word_addr_len = 1,
+};
+
+static int
+sfe4001_init ( struct efab_nic *efab )
+{
+ struct i2c_interface *i2c = &efab->i2c_bb.i2c;
+ efab_dword_t reg;
+ uint8_t in, cfg, out;
+ int count, rc;
+
+ EFAB_LOG ( "Initialise SFE4001 board\n" );
+
+ /* Ensure XGXS and XAUI SerDes are held in reset */
+ EFAB_POPULATE_DWORD_7 ( reg,
+ FCN_XX_PWRDNA_EN, 1,
+ FCN_XX_PWRDNB_EN, 1,
+ FCN_XX_RSTPLLAB_EN, 1,
+ FCN_XX_RESETA_EN, 1,
+ FCN_XX_RESETB_EN, 1,
+ FCN_XX_RSTXGXSRX_EN, 1,
+ FCN_XX_RSTXGXSTX_EN, 1 );
+ falcon_xmac_writel ( efab, &reg, FCN_XX_PWR_RST_REG_MAC);
+ udelay(10);
+
+ /* Set DSP over-temperature alert threshold */
+ cfg = MAX_TEMP_THRESH;
+ rc = i2c->write ( i2c, &i2c_max6647, WLHO, &cfg, EFAB_BYTE );
+ if ( rc )
+ goto fail1;
+
+ /* Read it back and verify */
+ rc = i2c->read ( i2c, &i2c_max6647, RLHN, &in, EFAB_BYTE );
+ if ( rc )
+ goto fail2;
+
+ if ( in != MAX_TEMP_THRESH ) {
+ EFAB_ERR ( "Unable to verify MAX6647 limit (requested=%d "
+ "confirmed=%d)\n", cfg, in );
+ rc = -EIO;
+ goto fail3;
+ }
+
+ /* Clear any previous over-temperature alert */
+ rc = i2c->read ( i2c, &i2c_max6647, RSL, &in, EFAB_BYTE );
+ if ( rc )
+ goto fail4;
+
+ /* Enable port 0 and 1 outputs on IO expander */
+ cfg = 0x00;
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_CONFIG, &cfg, EFAB_BYTE );
+ if ( rc )
+ goto fail5;
+ cfg = 0xff & ~(1 << P1_SPARE_LBN);
+ rc = i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &cfg, EFAB_BYTE );
+ if ( rc )
+ goto fail6;
+
+ /* Turn all power off then wait 1 sec. This ensures PHY is reset */
+ out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) |
+ (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) |
+ (0 << P0_EN_1V0X_LBN));
+
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ if ( rc )
+ goto fail7;
+
+ mdelay(1000);
+
+ for (count=0; count<20; count++) {
+ /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */
+ out = 0xff & ~( (1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) |
+ (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) |
+ (1 << P0_X_TRST_LBN) );
+
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ if ( rc )
+ goto fail8;
+
+ mdelay ( 10 );
+
+ /* Turn on the 1V power rail */
+ out &= ~( 1 << P0_EN_1V0X_LBN );
+ rc = i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ if ( rc )
+ goto fail9;
+
+ EFAB_LOG ( "Waiting for power...(attempt %d)\n", count);
+ mdelay ( 1000 );
+
+ /* Check DSP is powered */
+ rc = i2c->read ( i2c, &i2c_pca9539, P1_IN, &in, EFAB_BYTE );
+ if ( rc )
+ goto fail10;
+
+ if ( in & ( 1 << P1_AFE_PWD_LBN ) )
+ return 0;
+ }
+
+ rc = -ETIMEDOUT;
+
+fail10:
+fail9:
+fail8:
+fail7:
+ /* Turn off power rails */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+ /* Disable port 1 outputs on IO expander */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &out, EFAB_BYTE );
+fail6:
+ /* Disable port 0 outputs */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &out, EFAB_BYTE );
+fail5:
+fail4:
+fail3:
+fail2:
+fail1:
+ EFAB_ERR ( "Failed initialising SFE4001 board\n" );
+ return rc;
+}
+
+static void
+sfe4001_fini ( struct efab_nic *efab )
+{
+ struct i2c_interface *i2c = &efab->i2c_bb.i2c;
+ uint8_t in, cfg, out;
+
+ EFAB_ERR ( "Turning off SFE4001\n" );
+
+ /* Turn off all power rails */
+ out = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P0_OUT, &out, EFAB_BYTE );
+
+ /* Disable port 1 outputs on IO expander */
+ cfg = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P1_CONFIG, &cfg, EFAB_BYTE );
+
+ /* Disable port 0 outputs on IO expander */
+ cfg = 0xff;
+ (void) i2c->write ( i2c, &i2c_pca9539, P0_CONFIG, &cfg, EFAB_BYTE );
+
+ /* Clear any over-temperature alert */
+ (void) i2c->read ( i2c, &i2c_max6647, RSL, &in, EFAB_BYTE );
+}
+
+struct efab_board_operations sfe4001_ops = {
+ .init = sfe4001_init,
+ .fini = sfe4001_fini,
+};
+
+static int sfe4002_init ( struct efab_nic *efab __attribute__((unused)) )
+{
+ return 0;
+}
+static void sfe4002_fini ( struct efab_nic *efab __attribute__((unused)) )
+{
+}
+
+struct efab_board_operations sfe4002_ops = {
+ .init = sfe4002_init,
+ .fini = sfe4002_fini,
+};
+
+static int sfe4003_init ( struct efab_nic *efab __attribute__((unused)) )
+{
+ return 0;
+}
+static void sfe4003_fini ( struct efab_nic *efab __attribute__((unused)) )
+{
+}
+
+struct efab_board_operations sfe4003_ops = {
+ .init = sfe4003_init,
+ .fini = sfe4003_fini,
+};
+
+/*******************************************************************************
+ *
+ *
+ * Hardware initialisation
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_free_special_buffer ( void *p )
+{
+ /* We don't bother cleaning up the buffer table entries -
+ * we're hardly limited */
+ free_dma ( p, EFAB_BUF_ALIGN );
+}
+
+static void*
+falcon_alloc_special_buffer ( struct efab_nic *efab, int bytes,
+ struct efab_special_buffer *entry )
+{
+ void* buffer;
+ int remaining;
+ efab_qword_t buf_desc;
+ unsigned long dma_addr;
+
+ /* Allocate the buffer, aligned on a buffer address boundary */
+ buffer = malloc_dma ( bytes, EFAB_BUF_ALIGN );
+ if ( ! buffer )
+ return NULL;
+
+ /* Push buffer table entries to back the buffer */
+ entry->id = efab->buffer_head;
+ entry->dma_addr = dma_addr = virt_to_bus ( buffer );
+ assert ( ( dma_addr & ( EFAB_BUF_ALIGN - 1 ) ) == 0 );
+
+ remaining = bytes;
+ while ( remaining > 0 ) {
+ EFAB_POPULATE_QWORD_3 ( buf_desc,
+ FCN_IP_DAT_BUF_SIZE, FCN_IP_DAT_BUF_SIZE_4K,
+ FCN_BUF_ADR_FBUF, ( dma_addr >> 12 ),
+ FCN_BUF_OWNER_ID_FBUF, 0 );
+
+ falcon_write_sram ( efab, &buf_desc, efab->buffer_head );
+
+ ++efab->buffer_head;
+ dma_addr += EFAB_BUF_ALIGN;
+ remaining -= EFAB_BUF_ALIGN;
+ }
+
+ EFAB_TRACE ( "Allocated 0x%x bytes at %p backed by buffer table "
+ "entries 0x%x..0x%x\n", bytes, buffer, entry->id,
+ efab->buffer_head - 1 );
+
+ return buffer;
+}
+
+static void
+clear_b0_fpga_memories ( struct efab_nic *efab)
+{
+ efab_oword_t blanko, temp;
+ efab_dword_t blankd;
+ int offset;
+
+ EFAB_ZERO_OWORD ( blanko );
+ EFAB_ZERO_DWORD ( blankd );
+
+ /* Clear the address region register */
+ EFAB_POPULATE_OWORD_4 ( temp,
+ FCN_ADR_REGION0, 0,
+ FCN_ADR_REGION1, ( 1 << 16 ),
+ FCN_ADR_REGION2, ( 2 << 16 ),
+ FCN_ADR_REGION3, ( 3 << 16 ) );
+ falcon_write ( efab, &temp, FCN_ADR_REGION_REG_KER );
+
+ EFAB_TRACE ( "Clearing filter and RSS tables\n" );
+
+ for ( offset = FCN_RX_FILTER_TBL0 ;
+ offset < FCN_RX_RSS_INDIR_TBL_B0+0x800 ;
+ offset += 0x10 ) {
+ falcon_write ( efab, &blanko, offset );
+ }
+
+ EFAB_TRACE ( "Wiping buffer tables\n" );
+
+ /* Notice the 8 byte access mode */
+ for ( offset = 0x2800000 ;
+ offset < 0x3000000 ;
+ offset += 0x8) {
+ _falcon_writel ( efab, 0, offset );
+ _falcon_writel ( efab, 0, offset + 4 );
+ wmb();
+ }
+}
+
+static int
+falcon_reset ( struct efab_nic *efab )
+{
+ efab_oword_t glb_ctl_reg_ker;
+
+ /* Initiate software reset */
+ EFAB_POPULATE_OWORD_6 ( glb_ctl_reg_ker,
+ FCN_PCIE_CORE_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_PCIE_NSTCK_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_PCIE_SD_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_EE_RST_CTL, EXCLUDE_FROM_RESET,
+ FCN_EXT_PHY_RST_DUR, 0x7, /* 10ms */
+ FCN_SWRST, 1 );
+
+ falcon_write ( efab, &glb_ctl_reg_ker, FCN_GLB_CTL_REG_KER );
+
+ /* Allow 50ms for reset */
+ mdelay ( 50 );
+
+ /* Check for device reset complete */
+ falcon_read ( efab, &glb_ctl_reg_ker, FCN_GLB_CTL_REG_KER );
+ if ( EFAB_OWORD_FIELD ( glb_ctl_reg_ker, FCN_SWRST ) != 0 ) {
+ EFAB_ERR ( "Reset failed\n" );
+ return -ETIMEDOUT;
+ }
+
+ if ( ( efab->pci_revision == FALCON_REV_B0 ) && !efab->is_asic ) {
+ clear_b0_fpga_memories ( efab );
+ }
+
+ return 0;
+}
+
+/** Offset of MAC address within EEPROM or Flash */
+#define FALCON_MAC_ADDRESS_OFFSET 0x310
+
+/*
+ * Falcon EEPROM structure
+ */
+#define SF_NV_CONFIG_BASE 0x300
+#define SF_NV_CONFIG_EXTRA 0xA0
+
+struct falcon_nv_config_ver2 {
+ uint16_t nports;
+ uint8_t port0_phy_addr;
+ uint8_t port0_phy_type;
+ uint8_t port1_phy_addr;
+ uint8_t port1_phy_type;
+ uint16_t asic_sub_revision;
+ uint16_t board_revision;
+ uint8_t mac_location;
+};
+
+struct falcon_nv_extra {
+ uint16_t magicnumber;
+ uint16_t structure_version;
+ uint16_t checksum;
+ union {
+ struct falcon_nv_config_ver2 ver2;
+ } ver_specific;
+};
+
+#define BOARD_TYPE(_rev) (_rev >> 8)
+
+static void
+falcon_probe_nic_variant ( struct efab_nic *efab, struct pci_device *pci )
+{
+ efab_oword_t altera_build, nic_stat;
+ int is_pcie, fpga_version;
+ uint8_t revision;
+
+ /* PCI revision */
+ pci_read_config_byte ( pci, PCI_CLASS_REVISION, &revision );
+ efab->pci_revision = revision;
+
+ /* Asic vs FPGA */
+ falcon_read ( efab, &altera_build, FCN_ALTERA_BUILD_REG_KER );
+ fpga_version = EFAB_OWORD_FIELD ( altera_build, FCN_VER_ALL );
+ efab->is_asic = (fpga_version == 0);
+
+ /* MAC and PCI type */
+ falcon_read ( efab, &nic_stat, FCN_NIC_STAT_REG );
+ if ( efab->pci_revision == FALCON_REV_B0 ) {
+ is_pcie = 1;
+ efab->phy_10g = EFAB_OWORD_FIELD ( nic_stat, FCN_STRAP_10G );
+ }
+ else if ( efab->is_asic ) {
+ is_pcie = EFAB_OWORD_FIELD ( nic_stat, FCN_STRAP_PCIE );
+ efab->phy_10g = EFAB_OWORD_FIELD ( nic_stat, FCN_STRAP_10G );
+ }
+ else {
+ int minor = EFAB_OWORD_FIELD ( altera_build, FCN_VER_MINOR );
+ is_pcie = 0;
+ efab->phy_10g = ( minor == 0x14 );
+ }
+}
+
+static void
+falcon_init_spi_device ( struct efab_nic *efab, struct spi_device *spi )
+{
+ /* Falcon's SPI interface only supports reads/writes of up to 16 bytes.
+ * Reduce the nvs block size down to satisfy this - which means callers
+ * should use the nvs_* functions rather than spi_*. */
+ if ( spi->nvs.block_size > FALCON_SPI_MAX_LEN )
+ spi->nvs.block_size = FALCON_SPI_MAX_LEN;
+
+ spi->bus = &efab->spi_bus;
+ efab->spi = spi;
+}
+
+static int
+falcon_probe_spi ( struct efab_nic *efab )
+{
+ efab_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
+ int has_flash, has_eeprom, ad9bit;
+
+ falcon_read ( efab, &nic_stat, FCN_NIC_STAT_REG );
+ falcon_read ( efab, &gpio_ctl, FCN_GPIO_CTL_REG_KER );
+ falcon_read ( efab, &ee_vpd_cfg, FCN_EE_VPD_CFG_REG );
+
+ /* determine if FLASH / EEPROM is present */
+ if ( ( efab->pci_revision >= FALCON_REV_B0 ) || efab->is_asic ) {
+ has_flash = EFAB_OWORD_FIELD ( nic_stat, FCN_SF_PRST );
+ has_eeprom = EFAB_OWORD_FIELD ( nic_stat, FCN_EE_PRST );
+ } else {
+ has_flash = EFAB_OWORD_FIELD ( gpio_ctl, FCN_FLASH_PRESENT );
+ has_eeprom = EFAB_OWORD_FIELD ( gpio_ctl, FCN_EEPROM_PRESENT );
+ }
+ ad9bit = EFAB_OWORD_FIELD ( ee_vpd_cfg, FCN_EE_VPD_EN_AD9_MODE );
+
+ /* Configure the SPI and I2C bus */
+ efab->spi_bus.rw = falcon_spi_rw;
+ init_i2c_bit_basher ( &efab->i2c_bb, &falcon_i2c_bit_ops );
+
+ /* Configure the EEPROM SPI device. Generally, an Atmel 25040
+ * (or similar) is used, but this is only possible if there is also
+ * a flash device present to store the boot-time chip configuration.
+ */
+ if ( has_eeprom ) {
+ if ( has_flash && ad9bit )
+ init_at25040 ( &efab->spi_eeprom );
+ else
+ init_mc25xx640 ( &efab->spi_eeprom );
+ falcon_init_spi_device ( efab, &efab->spi_eeprom );
+ }
+
+ /* Configure the FLASH SPI device */
+ if ( has_flash ) {
+ init_at25f1024 ( &efab->spi_flash );
+ falcon_init_spi_device ( efab, &efab->spi_flash );
+ }
+
+ EFAB_LOG ( "flash is %s, EEPROM is %s%s\n",
+ ( has_flash ? "present" : "absent" ),
+ ( has_eeprom ? "present " : "absent" ),
+ ( has_eeprom ? (ad9bit ? "(9bit)" : "(16bit)") : "") );
+
+ /* The device MUST have flash or eeprom */
+ if ( ! efab->spi ) {
+ EFAB_ERR ( "Device appears to have no flash or eeprom\n" );
+ return -EIO;
+ }
+
+ /* If the device has EEPROM attached, then advertise NVO space */
+ if ( has_eeprom )
+ nvo_init ( &efab->nvo, &efab->spi_eeprom.nvs, falcon_nvo_fragments,
+ &efab->netdev->refcnt );
+
+ return 0;
+}
+
+static int
+falcon_probe_nvram ( struct efab_nic *efab )
+{
+ struct nvs_device *nvs = &efab->spi->nvs;
+ struct falcon_nv_extra nv;
+ int rc, board_revision;
+
+ /* Read the MAC address */
+ rc = nvs_read ( nvs, FALCON_MAC_ADDRESS_OFFSET,
+ efab->mac_addr, ETH_ALEN );
+ if ( rc )
+ return rc;
+
+ /* Poke through the NVRAM structure for the PHY type. */
+ rc = nvs_read ( nvs, SF_NV_CONFIG_BASE + SF_NV_CONFIG_EXTRA,
+ &nv, sizeof ( nv ) );
+ if ( rc )
+ return rc;
+
+ /* Handle each supported NVRAM version */
+ if ( ( le16_to_cpu ( nv.magicnumber ) == FCN_NV_MAGIC_NUMBER ) &&
+ ( le16_to_cpu ( nv.structure_version ) >= 2 ) ) {
+ struct falcon_nv_config_ver2* ver2 = &nv.ver_specific.ver2;
+
+ /* Get the PHY type */
+ efab->phy_addr = le16_to_cpu ( ver2->port0_phy_addr );
+ efab->phy_type = le16_to_cpu ( ver2->port0_phy_type );
+ board_revision = le16_to_cpu ( ver2->board_revision );
+ }
+ else {
+ EFAB_ERR ( "NVram is not recognised\n" );
+ return -EINVAL;
+ }
+
+ efab->board_type = BOARD_TYPE ( board_revision );
+
+ EFAB_TRACE ( "Falcon board %d phy %d @ addr %d\n",
+ efab->board_type, efab->phy_type, efab->phy_addr );
+
+ /* Patch in the board operations */
+ switch ( efab->board_type ) {
+ case EFAB_BOARD_SFE4001:
+ efab->board_op = &sfe4001_ops;
+ break;
+ case EFAB_BOARD_SFE4002:
+ efab->board_op = &sfe4002_ops;
+ break;
+ case EFAB_BOARD_SFE4003:
+ efab->board_op = &sfe4003_ops;
+ break;
+ default:
+ EFAB_ERR ( "Unrecognised board type\n" );
+ return -EINVAL;
+ }
+
+ /* Patch in MAC operations */
+ if ( efab->phy_10g )
+ efab->mac_op = &falcon_xmac_operations;
+ else
+ efab->mac_op = &falcon_gmac_operations;
+
+ /* Hook in the PHY ops */
+ switch ( efab->phy_type ) {
+ case PHY_TYPE_10XPRESS:
+ efab->phy_op = &falcon_tenxpress_phy_ops;
+ break;
+ case PHY_TYPE_CX4:
+ efab->phy_op = &falcon_xaui_phy_ops;
+ break;
+ case PHY_TYPE_XFP:
+ efab->phy_op = &falcon_xfp_phy_ops;
+ break;
+ case PHY_TYPE_CX4_RTMR:
+ efab->phy_op = &falcon_txc_phy_ops;
+ break;
+ case PHY_TYPE_PM8358:
+ efab->phy_op = &falcon_pm8358_phy_ops;
+ break;
+ case PHY_TYPE_1GIG_ALASKA:
+ efab->phy_op = &falcon_alaska_phy_ops;
+ break;
+ default:
+ EFAB_ERR ( "Unknown PHY type: %d\n", efab->phy_type );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+falcon_init_sram ( struct efab_nic *efab )
+{
+ efab_oword_t reg;
+ int count;
+
+ /* use card in internal SRAM mode */
+ falcon_read ( efab, &reg, FCN_NIC_STAT_REG );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_ONCHIP_SRAM, 1 );
+ falcon_write ( efab, &reg, FCN_NIC_STAT_REG );
+
+ /* Deactivate any external SRAM that might be present */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_GPIO1_OEN, 1,
+ FCN_GPIO1_OUT, 1 );
+ falcon_write ( efab, &reg, FCN_GPIO_CTL_REG_KER );
+
+ /* Initiate SRAM reset */
+ EFAB_POPULATE_OWORD_2 ( reg,
+ FCN_SRAM_OOB_BT_INIT_EN, 1,
+ FCN_SRM_NUM_BANKS_AND_BANK_SIZE, 0 );
+ falcon_write ( efab, &reg, FCN_SRM_CFG_REG_KER );
+
+ /* Wait for SRAM reset to complete */
+ count = 0;
+ do {
+ /* SRAM reset is slow; expect around 16ms */
+ mdelay ( 20 );
+
+ /* Check for reset complete */
+ falcon_read ( efab, &reg, FCN_SRM_CFG_REG_KER );
+ if ( !EFAB_OWORD_FIELD ( reg, FCN_SRAM_OOB_BT_INIT_EN ) )
+ return 0;
+ } while (++count < 20); /* wait upto 0.4 sec */
+
+ EFAB_ERR ( "timed out waiting for SRAM reset\n");
+ return -ETIMEDOUT;
+}
+
+static void
+falcon_setup_nic ( struct efab_nic *efab )
+{
+ efab_dword_t timer_cmd;
+ efab_oword_t reg;
+ int tx_fc, xoff_thresh, xon_thresh;
+
+ /* bug5129: Clear the parity enables on the TX data fifos as
+ * they produce false parity errors because of timing issues
+ */
+ falcon_read ( efab, &reg, FCN_SPARE_REG_KER );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_MEM_PERR_EN_TX_DATA, 0 );
+ falcon_write ( efab, &reg, FCN_SPARE_REG_KER );
+
+ /* Set up TX and RX descriptor caches in SRAM */
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_SRM_TX_DC_BASE_ADR, 0x130000 );
+ falcon_write ( efab, &reg, FCN_SRM_TX_DC_CFG_REG_KER );
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_TX_DC_SIZE, 1 /* 16 descriptors */ );
+ falcon_write ( efab, &reg, FCN_TX_DC_CFG_REG_KER );
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_SRM_RX_DC_BASE_ADR, 0x100000 );
+ falcon_write ( efab, &reg, FCN_SRM_RX_DC_CFG_REG_KER );
+ EFAB_POPULATE_OWORD_1 ( reg, FCN_RX_DC_SIZE, 2 /* 32 descriptors */ );
+ falcon_write ( efab, &reg, FCN_RX_DC_CFG_REG_KER );
+
+ /* Set number of RSS CPUs
+ * bug7244: Increase filter depth to reduce RX_RESET likelyhood
+ */
+ EFAB_POPULATE_OWORD_5 ( reg,
+ FCN_NUM_KER, 0,
+ FCN_UDP_FULL_SRCH_LIMIT, 8,
+ FCN_UDP_WILD_SRCH_LIMIT, 8,
+ FCN_TCP_WILD_SRCH_LIMIT, 8,
+ FCN_TCP_FULL_SRCH_LIMIT, 8);
+ falcon_write ( efab, &reg, FCN_RX_FILTER_CTL_REG_KER );
+ udelay ( 1000 );
+
+ /* Setup RX. Wait for descriptor is broken and must
+ * be disabled. RXDP recovery shouldn't be needed, but is.
+ * disable ISCSI parsing because we don't need it
+ */
+ falcon_read ( efab, &reg, FCN_RX_SELF_RST_REG_KER );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_NODESC_WAIT_DIS, 1 );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_RECOVERY_EN, 1 );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_ISCSI_DIS, 1 );
+ falcon_write ( efab, &reg, FCN_RX_SELF_RST_REG_KER );
+
+ /* Determine recommended flow control settings. *
+ * Flow control is qualified on B0 and A1/1G, not on A1/10G */
+ if ( efab->pci_revision == FALCON_REV_B0 ) {
+ tx_fc = 1;
+ xoff_thresh = 54272; /* ~80Kb - 3*max MTU */
+ xon_thresh = 27648; /* ~3*max MTU */
+ }
+ else if ( !efab->phy_10g ) {
+ tx_fc = 1;
+ xoff_thresh = 2048;
+ xon_thresh = 512;
+ }
+ else {
+ tx_fc = xoff_thresh = xon_thresh = 0;
+ }
+
+ /* Setup TX and RX */
+ falcon_read ( efab, &reg, FCN_TX_CFG2_REG_KER );
+ EFAB_SET_OWORD_FIELD ( reg, FCN_TX_DIS_NON_IP_EV, 1 );
+ falcon_write ( efab, &reg, FCN_TX_CFG2_REG_KER );
+
+ falcon_read ( efab, &reg, FCN_RX_CFG_REG_KER );
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_USR_BUF_SIZE,
+ (3*4096) / 32 );
+ if ( efab->pci_revision == FALCON_REV_B0)
+ EFAB_SET_OWORD_FIELD ( reg, FCN_RX_INGR_EN_B0, 1 );
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_XON_MAC_TH,
+ xon_thresh / 256);
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_XOFF_MAC_TH,
+ xoff_thresh / 256);
+ EFAB_SET_OWORD_FIELD_VER ( efab, reg, FCN_RX_XOFF_MAC_EN, tx_fc);
+ falcon_write ( efab, &reg, FCN_RX_CFG_REG_KER );
+
+ /* Set timer register */
+ EFAB_POPULATE_DWORD_2 ( timer_cmd,
+ FCN_TIMER_MODE, FCN_TIMER_MODE_DIS,
+ FCN_TIMER_VAL, 0 );
+ falcon_writel ( efab, &timer_cmd, FCN_TIMER_CMD_REG_KER );
+}
+
+static void
+falcon_init_resources ( struct efab_nic *efab )
+{
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+
+ efab_oword_t reg;
+ int jumbo;
+
+ /* Initialise the ptrs */
+ tx_queue->read_ptr = tx_queue->write_ptr = 0;
+ rx_queue->read_ptr = rx_queue->write_ptr = 0;
+ ev_queue->read_ptr = 0;
+
+ /* Push the event queue to the hardware */
+ EFAB_POPULATE_OWORD_3 ( reg,
+ FCN_EVQ_EN, 1,
+ FCN_EVQ_SIZE, FQS(FCN_EVQ, EFAB_EVQ_SIZE),
+ FCN_EVQ_BUF_BASE_ID, ev_queue->entry.id );
+ falcon_write ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_EVQ_PTR_TBL_KER ) );
+
+ /* Push the tx queue to the hardware */
+ EFAB_POPULATE_OWORD_8 ( reg,
+ FCN_TX_DESCQ_EN, 1,
+ FCN_TX_ISCSI_DDIG_EN, 0,
+ FCN_TX_ISCSI_DDIG_EN, 0,
+ FCN_TX_DESCQ_BUF_BASE_ID, tx_queue->entry.id,
+ FCN_TX_DESCQ_EVQ_ID, 0,
+ FCN_TX_DESCQ_SIZE, FQS(FCN_TX_DESCQ, EFAB_TXD_SIZE),
+ FCN_TX_DESCQ_TYPE, 0 /* kernel queue */,
+ FCN_TX_NON_IP_DROP_DIS_B0, 1 );
+ falcon_write ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+
+ /* Push the rx queue to the hardware */
+ jumbo = ( efab->pci_revision == FALCON_REV_B0 ) ? 0 : 1;
+ EFAB_POPULATE_OWORD_8 ( reg,
+ FCN_RX_ISCSI_DDIG_EN, 0,
+ FCN_RX_ISCSI_HDIG_EN, 0,
+ FCN_RX_DESCQ_BUF_BASE_ID, rx_queue->entry.id,
+ FCN_RX_DESCQ_EVQ_ID, 0,
+ FCN_RX_DESCQ_SIZE, FQS(FCN_RX_DESCQ, EFAB_RXD_SIZE),
+ FCN_RX_DESCQ_TYPE, 0 /* kernel queue */,
+ FCN_RX_DESCQ_JUMBO, jumbo,
+ FCN_RX_DESCQ_EN, 1 );
+ falcon_write ( efab, &reg,
+ FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+
+ /* Program INT_ADR_REG_KER */
+ EFAB_POPULATE_OWORD_1 ( reg,
+ FCN_INT_ADR_KER, virt_to_bus ( &efab->int_ker ) );
+ falcon_write ( efab, &reg, FCN_INT_ADR_REG_KER );
+
+ /* Ack the event queue */
+ falcon_eventq_read_ack ( efab, ev_queue );
+}
+
+static void
+falcon_fini_resources ( struct efab_nic *efab )
+{
+ efab_oword_t cmd;
+
+ /* Disable interrupts */
+ falcon_interrupts ( efab, 0, 0 );
+
+ /* Flush the dma queues */
+ EFAB_POPULATE_OWORD_2 ( cmd,
+ FCN_TX_FLUSH_DESCQ_CMD, 1,
+ FCN_TX_FLUSH_DESCQ, 0 );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+
+ EFAB_POPULATE_OWORD_2 ( cmd,
+ FCN_RX_FLUSH_DESCQ_CMD, 1,
+ FCN_RX_FLUSH_DESCQ, 0 );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+
+ mdelay ( 100 );
+
+ /* Remove descriptor rings from card */
+ EFAB_ZERO_OWORD ( cmd );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_TX_DESC_PTR_TBL_KER ) );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_RX_DESC_PTR_TBL_KER ) );
+ falcon_write ( efab, &cmd,
+ FCN_REVISION_REG ( efab, FCN_EVQ_PTR_TBL_KER ) );
+}
+
+/*******************************************************************************
+ *
+ *
+ * Hardware rx path
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_build_rx_desc ( falcon_rx_desc_t *rxd, struct io_buffer *iob )
+{
+ EFAB_POPULATE_QWORD_2 ( *rxd,
+ FCN_RX_KER_BUF_SIZE, EFAB_RX_BUF_SIZE,
+ FCN_RX_KER_BUF_ADR, virt_to_bus ( iob->data ) );
+}
+
+static void
+falcon_notify_rx_desc ( struct efab_nic *efab, struct efab_rx_queue *rx_queue )
+{
+ efab_dword_t reg;
+ int ptr = rx_queue->write_ptr % EFAB_RXD_SIZE;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_RX_DESC_WPTR_DWORD, ptr );
+ falcon_writel ( efab, &reg, FCN_RX_DESC_UPD_REG_KER_DWORD );
+}
+
+
+/*******************************************************************************
+ *
+ *
+ * Hardware tx path
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_build_tx_desc ( falcon_tx_desc_t *txd, struct io_buffer *iob )
+{
+ EFAB_POPULATE_QWORD_2 ( *txd,
+ FCN_TX_KER_BYTE_CNT, iob_len ( iob ),
+ FCN_TX_KER_BUF_ADR, virt_to_bus ( iob->data ) );
+}
+
+static void
+falcon_notify_tx_desc ( struct efab_nic *efab,
+ struct efab_tx_queue *tx_queue )
+{
+ efab_dword_t reg;
+ int ptr = tx_queue->write_ptr % EFAB_TXD_SIZE;
+
+ EFAB_POPULATE_DWORD_1 ( reg, FCN_TX_DESC_WPTR_DWORD, ptr );
+ falcon_writel ( efab, &reg, FCN_TX_DESC_UPD_REG_KER_DWORD );
+}
+
+
+/*******************************************************************************
+ *
+ *
+ * Software receive interface
+ *
+ *
+ *******************************************************************************/
+
+static int
+efab_fill_rx_queue ( struct efab_nic *efab,
+ struct efab_rx_queue *rx_queue )
+{
+ int fill_level = rx_queue->write_ptr - rx_queue->read_ptr;
+ int space = EFAB_NUM_RX_DESC - fill_level - 1;
+ int pushed = 0;
+
+ while ( space ) {
+ int buf_id = rx_queue->write_ptr % EFAB_NUM_RX_DESC;
+ int desc_id = rx_queue->write_ptr % EFAB_RXD_SIZE;
+ struct io_buffer *iob;
+ falcon_rx_desc_t *rxd;
+
+ assert ( rx_queue->buf[buf_id] == NULL );
+ iob = alloc_iob ( EFAB_RX_BUF_SIZE );
+ if ( !iob )
+ break;
+
+ EFAB_TRACE ( "pushing rx_buf[%d] iob %p data %p\n",
+ buf_id, iob, iob->data );
+
+ rx_queue->buf[buf_id] = iob;
+ rxd = rx_queue->ring + desc_id;
+ falcon_build_rx_desc ( rxd, iob );
+ ++rx_queue->write_ptr;
+ ++pushed;
+ --space;
+ }
+
+ if ( pushed ) {
+ /* Push the ptr to hardware */
+ falcon_notify_rx_desc ( efab, rx_queue );
+
+ fill_level = rx_queue->write_ptr - rx_queue->read_ptr;
+ EFAB_TRACE ( "pushed %d rx buffers to fill level %d\n",
+ pushed, fill_level );
+ }
+
+ if ( fill_level == 0 )
+ return -ENOMEM;
+ return 0;
+}
+
+static void
+efab_receive ( struct efab_nic *efab, unsigned int id, int len, int drop )
+{
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct io_buffer *iob;
+ unsigned int read_ptr = rx_queue->read_ptr % EFAB_RXD_SIZE;
+ unsigned int buf_ptr = rx_queue->read_ptr % EFAB_NUM_RX_DESC;
+
+ assert ( id == read_ptr );
+
+ /* Pop this rx buffer out of the software ring */
+ iob = rx_queue->buf[buf_ptr];
+ rx_queue->buf[buf_ptr] = NULL;
+
+ EFAB_TRACE ( "popping rx_buf[%d] iob %p data %p with %d bytes %s\n",
+ id, iob, iob->data, len, drop ? "bad" : "ok" );
+
+ /* Pass the packet up if required */
+ if ( drop )
+ free_iob ( iob );
+ else {
+ iob_put ( iob, len );
+ netdev_rx ( efab->netdev, iob );
+ }
+
+ ++rx_queue->read_ptr;
+}
+
+/*******************************************************************************
+ *
+ *
+ * Software transmit interface
+ *
+ *
+ *******************************************************************************/
+
+static int
+efab_transmit ( struct net_device *netdev, struct io_buffer *iob )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ int fill_level, space;
+ falcon_tx_desc_t *txd;
+ int buf_id;
+
+ fill_level = tx_queue->write_ptr - tx_queue->read_ptr;
+ space = EFAB_TXD_SIZE - fill_level - 1;
+ if ( space < 1 )
+ return -ENOBUFS;
+
+ /* Save the iobuffer for later completion */
+ buf_id = tx_queue->write_ptr % EFAB_TXD_SIZE;
+ assert ( tx_queue->buf[buf_id] == NULL );
+ tx_queue->buf[buf_id] = iob;
+
+ EFAB_TRACE ( "tx_buf[%d] for iob %p data %p len %zd\n",
+ buf_id, iob, iob->data, iob_len ( iob ) );
+
+ /* Form the descriptor, and push it to hardware */
+ txd = tx_queue->ring + buf_id;
+ falcon_build_tx_desc ( txd, iob );
+ ++tx_queue->write_ptr;
+ falcon_notify_tx_desc ( efab, tx_queue );
+
+ return 0;
+}
+
+static int
+efab_transmit_done ( struct efab_nic *efab, int id )
+{
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ unsigned int read_ptr, stop;
+
+ /* Complete all buffers from read_ptr up to and including id */
+ read_ptr = tx_queue->read_ptr % EFAB_TXD_SIZE;
+ stop = ( id + 1 ) % EFAB_TXD_SIZE;
+
+ while ( read_ptr != stop ) {
+ struct io_buffer *iob = tx_queue->buf[read_ptr];
+ assert ( iob );
+
+ /* Complete the tx buffer */
+ if ( iob )
+ netdev_tx_complete ( efab->netdev, iob );
+ tx_queue->buf[read_ptr] = NULL;
+
+ ++tx_queue->read_ptr;
+ read_ptr = tx_queue->read_ptr % EFAB_TXD_SIZE;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ *
+ *
+ * Hardware event path
+ *
+ *
+ *******************************************************************************/
+
+static void
+falcon_clear_interrupts ( struct efab_nic *efab )
+{
+ efab_dword_t reg;
+
+ if ( efab->pci_revision == FALCON_REV_B0 ) {
+ /* read the ISR */
+ falcon_readl( efab, &reg, INT_ISR0_B0 );
+ }
+ else {
+ /* write to the INT_ACK register */
+ falcon_writel ( efab, 0, FCN_INT_ACK_KER_REG_A1 );
+ mb();
+ falcon_readl ( efab, &reg,
+ WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 );
+ }
+}
+
+static void
+falcon_handle_event ( struct efab_nic *efab, falcon_event_t *evt )
+{
+ int ev_code, desc_ptr, len, drop;
+
+ /* Decode event */
+ ev_code = EFAB_QWORD_FIELD ( *evt, FCN_EV_CODE );
+ switch ( ev_code ) {
+ case FCN_TX_IP_EV_DECODE:
+ desc_ptr = EFAB_QWORD_FIELD ( *evt, FCN_TX_EV_DESC_PTR );
+ efab_transmit_done ( efab, desc_ptr );
+ break;
+
+ case FCN_RX_IP_EV_DECODE:
+ desc_ptr = EFAB_QWORD_FIELD ( *evt, FCN_RX_EV_DESC_PTR );
+ len = EFAB_QWORD_FIELD ( *evt, FCN_RX_EV_BYTE_CNT );
+ drop = !EFAB_QWORD_FIELD ( *evt, FCN_RX_EV_PKT_OK );
+
+ efab_receive ( efab, desc_ptr, len, drop );
+ break;
+
+ default:
+ EFAB_TRACE ( "Unknown event type %d\n", ev_code );
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ *
+ * Software (polling) interrupt handler
+ *
+ *
+ *******************************************************************************/
+
+static void
+efab_poll ( struct net_device *netdev )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ falcon_event_t *evt;
+
+ /* Read the event queue by directly looking for events
+ * (we don't even bother to read the eventq write ptr) */
+ evt = ev_queue->ring + ev_queue->read_ptr;
+ while ( falcon_event_present ( evt ) ) {
+
+ EFAB_TRACE ( "Event at index 0x%x address %p is "
+ EFAB_QWORD_FMT "\n", ev_queue->read_ptr,
+ evt, EFAB_QWORD_VAL ( *evt ) );
+
+ falcon_handle_event ( efab, evt );
+
+ /* Clear the event */
+ EFAB_SET_QWORD ( *evt );
+
+ /* Move to the next event. We don't ack the event
+ * queue until the end */
+ ev_queue->read_ptr = ( ( ev_queue->read_ptr + 1 ) %
+ EFAB_EVQ_SIZE );
+ evt = ev_queue->ring + ev_queue->read_ptr;
+ }
+
+ /* Push more buffers if needed */
+ (void) efab_fill_rx_queue ( efab, rx_queue );
+
+ /* Clear any pending interrupts */
+ falcon_clear_interrupts ( efab );
+
+ /* Ack the event queue */
+ falcon_eventq_read_ack ( efab, ev_queue );
+}
+
+static void
+efab_irq ( struct net_device *netdev, int enable )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+
+ switch ( enable ) {
+ case 0:
+ falcon_interrupts ( efab, 0, 0 );
+ break;
+ case 1:
+ falcon_interrupts ( efab, 1, 0 );
+ falcon_eventq_read_ack ( efab, ev_queue );
+ break;
+ case 2:
+ falcon_interrupts ( efab, 1, 1 );
+ break;
+ }
+}
+
+/*******************************************************************************
+ *
+ *
+ * Software open/close
+ *
+ *
+ *******************************************************************************/
+
+static void
+efab_free_resources ( struct efab_nic *efab )
+{
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ int i;
+
+ for ( i = 0; i < EFAB_NUM_RX_DESC; i++ ) {
+ if ( rx_queue->buf[i] )
+ free_iob ( rx_queue->buf[i] );
+ }
+
+ for ( i = 0; i < EFAB_TXD_SIZE; i++ ) {
+ if ( tx_queue->buf[i] )
+ netdev_tx_complete ( efab->netdev, tx_queue->buf[i] );
+ }
+
+ if ( rx_queue->ring )
+ falcon_free_special_buffer ( rx_queue->ring );
+
+ if ( tx_queue->ring )
+ falcon_free_special_buffer ( tx_queue->ring );
+
+ if ( ev_queue->ring )
+ falcon_free_special_buffer ( ev_queue->ring );
+
+ memset ( rx_queue, 0, sizeof ( *rx_queue ) );
+ memset ( tx_queue, 0, sizeof ( *tx_queue ) );
+ memset ( ev_queue, 0, sizeof ( *ev_queue ) );
+
+ /* Ensure subsequent buffer allocations start at id 0 */
+ efab->buffer_head = 0;
+}
+
+static int
+efab_alloc_resources ( struct efab_nic *efab )
+{
+ struct efab_ev_queue *ev_queue = &efab->ev_queue;
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ struct efab_tx_queue *tx_queue = &efab->tx_queue;
+ size_t bytes;
+
+ /* Allocate the hardware event queue */
+ bytes = sizeof ( falcon_event_t ) * EFAB_TXD_SIZE;
+ ev_queue->ring = falcon_alloc_special_buffer ( efab, bytes,
+ &ev_queue->entry );
+ if ( !ev_queue->ring )
+ goto fail1;
+
+ /* Initialise the hardware event queue */
+ memset ( ev_queue->ring, 0xff, bytes );
+
+ /* Allocate the hardware tx queue */
+ bytes = sizeof ( falcon_tx_desc_t ) * EFAB_TXD_SIZE;
+ tx_queue->ring = falcon_alloc_special_buffer ( efab, bytes,
+ &tx_queue->entry );
+ if ( ! tx_queue->ring )
+ goto fail2;
+
+ /* Allocate the hardware rx queue */
+ bytes = sizeof ( falcon_rx_desc_t ) * EFAB_RXD_SIZE;
+ rx_queue->ring = falcon_alloc_special_buffer ( efab, bytes,
+ &rx_queue->entry );
+ if ( ! rx_queue->ring )
+ goto fail3;
+
+ return 0;
+
+fail3:
+ falcon_free_special_buffer ( tx_queue->ring );
+ tx_queue->ring = NULL;
+fail2:
+ falcon_free_special_buffer ( ev_queue->ring );
+ ev_queue->ring = NULL;
+fail1:
+ return -ENOMEM;
+}
+
+static int
+efab_init_mac ( struct efab_nic *efab )
+{
+ int count, rc;
+
+ /* This can take several seconds */
+ EFAB_LOG ( "Waiting for link..\n" );
+ for ( count=0; count<5; count++ ) {
+ rc = efab->mac_op->init ( efab );
+ if ( rc ) {
+ EFAB_ERR ( "Failed reinitialising MAC, error %s\n",
+ strerror ( rc ));
+ return rc;
+ }
+
+ /* Sleep for 2s to wait for the link to settle, either
+ * because we want to use it, or because we're about
+ * to reset the mac anyway
+ */
+ sleep ( 2 );
+
+ if ( ! efab->link_up ) {
+ EFAB_ERR ( "!\n" );
+ continue;
+ }
+
+ EFAB_LOG ( "\n%dMbps %s-duplex\n",
+ ( efab->link_options & LPA_EF_10000 ? 10000 :
+ ( efab->link_options & LPA_EF_1000 ? 1000 :
+ ( efab->link_options & LPA_100 ? 100 : 10 ) ) ),
+ ( efab->link_options & LPA_EF_DUPLEX ?
+ "full" : "half" ) );
+
+ /* TODO: Move link state handling to the poll() routine */
+ netdev_link_up ( efab->netdev );
+ return 0;
+ }
+
+ EFAB_ERR ( "timed initialising MAC\n" );
+ return -ETIMEDOUT;
+}
+
+static void
+efab_close ( struct net_device *netdev )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+
+ falcon_fini_resources ( efab );
+ efab_free_resources ( efab );
+ efab->board_op->fini ( efab );
+ falcon_reset ( efab );
+}
+
+static int
+efab_open ( struct net_device *netdev )
+{
+ struct efab_nic *efab = netdev_priv ( netdev );
+ struct efab_rx_queue *rx_queue = &efab->rx_queue;
+ int rc;
+
+ rc = falcon_reset ( efab );
+ if ( rc )
+ goto fail1;
+
+ rc = efab->board_op->init ( efab );
+ if ( rc )
+ goto fail2;
+
+ rc = falcon_init_sram ( efab );
+ if ( rc )
+ goto fail3;
+
+ /* Configure descriptor caches before pushing hardware queues */
+ falcon_setup_nic ( efab );
+
+ rc = efab_alloc_resources ( efab );
+ if ( rc )
+ goto fail4;
+
+ falcon_init_resources ( efab );
+
+ /* Push rx buffers */
+ rc = efab_fill_rx_queue ( efab, rx_queue );
+ if ( rc )
+ goto fail5;
+
+ /* Try and bring the interface up */
+ rc = efab_init_mac ( efab );
+ if ( rc )
+ goto fail6;
+
+ return 0;
+
+fail6:
+fail5:
+ efab_free_resources ( efab );
+fail4:
+fail3:
+ efab->board_op->fini ( efab );
+fail2:
+ falcon_reset ( efab );
+fail1:
+ return rc;
+}
+
+static struct net_device_operations efab_operations = {
+ .open = efab_open,
+ .close = efab_close,
+ .transmit = efab_transmit,
+ .poll = efab_poll,
+ .irq = efab_irq,
+};
+
+static void
+efab_remove ( struct pci_device *pci )
+{
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct efab_nic *efab = netdev_priv ( netdev );
+
+ if ( efab->membase ) {
+ falcon_reset ( efab );
+
+ iounmap ( efab->membase );
+ efab->membase = NULL;
+ }
+
+ if ( efab->nvo.nvs ) {
+ unregister_nvo ( &efab->nvo );
+ efab->nvo.nvs = NULL;
+ }
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static int
+efab_probe ( struct pci_device *pci,
+ const struct pci_device_id *id )
+{
+ struct net_device *netdev;
+ struct efab_nic *efab;
+ unsigned long mmio_start, mmio_len;
+ int rc;
+
+ /* Create the network adapter */
+ netdev = alloc_etherdev ( sizeof ( struct efab_nic ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto fail1;
+ }
+
+ /* Initialise the network adapter, and initialise private storage */
+ netdev_init ( netdev, &efab_operations );
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+
+ efab = netdev_priv ( netdev );
+ memset ( efab, 0, sizeof ( *efab ) );
+ efab->netdev = netdev;
+
+ /* Get iobase/membase */
+ mmio_start = pci_bar_start ( pci, PCI_BASE_ADDRESS_2 );
+ mmio_len = pci_bar_size ( pci, PCI_BASE_ADDRESS_2 );
+ efab->membase = ioremap ( mmio_start, mmio_len );
+ EFAB_TRACE ( "BAR of %lx bytes at phys %lx mapped at %p\n",
+ mmio_len, mmio_start, efab->membase );
+
+ /* Enable the PCI device */
+ adjust_pci_device ( pci );
+ efab->iobase = pci->ioaddr & ~3;
+
+ /* Determine the NIC variant */
+ falcon_probe_nic_variant ( efab, pci );
+
+ /* Read the SPI interface and determine the MAC address,
+ * and the board and phy variant. Hook in the op tables */
+ rc = falcon_probe_spi ( efab );
+ if ( rc )
+ goto fail2;
+ rc = falcon_probe_nvram ( efab );
+ if ( rc )
+ goto fail3;
+
+ memcpy ( netdev->hw_addr, efab->mac_addr, ETH_ALEN );
+
+ netdev_link_up ( netdev );
+ rc = register_netdev ( netdev );
+ if ( rc )
+ goto fail4;
+
+ /* Advertise non-volatile storage */
+ if ( efab->nvo.nvs ) {
+ rc = register_nvo ( &efab->nvo, netdev_settings ( netdev ) );
+ if ( rc )
+ goto fail5;
+ }
+
+ EFAB_LOG ( "Found %s EtherFabric %s %s revision %d\n", id->name,
+ efab->is_asic ? "ASIC" : "FPGA",
+ efab->phy_10g ? "10G" : "1G",
+ efab->pci_revision );
+
+ return 0;
+
+fail5:
+ unregister_netdev ( netdev );
+fail4:
+fail3:
+fail2:
+ iounmap ( efab->membase );
+ efab->membase = NULL;
+ netdev_put ( netdev );
+fail1:
+ return rc;
+}
+
+
+static struct pci_device_id efab_nics[] = {
+ PCI_ROM(0x1924, 0x0703, "falcon", "EtherFabric Falcon", 0),
+ PCI_ROM(0x1924, 0x0710, "falconb0", "EtherFabric FalconB0", 0),
+};
+
+struct pci_driver etherfabric_driver __pci_driver = {
+ .ids = efab_nics,
+ .id_count = sizeof ( efab_nics ) / sizeof ( efab_nics[0] ),
+ .probe = efab_probe,
+ .remove = efab_remove,
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.h
new file mode 100644
index 0000000..9657eb7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric.h
@@ -0,0 +1,553 @@
+/**************************************************************************
+ *
+ * GPL net driver for Level 5 Etherfabric network cards
+ *
+ * Written by Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Copyright Fen Systems Ltd. 2005
+ * Copyright Level 5 Networks Inc. 2005
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice. This file is not a complete program and may only be used
+ * when the entire operating system is licensed under the GPL.
+ *
+ **************************************************************************
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef EFAB_BITFIELD_H
+#define EFAB_BITFIELD_H
+
+/** @file
+ *
+ * Etherfabric bitfield access
+ *
+ * Etherfabric NICs make extensive use of bitfields up to 128 bits
+ * wide. Since there is no native 128-bit datatype on most systems,
+ * and since 64-bit datatypes are inefficient on 32-bit systems and
+ * vice versa, we wrap accesses in a way that uses the most efficient
+ * datatype.
+ *
+ * The NICs are PCI devices and therefore little-endian. Since most
+ * of the quantities that we deal with are DMAed to/from host memory,
+ * we define our datatypes (efab_oword_t, efab_qword_t and
+ * efab_dword_t) to be little-endian.
+ *
+ * In the less common case of using PIO for individual register
+ * writes, we construct the little-endian datatype in host memory and
+ * then use non-swapping equivalents of writel/writeq, rather than
+ * constructing a native-endian datatype and relying on the implicit
+ * byte-swapping done by writel/writeq. (We use a similar strategy
+ * for register reads.)
+ */
+
+/** Dummy field low bit number */
+#define EFAB_DUMMY_FIELD_LBN 0
+/** Dummy field width */
+#define EFAB_DUMMY_FIELD_WIDTH 0
+/** Dword 0 low bit number */
+#define EFAB_DWORD_0_LBN 0
+/** Dword 0 width */
+#define EFAB_DWORD_0_WIDTH 32
+/** Dword 1 low bit number */
+#define EFAB_DWORD_1_LBN 32
+/** Dword 1 width */
+#define EFAB_DWORD_1_WIDTH 32
+/** Dword 2 low bit number */
+#define EFAB_DWORD_2_LBN 64
+/** Dword 2 width */
+#define EFAB_DWORD_2_WIDTH 32
+/** Dword 3 low bit number */
+#define EFAB_DWORD_3_LBN 96
+/** Dword 3 width */
+#define EFAB_DWORD_3_WIDTH 32
+
+/** Specified attribute (e.g. LBN) of the specified field */
+#define EFAB_VAL(field,attribute) field ## _ ## attribute
+/** Low bit number of the specified field */
+#define EFAB_LOW_BIT( field ) EFAB_VAL ( field, LBN )
+/** Bit width of the specified field */
+#define EFAB_WIDTH( field ) EFAB_VAL ( field, WIDTH )
+/** High bit number of the specified field */
+#define EFAB_HIGH_BIT(field) ( EFAB_LOW_BIT(field) + EFAB_WIDTH(field) - 1 )
+/** Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 64 bits.
+ */
+#define EFAB_MASK64( field ) \
+ ( EFAB_WIDTH(field) == 64 ? ~( ( uint64_t ) 0 ) : \
+ ( ( ( ( ( uint64_t ) 1 ) << EFAB_WIDTH(field) ) ) - 1 ) )
+
+/** Mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ *
+ * The maximum width mask that can be generated is 32 bits. Use
+ * EFAB_MASK64 for higher width fields.
+ */
+#define EFAB_MASK32( field ) \
+ ( EFAB_WIDTH(field) == 32 ? ~( ( uint32_t ) 0 ) : \
+ ( ( ( ( ( uint32_t ) 1 ) << EFAB_WIDTH(field) ) ) - 1 ) )
+
+/** A doubleword (i.e. 4 byte) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efab_dword {
+ uint32_t u32[1];
+ uint32_t opaque; /* For bitwise operations between two efab_dwords */
+} efab_dword_t;
+
+/** A quadword (i.e. 8 byte) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efab_qword {
+ uint64_t u64[1];
+ uint32_t u32[2];
+ efab_dword_t dword[2];
+} efab_qword_t;
+
+/**
+ * An octword (eight-word, i.e. 16 byte) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efab_oword {
+ uint64_t u64[2];
+ efab_qword_t qword[2];
+ uint32_t u32[4];
+ efab_dword_t dword[4];
+} efab_oword_t;
+
+/** Format string for printing an efab_dword_t */
+#define EFAB_DWORD_FMT "%08x"
+
+/** Format string for printing an efab_qword_t */
+#define EFAB_QWORD_FMT "%08x:%08x"
+
+/** Format string for printing an efab_oword_t */
+#define EFAB_OWORD_FMT "%08x:%08x:%08x:%08x"
+
+/** printk parameters for printing an efab_dword_t */
+#define EFAB_DWORD_VAL(dword) \
+ ( ( unsigned int ) le32_to_cpu ( (dword).u32[0] ) )
+
+/** printk parameters for printing an efab_qword_t */
+#define EFAB_QWORD_VAL(qword) \
+ ( ( unsigned int ) le32_to_cpu ( (qword).u32[1] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (qword).u32[0] ) )
+
+/** printk parameters for printing an efab_oword_t */
+#define EFAB_OWORD_VAL(oword) \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[3] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[2] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[1] ) ), \
+ ( ( unsigned int ) le32_to_cpu ( (oword).u32[0] ) )
+
+/**
+ * Extract bit field portion [low,high) from the native-endian element
+ * which contains bits [min,max).
+ *
+ * For example, suppose "element" represents the high 32 bits of a
+ * 64-bit value, and we wish to extract the bits belonging to the bit
+ * field occupying bits 28-45 of this 64-bit value.
+ *
+ * Then EFAB_EXTRACT ( element, 32, 63, 28, 45 ) would give
+ *
+ * ( element ) << 4
+ *
+ * The result will contain the relevant bits filled in in the range
+ * [0,high-low), with garbage in bits [high-low+1,...).
+ */
+#define EFAB_EXTRACT_NATIVE( native_element, min ,max ,low ,high ) \
+ ( ( ( low > max ) || ( high < min ) ) ? 0 : \
+ ( ( low > min ) ? \
+ ( (native_element) >> ( low - min ) ) : \
+ ( (native_element) << ( min - low ) ) ) )
+
+/**
+ * Extract bit field portion [low,high) from the 64-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EFAB_EXTRACT64( element, min, max, low, high ) \
+ EFAB_EXTRACT_NATIVE ( le64_to_cpu(element), min, max, low, high )
+
+/**
+ * Extract bit field portion [low,high) from the 32-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define EFAB_EXTRACT32( element, min, max, low, high ) \
+ EFAB_EXTRACT_NATIVE ( le32_to_cpu(element), min, max, low, high )
+
+#define EFAB_EXTRACT_OWORD64( oword, low, high ) \
+ ( EFAB_EXTRACT64 ( (oword).u64[0], 0, 63, low, high ) | \
+ EFAB_EXTRACT64 ( (oword).u64[1], 64, 127, low, high ) )
+
+#define EFAB_EXTRACT_QWORD64( qword, low, high ) \
+ ( EFAB_EXTRACT64 ( (qword).u64[0], 0, 63, low, high ) )
+
+#define EFAB_EXTRACT_OWORD32( oword, low, high ) \
+ ( EFAB_EXTRACT32 ( (oword).u32[0], 0, 31, low, high ) | \
+ EFAB_EXTRACT32 ( (oword).u32[1], 32, 63, low, high ) | \
+ EFAB_EXTRACT32 ( (oword).u32[2], 64, 95, low, high ) | \
+ EFAB_EXTRACT32 ( (oword).u32[3], 96, 127, low, high ) )
+
+#define EFAB_EXTRACT_QWORD32( qword, low, high ) \
+ ( EFAB_EXTRACT32 ( (qword).u32[0], 0, 31, low, high ) | \
+ EFAB_EXTRACT32 ( (qword).u32[1], 32, 63, low, high ) )
+
+#define EFAB_EXTRACT_DWORD( dword, low, high ) \
+ ( EFAB_EXTRACT32 ( (dword).u32[0], 0, 31, low, high ) )
+
+#define EFAB_OWORD_FIELD64( oword, field ) \
+ ( EFAB_EXTRACT_OWORD64 ( oword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK64 ( field ) )
+
+#define EFAB_QWORD_FIELD64( qword, field ) \
+ ( EFAB_EXTRACT_QWORD64 ( qword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK64 ( field ) )
+
+#define EFAB_OWORD_FIELD32( oword, field ) \
+ ( EFAB_EXTRACT_OWORD32 ( oword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK32 ( field ) )
+
+#define EFAB_QWORD_FIELD32( qword, field ) \
+ ( EFAB_EXTRACT_QWORD32 ( qword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK32 ( field ) )
+
+#define EFAB_DWORD_FIELD( dword, field ) \
+ ( EFAB_EXTRACT_DWORD ( dword, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ) ) & \
+ EFAB_MASK32 ( field ) )
+
+#define EFAB_OWORD_IS_ZERO64( oword ) \
+ ( ! ( (oword).u64[0] || (oword).u64[1] ) )
+
+#define EFAB_QWORD_IS_ZERO64( qword ) \
+ ( ! ( (qword).u64[0] ) )
+
+#define EFAB_OWORD_IS_ZERO32( oword ) \
+ ( ! ( (oword).u32[0] || (oword).u32[1] || \
+ (oword).u32[2] || (oword).u32[3] ) )
+
+#define EFAB_QWORD_IS_ZERO32( qword ) \
+ ( ! ( (qword).u32[0] || (qword).u32[1] ) )
+
+#define EFAB_DWORD_IS_ZERO( dword ) \
+ ( ! ( (dword).u32[0] ) )
+
+#define EFAB_OWORD_IS_ALL_ONES64( oword ) \
+ ( ( (oword).u64[0] & (oword).u64[1] ) == ~( ( uint64_t ) 0 ) )
+
+#define EFAB_QWORD_IS_ALL_ONES64( qword ) \
+ ( (qword).u64[0] == ~( ( uint64_t ) 0 ) )
+
+#define EFAB_OWORD_IS_ALL_ONES32( oword ) \
+ ( ( (oword).u32[0] & (oword).u32[1] & \
+ (oword).u32[2] & (oword).u32[3] ) == ~( ( uint32_t ) 0 ) )
+
+#define EFAB_QWORD_IS_ALL_ONES32( qword ) \
+ ( ( (qword).u32[0] & (qword).u32[1] ) == ~( ( uint32_t ) 0 ) )
+
+#define EFAB_DWORD_IS_ALL_ONES( dword ) \
+ ( (dword).u32[0] == ~( ( uint32_t ) 0 ) )
+
+#if ( BITS_PER_LONG == 64 )
+#define EFAB_OWORD_FIELD EFAB_OWORD_FIELD64
+#define EFAB_QWORD_FIELD EFAB_QWORD_FIELD64
+#define EFAB_OWORD_IS_ZERO EFAB_OWORD_IS_ZERO64
+#define EFAB_QWORD_IS_ZERO EFAB_QWORD_IS_ZERO64
+#define EFAB_OWORD_IS_ALL_ONES EFAB_OWORD_IS_ALL_ONES64
+#define EFAB_QWORD_IS_ALL_ONES EFAB_QWORD_IS_ALL_ONES64
+#else
+#define EFAB_OWORD_FIELD EFAB_OWORD_FIELD32
+#define EFAB_QWORD_FIELD EFAB_QWORD_FIELD32
+#define EFAB_OWORD_IS_ZERO EFAB_OWORD_IS_ZERO32
+#define EFAB_QWORD_IS_ZERO EFAB_QWORD_IS_ZERO32
+#define EFAB_OWORD_IS_ALL_ONES EFAB_OWORD_IS_ALL_ONES32
+#define EFAB_QWORD_IS_ALL_ONES EFAB_QWORD_IS_ALL_ONES32
+#endif
+
+/**
+ * Construct bit field portion
+ *
+ * Creates the portion of the bit field [low,high) that lies within
+ * the range [min,max).
+ */
+#define EFAB_INSERT_NATIVE64( min, max, low, high, value ) \
+ ( ( ( low > max ) || ( high < min ) ) ? 0 : \
+ ( ( low > min ) ? \
+ ( ( ( uint64_t ) (value) ) << ( low - min ) ) : \
+ ( ( ( uint64_t ) (value) ) >> ( min - low ) ) ) )
+
+#define EFAB_INSERT_NATIVE32( min, max, low, high, value ) \
+ ( ( ( low > max ) || ( high < min ) ) ? 0 : \
+ ( ( low > min ) ? \
+ ( ( ( uint32_t ) (value) ) << ( low - min ) ) : \
+ ( ( ( uint32_t ) (value) ) >> ( min - low ) ) ) )
+
+#define EFAB_INSERT_NATIVE( min, max, low, high, value ) \
+ ( ( ( ( max - min ) >= 32 ) || \
+ ( ( high - low ) >= 32 ) ) \
+ ? EFAB_INSERT_NATIVE64 ( min, max, low, high, value ) \
+ : EFAB_INSERT_NATIVE32 ( min, max, low, high, value ) )
+
+/**
+ * Construct bit field portion
+ *
+ * Creates the portion of the named bit field that lies within the
+ * range [min,max).
+ */
+#define EFAB_INSERT_FIELD_NATIVE( min, max, field, value ) \
+ EFAB_INSERT_NATIVE ( min, max, EFAB_LOW_BIT ( field ), \
+ EFAB_HIGH_BIT ( field ), value )
+
+/**
+ * Construct bit field
+ *
+ * Creates the portion of the named bit fields that lie within the
+ * range [min,max).
+ */
+#define EFAB_INSERT_FIELDS_NATIVE( min, max, \
+ field1, value1, \
+ field2, value2, \
+ field3, value3, \
+ field4, value4, \
+ field5, value5, \
+ field6, value6, \
+ field7, value7, \
+ field8, value8, \
+ field9, value9, \
+ field10, value10 ) \
+ ( EFAB_INSERT_FIELD_NATIVE ( min, max, field1, value1 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field2, value2 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field3, value3 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field4, value4 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field5, value5 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field6, value6 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field7, value7 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field8, value8 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field9, value9 ) | \
+ EFAB_INSERT_FIELD_NATIVE ( min, max, field10, value10 ) )
+
+#define EFAB_INSERT_FIELDS64( ... ) \
+ cpu_to_le64 ( EFAB_INSERT_FIELDS_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_INSERT_FIELDS32( ... ) \
+ cpu_to_le32 ( EFAB_INSERT_FIELDS_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_POPULATE_OWORD64( oword, ... ) do { \
+ (oword).u64[0] = EFAB_INSERT_FIELDS64 ( 0, 63, __VA_ARGS__ );\
+ (oword).u64[1] = EFAB_INSERT_FIELDS64 ( 64, 127, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_QWORD64( qword, ... ) do { \
+ (qword).u64[0] = EFAB_INSERT_FIELDS64 ( 0, 63, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_OWORD32( oword, ... ) do { \
+ (oword).u32[0] = EFAB_INSERT_FIELDS32 ( 0, 31, __VA_ARGS__ );\
+ (oword).u32[1] = EFAB_INSERT_FIELDS32 ( 32, 63, __VA_ARGS__ );\
+ (oword).u32[2] = EFAB_INSERT_FIELDS32 ( 64, 95, __VA_ARGS__ );\
+ (oword).u32[3] = EFAB_INSERT_FIELDS32 ( 96, 127, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_QWORD32( qword, ... ) do { \
+ (qword).u32[0] = EFAB_INSERT_FIELDS32 ( 0, 31, __VA_ARGS__ );\
+ (qword).u32[1] = EFAB_INSERT_FIELDS32 ( 32, 63, __VA_ARGS__ );\
+ } while ( 0 )
+
+#define EFAB_POPULATE_DWORD( dword, ... ) do { \
+ (dword).u32[0] = EFAB_INSERT_FIELDS32 ( 0, 31, __VA_ARGS__ );\
+ } while ( 0 )
+
+#if ( BITS_PER_LONG == 64 )
+#define EFAB_POPULATE_OWORD EFAB_POPULATE_OWORD64
+#define EFAB_POPULATE_QWORD EFAB_POPULATE_QWORD64
+#else
+#define EFAB_POPULATE_OWORD EFAB_POPULATE_OWORD32
+#define EFAB_POPULATE_QWORD EFAB_POPULATE_QWORD32
+#endif
+
+/* Populate an octword field with various numbers of arguments */
+#define EFAB_POPULATE_OWORD_10 EFAB_POPULATE_OWORD
+#define EFAB_POPULATE_OWORD_9( oword, ... ) \
+ EFAB_POPULATE_OWORD_10 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_8( oword, ... ) \
+ EFAB_POPULATE_OWORD_9 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_7( oword, ... ) \
+ EFAB_POPULATE_OWORD_8 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_6( oword, ... ) \
+ EFAB_POPULATE_OWORD_7 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_5( oword, ... ) \
+ EFAB_POPULATE_OWORD_6 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_4( oword, ... ) \
+ EFAB_POPULATE_OWORD_5 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_3( oword, ... ) \
+ EFAB_POPULATE_OWORD_4 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_2( oword, ... ) \
+ EFAB_POPULATE_OWORD_3 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_OWORD_1( oword, ... ) \
+ EFAB_POPULATE_OWORD_2 ( oword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_ZERO_OWORD( oword ) \
+ EFAB_POPULATE_OWORD_1 ( oword, EFAB_DUMMY_FIELD, 0 )
+#define EFAB_SET_OWORD( oword ) \
+ EFAB_POPULATE_OWORD_4 ( oword, \
+ EFAB_DWORD_0, 0xffffffff, \
+ EFAB_DWORD_1, 0xffffffff, \
+ EFAB_DWORD_2, 0xffffffff, \
+ EFAB_DWORD_3, 0xffffffff )
+
+/* Populate a quadword field with various numbers of arguments */
+#define EFAB_POPULATE_QWORD_10 EFAB_POPULATE_QWORD
+#define EFAB_POPULATE_QWORD_9( qword, ... ) \
+ EFAB_POPULATE_QWORD_10 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_8( qword, ... ) \
+ EFAB_POPULATE_QWORD_9 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_7( qword, ... ) \
+ EFAB_POPULATE_QWORD_8 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_6( qword, ... ) \
+ EFAB_POPULATE_QWORD_7 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_5( qword, ... ) \
+ EFAB_POPULATE_QWORD_6 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_4( qword, ... ) \
+ EFAB_POPULATE_QWORD_5 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_3( qword, ... ) \
+ EFAB_POPULATE_QWORD_4 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_2( qword, ... ) \
+ EFAB_POPULATE_QWORD_3 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_QWORD_1( qword, ... ) \
+ EFAB_POPULATE_QWORD_2 ( qword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_ZERO_QWORD( qword ) \
+ EFAB_POPULATE_QWORD_1 ( qword, EFAB_DUMMY_FIELD, 0 )
+#define EFAB_SET_QWORD( qword ) \
+ EFAB_POPULATE_QWORD_2 ( qword, \
+ EFAB_DWORD_0, 0xffffffff, \
+ EFAB_DWORD_1, 0xffffffff )
+
+/* Populate a dword field with various numbers of arguments */
+#define EFAB_POPULATE_DWORD_10 EFAB_POPULATE_DWORD
+#define EFAB_POPULATE_DWORD_9( dword, ... ) \
+ EFAB_POPULATE_DWORD_10 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_8( dword, ... ) \
+ EFAB_POPULATE_DWORD_9 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_7( dword, ... ) \
+ EFAB_POPULATE_DWORD_8 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_6( dword, ... ) \
+ EFAB_POPULATE_DWORD_7 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_5( dword, ... ) \
+ EFAB_POPULATE_DWORD_6 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_4( dword, ... ) \
+ EFAB_POPULATE_DWORD_5 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_3( dword, ... ) \
+ EFAB_POPULATE_DWORD_4 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_2( dword, ... ) \
+ EFAB_POPULATE_DWORD_3 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_POPULATE_DWORD_1( dword, ... ) \
+ EFAB_POPULATE_DWORD_2 ( dword, EFAB_DUMMY_FIELD, 0, __VA_ARGS__ )
+#define EFAB_ZERO_DWORD( dword ) \
+ EFAB_POPULATE_DWORD_1 ( dword, EFAB_DUMMY_FIELD, 0 )
+#define EFAB_SET_DWORD( dword ) \
+ EFAB_POPULATE_DWORD_1 ( dword, EFAB_DWORD_0, 0xffffffff )
+
+/*
+ * Modify a named field within an already-populated structure. Used
+ * for read-modify-write operations.
+ *
+ */
+
+#define EFAB_INSERT_FIELD64( ... ) \
+ cpu_to_le64 ( EFAB_INSERT_FIELD_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_INSERT_FIELD32( ... ) \
+ cpu_to_le32 ( EFAB_INSERT_FIELD_NATIVE ( __VA_ARGS__ ) )
+
+#define EFAB_INPLACE_MASK64( min, max, field ) \
+ EFAB_INSERT_FIELD64 ( min, max, field, EFAB_MASK64 ( field ) )
+
+#define EFAB_INPLACE_MASK32( min, max, field ) \
+ EFAB_INSERT_FIELD32 ( min, max, field, EFAB_MASK32 ( field ) )
+
+#define EFAB_SET_OWORD_FIELD64( oword, field, value ) do { \
+ (oword).u64[0] = ( ( (oword).u64[0] \
+ & ~EFAB_INPLACE_MASK64 ( 0, 63, field ) ) \
+ | EFAB_INSERT_FIELD64 ( 0, 63, field, value ) ); \
+ (oword).u64[1] = ( ( (oword).u64[1] \
+ & ~EFAB_INPLACE_MASK64 ( 64, 127, field ) ) \
+ | EFAB_INSERT_FIELD64 ( 64, 127, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_QWORD_FIELD64( qword, field, value ) do { \
+ (qword).u64[0] = ( ( (qword).u64[0] \
+ & ~EFAB_INPLACE_MASK64 ( 0, 63, field ) ) \
+ | EFAB_INSERT_FIELD64 ( 0, 63, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_OWORD_FIELD32( oword, field, value ) do { \
+ (oword).u32[0] = ( ( (oword).u32[0] \
+ & ~EFAB_INPLACE_MASK32 ( 0, 31, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 0, 31, field, value ) ); \
+ (oword).u32[1] = ( ( (oword).u32[1] \
+ & ~EFAB_INPLACE_MASK32 ( 32, 63, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 32, 63, field, value ) ); \
+ (oword).u32[2] = ( ( (oword).u32[2] \
+ & ~EFAB_INPLACE_MASK32 ( 64, 95, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 64, 95, field, value ) ); \
+ (oword).u32[3] = ( ( (oword).u32[3] \
+ & ~EFAB_INPLACE_MASK32 ( 96, 127, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 96, 127, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_QWORD_FIELD32( qword, field, value ) do { \
+ (qword).u32[0] = ( ( (qword).u32[0] \
+ & ~EFAB_INPLACE_MASK32 ( 0, 31, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 0, 31, field, value ) ); \
+ (qword).u32[1] = ( ( (qword).u32[1] \
+ & ~EFAB_INPLACE_MASK32 ( 32, 63, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 32, 63, field, value ) ); \
+ } while ( 0 )
+
+#define EFAB_SET_DWORD_FIELD( dword, field, value ) do { \
+ (dword).u32[0] = ( ( (dword).u32[0] \
+ & ~EFAB_INPLACE_MASK32 ( 0, 31, field ) ) \
+ | EFAB_INSERT_FIELD32 ( 0, 31, field, value ) ); \
+ } while ( 0 )
+
+#if ( BITS_PER_LONG == 64 )
+#define EFAB_SET_OWORD_FIELD EFAB_SET_OWORD_FIELD64
+#define EFAB_SET_QWORD_FIELD EFAB_SET_QWORD_FIELD64
+#else
+#define EFAB_SET_OWORD_FIELD EFAB_SET_OWORD_FIELD32
+#define EFAB_SET_QWORD_FIELD EFAB_SET_QWORD_FIELD32
+#endif
+
+/* Used to avoid compiler warnings about shift range exceeding width
+ * of the data types when dma_addr_t is only 32 bits wide.
+ */
+#define DMA_ADDR_T_WIDTH ( 8 * sizeof ( dma_addr_t ) )
+#define EFAB_DMA_TYPE_WIDTH( width ) \
+ ( ( (width) < DMA_ADDR_T_WIDTH ) ? (width) : DMA_ADDR_T_WIDTH )
+#define EFAB_DMA_MAX_MASK ( ( DMA_ADDR_T_WIDTH == 64 ) ? \
+ ~( ( uint64_t ) 0 ) : ~( ( uint32_t ) 0 ) )
+#define EFAB_DMA_MASK(mask) ( (mask) & EFAB_DMA_MAX_MASK )
+
+#endif /* EFAB_BITFIELD_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric_nic.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric_nic.h
new file mode 100644
index 0000000..fe94d80
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/etherfabric_nic.h
@@ -0,0 +1,204 @@
+/**************************************************************************
+ *
+ * Etherboot driver for Level 5 Etherfabric network cards
+ *
+ * Written by Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Copyright Fen Systems Ltd. 2005
+ * Copyright Level 5 Networks Inc. 2005
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by
+ * reference. Drivers based on or derived from this code fall under
+ * the GPL and must retain the authorship, copyright and license
+ * notice.
+ *
+ **************************************************************************
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef EFAB_NIC_H
+#define EFAB_NIC_H
+#include <gpxe/bitbash.h>
+#include <gpxe/i2c.h>
+#include <gpxe/spi.h>
+#include <gpxe/nvo.h>
+#include <gpxe/if_ether.h>
+/**************************************************************************
+ *
+ * Constants and macros
+ *
+ **************************************************************************
+ */
+/* Board IDs. Early boards have no board_type, (e.g. EF1002 and 401/403)
+ * But newer boards are getting bigger...
+ */
+typedef enum {
+ EFAB_BOARD_INVALID = 0, /* Early boards do not have board rev. info. */
+ EFAB_BOARD_SFE4001 = 1,
+ EFAB_BOARD_SFE4002 = 2,
+ EFAB_BOARD_SFE4003 = 3,
+ /* Insert new types before here */
+ EFAB_BOARD_MAX
+} efab_board_type;
+
+/* PHY types. */
+typedef enum {
+ PHY_TYPE_AUTO = 0, /* on development board detect between CX4 & alaska */
+ PHY_TYPE_CX4_RTMR = 1,
+ PHY_TYPE_1GIG_ALASKA = 2,
+ PHY_TYPE_10XPRESS = 3,
+ PHY_TYPE_XFP = 4,
+ PHY_TYPE_CX4 = 5,
+ PHY_TYPE_PM8358 = 6,
+} phy_type_t;
+
+/**************************************************************************
+ *
+ * Hardware data structures and sizing
+ *
+ **************************************************************************
+ */
+
+#define dma_addr_t unsigned long
+typedef efab_qword_t falcon_rx_desc_t;
+typedef efab_qword_t falcon_tx_desc_t;
+typedef efab_qword_t falcon_event_t;
+
+#define EFAB_BUF_ALIGN 4096
+#define EFAB_RXD_SIZE 512
+#define EFAB_TXD_SIZE 512
+#define EFAB_EVQ_SIZE 512
+
+#define EFAB_NUM_RX_DESC 16
+#define EFAB_RX_BUF_SIZE 1600
+
+/**************************************************************************
+ *
+ * Data structures
+ *
+ **************************************************************************
+ */
+
+struct efab_nic;
+
+/* A buffer table allocation backing a tx dma, rx dma or eventq */
+struct efab_special_buffer {
+ dma_addr_t dma_addr;
+ int id;
+};
+
+/* A TX queue */
+struct efab_tx_queue {
+ /* The hardware ring */
+ falcon_tx_desc_t *ring;
+
+ /* The software ring storing io_buffers. */
+ struct io_buffer *buf[EFAB_TXD_SIZE];
+
+ /* The buffer table reservation pushed to hardware */
+ struct efab_special_buffer entry;
+
+ /* Software descriptor write ptr */
+ unsigned int write_ptr;
+
+ /* Hardware descriptor read ptr */
+ unsigned int read_ptr;
+};
+
+/* An RX queue */
+struct efab_rx_queue {
+ /* The hardware ring */
+ falcon_rx_desc_t *ring;
+
+ /* The software ring storing io_buffers */
+ struct io_buffer *buf[EFAB_NUM_RX_DESC];
+
+ /* The buffer table reservation pushed to hardware */
+ struct efab_special_buffer entry;
+
+ /* Descriptor write ptr, into both the hardware and software rings */
+ unsigned int write_ptr;
+
+ /* Hardware completion ptr */
+ unsigned int read_ptr;
+};
+
+/* An event queue */
+struct efab_ev_queue {
+ /* The hardware ring to push to hardware.
+ * Must be the first entry in the structure */
+ falcon_event_t *ring;
+
+ /* The buffer table reservation pushed to hardware */
+ struct efab_special_buffer entry;
+
+ /* Pointers into the ring */
+ unsigned int read_ptr;
+};
+
+struct efab_mac_operations {
+ int ( * init ) ( struct efab_nic *efab );
+};
+
+struct efab_phy_operations {
+ int ( * init ) ( struct efab_nic *efab );
+ unsigned int mmds;
+};
+
+struct efab_board_operations {
+ int ( * init ) ( struct efab_nic *efab );
+ void ( * fini ) ( struct efab_nic *efab );
+};
+
+struct efab_nic {
+ struct net_device *netdev;
+ int pci_revision;
+ int is_asic;
+
+ /* I2C bit-bashed interface */
+ struct i2c_bit_basher i2c_bb;
+
+ /** SPI bus and devices, and the user visible NVO area */
+ struct spi_bus spi_bus;
+ struct spi_device spi_flash;
+ struct spi_device spi_eeprom;
+ struct spi_device *spi;
+ struct nvo_block nvo;
+
+ /** Board, MAC, and PHY operations tables */
+ struct efab_board_operations *board_op;
+ struct efab_mac_operations *mac_op;
+ struct efab_phy_operations *phy_op;
+
+ /* PHY and board types */
+ int phy_addr;
+ int phy_type;
+ int phy_10g;
+ int board_type;
+
+ /** Memory and IO base */
+ void *membase;
+ unsigned int iobase;
+
+ /* Buffer table allocation head */
+ int buffer_head;
+
+ /* Queues */
+ struct efab_rx_queue rx_queue;
+ struct efab_tx_queue tx_queue;
+ struct efab_ev_queue ev_queue;
+
+ /** MAC address */
+ uint8_t mac_addr[ETH_ALEN];
+ /** GMII link options */
+ unsigned int link_options;
+ /** Link status */
+ int link_up;
+
+ /** INT_REG_KER */
+ efab_oword_t int_ker __attribute__ (( aligned ( 16 ) ));
+};
+#endif /* EFAB_NIC_H */
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/forcedeth.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/forcedeth.c
new file mode 100644
index 0000000..73c44c4
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/forcedeth.c
@@ -0,0 +1,1442 @@
+/**************************************************************************
+* forcedeth.c -- Etherboot device driver for the NVIDIA nForce
+* media access controllers.
+*
+* Note: This driver is based on the Linux driver that was based on
+* a cleanroom reimplementation which was based on reverse
+* engineered documentation written by Carl-Daniel Hailfinger
+* and Andrew de Quincey. It's neither supported nor endorsed
+* by NVIDIA Corp. Use at your own risk.
+*
+* Written 2004 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* forcedeth: Ethernet driver for NVIDIA nForce media access controllers:
+*
+* (C) 2003 Manfred Spraul
+* See Linux Driver for full information
+*
+* Linux Driver Version 0.30, 25 Sep 2004
+* Linux Kernel 2.6.10
+*
+*
+* REVISION HISTORY:
+* ================
+* v1.0 01-31-2004 timlegge Initial port of Linux driver
+* v1.1 02-03-2004 timlegge Large Clean up, first release
+* v1.2 05-14-2005 timlegge Add Linux 0.22 to .030 features
+*
+* Indent Options: indent -kr -i8
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <gpxe/pci.h>
+/* Include timer support functions */
+#include <gpxe/ethernet.h>
+#include "mii.h"
+
+#define drv_version "v1.2"
+#define drv_date "05-14-2005"
+
+//#define TFTM_DEBUG
+#ifdef TFTM_DEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+#define ETH_DATA_LEN 1500
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+static unsigned long BASE;
+/* NIC specific static variables go here */
+#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3
+#define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066
+#define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086
+#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c
+#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6
+#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df
+#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6
+#define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056
+#define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057
+#define PCI_DEVICE_ID_NVIDIA_NVENET_10 0x0037
+#define PCI_DEVICE_ID_NVIDIA_NVENET_11 0x0038
+#define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373
+
+
+/*
+ * Hardware access:
+ */
+
+#define DEV_NEED_LASTPACKET1 0x0001 /* set LASTPACKET1 in tx flags */
+#define DEV_IRQMASK_1 0x0002 /* use NVREG_IRQMASK_WANTED_1 for irq mask */
+#define DEV_IRQMASK_2 0x0004 /* use NVREG_IRQMASK_WANTED_2 for irq mask */
+#define DEV_NEED_TIMERIRQ 0x0008 /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER 0x0010 /* poll link settings. Relies on the timer irq */
+
+enum {
+ NvRegIrqStatus = 0x000,
+#define NVREG_IRQSTAT_MIIEVENT 0040
+#define NVREG_IRQSTAT_MASK 0x1ff
+ NvRegIrqMask = 0x004,
+#define NVREG_IRQ_RX_ERROR 0x0001
+#define NVREG_IRQ_RX 0x0002
+#define NVREG_IRQ_RX_NOBUF 0x0004
+#define NVREG_IRQ_TX_ERR 0x0008
+#define NVREG_IRQ_TX2 0x0010
+#define NVREG_IRQ_TIMER 0x0020
+#define NVREG_IRQ_LINK 0x0040
+#define NVREG_IRQ_TX1 0x0100
+#define NVREG_IRQMASK_WANTED_1 0x005f
+#define NVREG_IRQMASK_WANTED_2 0x0147
+#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
+
+ NvRegUnknownSetupReg6 = 0x008,
+#define NVREG_UNKSETUP6_VAL 3
+
+/*
+ * NVREG_POLL_DEFAULT is the interval length of the timer source on the nic
+ * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
+ */
+ NvRegPollingInterval = 0x00c,
+#define NVREG_POLL_DEFAULT 970
+ NvRegMisc1 = 0x080,
+#define NVREG_MISC1_HD 0x02
+#define NVREG_MISC1_FORCE 0x3b0f3c
+
+ NvRegTransmitterControl = 0x084,
+#define NVREG_XMITCTL_START 0x01
+ NvRegTransmitterStatus = 0x088,
+#define NVREG_XMITSTAT_BUSY 0x01
+
+ NvRegPacketFilterFlags = 0x8c,
+#define NVREG_PFF_ALWAYS 0x7F0008
+#define NVREG_PFF_PROMISC 0x80
+#define NVREG_PFF_MYADDR 0x20
+
+ NvRegOffloadConfig = 0x90,
+#define NVREG_OFFLOAD_HOMEPHY 0x601
+#define NVREG_OFFLOAD_NORMAL RX_NIC_BUFSIZE
+ NvRegReceiverControl = 0x094,
+#define NVREG_RCVCTL_START 0x01
+ NvRegReceiverStatus = 0x98,
+#define NVREG_RCVSTAT_BUSY 0x01
+
+ NvRegRandomSeed = 0x9c,
+#define NVREG_RNDSEED_MASK 0x00ff
+#define NVREG_RNDSEED_FORCE 0x7f00
+#define NVREG_RNDSEED_FORCE2 0x2d00
+#define NVREG_RNDSEED_FORCE3 0x7400
+
+ NvRegUnknownSetupReg1 = 0xA0,
+#define NVREG_UNKSETUP1_VAL 0x16070f
+ NvRegUnknownSetupReg2 = 0xA4,
+#define NVREG_UNKSETUP2_VAL 0x16
+ NvRegMacAddrA = 0xA8,
+ NvRegMacAddrB = 0xAC,
+ NvRegMulticastAddrA = 0xB0,
+#define NVREG_MCASTADDRA_FORCE 0x01
+ NvRegMulticastAddrB = 0xB4,
+ NvRegMulticastMaskA = 0xB8,
+ NvRegMulticastMaskB = 0xBC,
+
+ NvRegPhyInterface = 0xC0,
+#define PHY_RGMII 0x10000000
+
+ NvRegTxRingPhysAddr = 0x100,
+ NvRegRxRingPhysAddr = 0x104,
+ NvRegRingSizes = 0x108,
+#define NVREG_RINGSZ_TXSHIFT 0
+#define NVREG_RINGSZ_RXSHIFT 16
+ NvRegUnknownTransmitterReg = 0x10c,
+ NvRegLinkSpeed = 0x110,
+#define NVREG_LINKSPEED_FORCE 0x10000
+#define NVREG_LINKSPEED_10 1000
+#define NVREG_LINKSPEED_100 100
+#define NVREG_LINKSPEED_1000 50
+ NvRegUnknownSetupReg5 = 0x130,
+#define NVREG_UNKSETUP5_BIT31 (1<<31)
+ NvRegUnknownSetupReg3 = 0x13c,
+#define NVREG_UNKSETUP3_VAL1 0x200010
+ NvRegTxRxControl = 0x144,
+#define NVREG_TXRXCTL_KICK 0x0001
+#define NVREG_TXRXCTL_BIT1 0x0002
+#define NVREG_TXRXCTL_BIT2 0x0004
+#define NVREG_TXRXCTL_IDLE 0x0008
+#define NVREG_TXRXCTL_RESET 0x0010
+#define NVREG_TXRXCTL_RXCHECK 0x0400
+ NvRegMIIStatus = 0x180,
+#define NVREG_MIISTAT_ERROR 0x0001
+#define NVREG_MIISTAT_LINKCHANGE 0x0008
+#define NVREG_MIISTAT_MASK 0x000f
+#define NVREG_MIISTAT_MASK2 0x000f
+ NvRegUnknownSetupReg4 = 0x184,
+#define NVREG_UNKSETUP4_VAL 8
+
+ NvRegAdapterControl = 0x188,
+#define NVREG_ADAPTCTL_START 0x02
+#define NVREG_ADAPTCTL_LINKUP 0x04
+#define NVREG_ADAPTCTL_PHYVALID 0x40000
+#define NVREG_ADAPTCTL_RUNNING 0x100000
+#define NVREG_ADAPTCTL_PHYSHIFT 24
+ NvRegMIISpeed = 0x18c,
+#define NVREG_MIISPEED_BIT8 (1<<8)
+#define NVREG_MIIDELAY 5
+ NvRegMIIControl = 0x190,
+#define NVREG_MIICTL_INUSE 0x08000
+#define NVREG_MIICTL_WRITE 0x00400
+#define NVREG_MIICTL_ADDRSHIFT 5
+ NvRegMIIData = 0x194,
+ NvRegWakeUpFlags = 0x200,
+#define NVREG_WAKEUPFLAGS_VAL 0x7770
+#define NVREG_WAKEUPFLAGS_BUSYSHIFT 24
+#define NVREG_WAKEUPFLAGS_ENABLESHIFT 16
+#define NVREG_WAKEUPFLAGS_D3SHIFT 12
+#define NVREG_WAKEUPFLAGS_D2SHIFT 8
+#define NVREG_WAKEUPFLAGS_D1SHIFT 4
+#define NVREG_WAKEUPFLAGS_D0SHIFT 0
+#define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT 0x01
+#define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT 0x02
+#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
+#define NVREG_WAKEUPFLAGS_ENABLE 0x1111
+
+ NvRegPatternCRC = 0x204,
+ NvRegPatternMask = 0x208,
+ NvRegPowerCap = 0x268,
+#define NVREG_POWERCAP_D3SUPP (1<<30)
+#define NVREG_POWERCAP_D2SUPP (1<<26)
+#define NVREG_POWERCAP_D1SUPP (1<<25)
+ NvRegPowerState = 0x26c,
+#define NVREG_POWERSTATE_POWEREDUP 0x8000
+#define NVREG_POWERSTATE_VALID 0x0100
+#define NVREG_POWERSTATE_MASK 0x0003
+#define NVREG_POWERSTATE_D0 0x0000
+#define NVREG_POWERSTATE_D1 0x0001
+#define NVREG_POWERSTATE_D2 0x0002
+#define NVREG_POWERSTATE_D3 0x0003
+};
+
+#define FLAG_MASK_V1 0xffff0000
+#define FLAG_MASK_V2 0xffffc000
+#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
+#define LEN_MASK_V2 (0xffffffff ^ FLAG_MASK_V2)
+
+#define NV_TX_LASTPACKET (1<<16)
+#define NV_TX_RETRYERROR (1<<19)
+#define NV_TX_LASTPACKET1 (1<<24)
+#define NV_TX_DEFERRED (1<<26)
+#define NV_TX_CARRIERLOST (1<<27)
+#define NV_TX_LATECOLLISION (1<<28)
+#define NV_TX_UNDERFLOW (1<<29)
+#define NV_TX_ERROR (1<<30)
+#define NV_TX_VALID (1<<31)
+
+#define NV_TX2_LASTPACKET (1<<29)
+#define NV_TX2_RETRYERROR (1<<18)
+#define NV_TX2_LASTPACKET1 (1<<23)
+#define NV_TX2_DEFERRED (1<<25)
+#define NV_TX2_CARRIERLOST (1<<26)
+#define NV_TX2_LATECOLLISION (1<<27)
+#define NV_TX2_UNDERFLOW (1<<28)
+/* error and valid are the same for both */
+#define NV_TX2_ERROR (1<<30)
+#define NV_TX2_VALID (1<<31)
+
+#define NV_RX_DESCRIPTORVALID (1<<16)
+#define NV_RX_MISSEDFRAME (1<<17)
+#define NV_RX_SUBSTRACT1 (1<<18)
+#define NV_RX_ERROR1 (1<<23)
+#define NV_RX_ERROR2 (1<<24)
+#define NV_RX_ERROR3 (1<<25)
+#define NV_RX_ERROR4 (1<<26)
+#define NV_RX_CRCERR (1<<27)
+#define NV_RX_OVERFLOW (1<<28)
+#define NV_RX_FRAMINGERR (1<<29)
+#define NV_RX_ERROR (1<<30)
+#define NV_RX_AVAIL (1<<31)
+
+#define NV_RX2_CHECKSUMMASK (0x1C000000)
+#define NV_RX2_CHECKSUMOK1 (0x10000000)
+#define NV_RX2_CHECKSUMOK2 (0x14000000)
+#define NV_RX2_CHECKSUMOK3 (0x18000000)
+#define NV_RX2_DESCRIPTORVALID (1<<29)
+#define NV_RX2_SUBSTRACT1 (1<<25)
+#define NV_RX2_ERROR1 (1<<18)
+#define NV_RX2_ERROR2 (1<<19)
+#define NV_RX2_ERROR3 (1<<20)
+#define NV_RX2_ERROR4 (1<<21)
+#define NV_RX2_CRCERR (1<<22)
+#define NV_RX2_OVERFLOW (1<<23)
+#define NV_RX2_FRAMINGERR (1<<24)
+/* error and avail are the same for both */
+#define NV_RX2_ERROR (1<<30)
+#define NV_RX2_AVAIL (1<<31)
+
+/* Miscelaneous hardware related defines: */
+#define NV_PCI_REGSZ 0x270
+
+/* various timeout delays: all in usec */
+#define NV_TXRX_RESET_DELAY 4
+#define NV_TXSTOP_DELAY1 10
+#define NV_TXSTOP_DELAY1MAX 500000
+#define NV_TXSTOP_DELAY2 100
+#define NV_RXSTOP_DELAY1 10
+#define NV_RXSTOP_DELAY1MAX 500000
+#define NV_RXSTOP_DELAY2 100
+#define NV_SETUP5_DELAY 5
+#define NV_SETUP5_DELAYMAX 50000
+#define NV_POWERUP_DELAY 5
+#define NV_POWERUP_DELAYMAX 5000
+#define NV_MIIBUSY_DELAY 50
+#define NV_MIIPHY_DELAY 10
+#define NV_MIIPHY_DELAYMAX 10000
+
+#define NV_WAKEUPPATTERNS 5
+#define NV_WAKEUPMASKENTRIES 4
+
+/* General driver defaults */
+#define NV_WATCHDOG_TIMEO (5*HZ)
+
+#define RX_RING 4
+#define TX_RING 2
+
+/*
+ * If your nic mysteriously hangs then try to reduce the limits
+ * to 1/0: It might be required to set NV_TX_LASTPACKET in the
+ * last valid ring entry. But this would be impossible to
+ * implement - probably a disassembly error.
+ */
+#define TX_LIMIT_STOP 63
+#define TX_LIMIT_START 62
+
+/* rx/tx mac addr + type + vlan + align + slack*/
+#define RX_NIC_BUFSIZE (ETH_DATA_LEN + 64)
+/* even more slack */
+#define RX_ALLOC_BUFSIZE (ETH_DATA_LEN + 128)
+
+#define OOM_REFILL (1+HZ/20)
+#define POLL_WAIT (1+HZ/100)
+#define LINK_TIMEOUT (3*HZ)
+
+/*
+ * desc_ver values:
+ * This field has two purposes:
+ * - Newer nics uses a different ring layout. The layout is selected by
+ * comparing np->desc_ver with DESC_VER_xy.
+ * - It contains bits that are forced on when writing to NvRegTxRxControl.
+ */
+#define DESC_VER_1 0x0
+#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
+
+/* PHY defines */
+#define PHY_OUI_MARVELL 0x5043
+#define PHY_OUI_CICADA 0x03f1
+#define PHYID1_OUI_MASK 0x03ff
+#define PHYID1_OUI_SHFT 6
+#define PHYID2_OUI_MASK 0xfc00
+#define PHYID2_OUI_SHFT 10
+#define PHY_INIT1 0x0f000
+#define PHY_INIT2 0x0e00
+#define PHY_INIT3 0x01000
+#define PHY_INIT4 0x0200
+#define PHY_INIT5 0x0004
+#define PHY_INIT6 0x02000
+#define PHY_GIGABIT 0x0100
+
+#define PHY_TIMEOUT 0x1
+#define PHY_ERROR 0x2
+
+#define PHY_100 0x1
+#define PHY_1000 0x2
+#define PHY_HALF 0x100
+
+
+/* Bit to know if MAC addr is stored in correct order */
+#define MAC_ADDR_CORRECT 0x01
+
+/* Big endian: should work, but is untested */
+struct ring_desc {
+ u32 PacketBuffer;
+ u32 FlagLen;
+};
+
+
+/* Define the TX and RX Descriptor and Buffers */
+struct {
+ struct ring_desc tx_ring[TX_RING];
+ unsigned char txb[TX_RING * RX_NIC_BUFSIZE];
+ struct ring_desc rx_ring[RX_RING];
+ unsigned char rxb[RX_RING * RX_NIC_BUFSIZE];
+} forcedeth_bufs __shared;
+#define tx_ring forcedeth_bufs.tx_ring
+#define rx_ring forcedeth_bufs.rx_ring
+#define txb forcedeth_bufs.txb
+#define rxb forcedeth_bufs.rxb
+
+/* Private Storage for the NIC */
+static struct forcedeth_private {
+ /* General data:
+ * Locking: spin_lock(&np->lock); */
+ int in_shutdown;
+ u32 linkspeed;
+ int duplex;
+ int phyaddr;
+ int wolenabled;
+ unsigned int phy_oui;
+ u16 gigabit;
+
+ /* General data: RO fields */
+ u8 *ring_addr;
+ u32 orig_mac[2];
+ u32 irqmask;
+ u32 desc_ver;
+ /* rx specific fields.
+ * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
+ */
+ unsigned int cur_rx, refill_rx;
+
+ /*
+ * tx specific fields.
+ */
+ unsigned int next_tx, nic_tx;
+ u32 tx_flags;
+} npx;
+
+static struct forcedeth_private *np;
+
+static inline void pci_push(u8 * base)
+{
+ /* force out pending posted writes */
+ readl(base);
+}
+
+static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
+{
+ return le32_to_cpu(prd->FlagLen)
+ & ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
+}
+
+static int reg_delay(int offset, u32 mask,
+ u32 target, int delay, int delaymax, const char *msg)
+{
+ u8 *base = (u8 *) BASE;
+
+ pci_push(base);
+ do {
+ udelay(delay);
+ delaymax -= delay;
+ if (delaymax < 0) {
+ if (msg)
+ printf("%s", msg);
+ return 1;
+ }
+ } while ((readl(base + offset) & mask) != target);
+ return 0;
+}
+
+#define MII_READ (-1)
+
+/* mii_rw: read/write a register on the PHY.
+ *
+ * Caller must guarantee serialization
+ */
+static int mii_rw(struct nic *nic __unused, int addr, int miireg,
+ int value)
+{
+ u8 *base = (u8 *) BASE;
+ u32 reg;
+ int retval;
+
+ writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+
+ reg = readl(base + NvRegMIIControl);
+ if (reg & NVREG_MIICTL_INUSE) {
+ writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl);
+ udelay(NV_MIIBUSY_DELAY);
+ }
+
+ reg =
+ (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;
+ if (value != MII_READ) {
+ writel(value, base + NvRegMIIData);
+ reg |= NVREG_MIICTL_WRITE;
+ }
+ writel(reg, base + NvRegMIIControl);
+
+ if (reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0,
+ NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) {
+ dprintf(("mii_rw of reg %d at PHY %d timed out.\n",
+ miireg, addr));
+ retval = -1;
+ } else if (value != MII_READ) {
+ /* it was a write operation - fewer failures are detectable */
+ dprintf(("mii_rw wrote 0x%x to reg %d at PHY %d\n",
+ value, miireg, addr));
+ retval = 0;
+ } else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) {
+ dprintf(("mii_rw of reg %d at PHY %d failed.\n",
+ miireg, addr));
+ retval = -1;
+ } else {
+ retval = readl(base + NvRegMIIData);
+ dprintf(("mii_rw read from reg %d at PHY %d: 0x%x.\n",
+ miireg, addr, retval));
+ }
+ return retval;
+}
+
+static int phy_reset(struct nic *nic)
+{
+
+ u32 miicontrol;
+ unsigned int tries = 0;
+
+ miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
+ miicontrol |= BMCR_RESET;
+ if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) {
+ return -1;
+ }
+
+ /* wait for 500ms */
+ mdelay(500);
+
+ /* must wait till reset is deasserted */
+ while (miicontrol & BMCR_RESET) {
+ mdelay(10);
+ miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
+ /* FIXME: 100 tries seem excessive */
+ if (tries++ > 100)
+ return -1;
+ }
+ return 0;
+}
+
+static int phy_init(struct nic *nic)
+{
+ u8 *base = (u8 *) BASE;
+ u32 phyinterface, phy_reserved, mii_status, mii_control,
+ mii_control_1000, reg;
+
+ /* set advertise register */
+ reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
+ reg |=
+ (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
+ ADVERTISE_100FULL | 0x800 | 0x400);
+ if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) {
+ printf("phy write to advertise failed.\n");
+ return PHY_ERROR;
+ }
+
+ /* get phy interface type */
+ phyinterface = readl(base + NvRegPhyInterface);
+
+ /* see if gigabit phy */
+ mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
+
+ if (mii_status & PHY_GIGABIT) {
+ np->gigabit = PHY_GIGABIT;
+ mii_control_1000 =
+ mii_rw(nic, np->phyaddr, MII_CTRL1000, MII_READ);
+ mii_control_1000 &= ~ADVERTISE_1000HALF;
+ if (phyinterface & PHY_RGMII)
+ mii_control_1000 |= ADVERTISE_1000FULL;
+ else
+ mii_control_1000 &= ~ADVERTISE_1000FULL;
+
+ if (mii_rw
+ (nic, np->phyaddr, MII_CTRL1000, mii_control_1000)) {
+ printf("phy init failed.\n");
+ return PHY_ERROR;
+ }
+ } else
+ np->gigabit = 0;
+
+ /* reset the phy */
+ if (phy_reset(nic)) {
+ printf("phy reset failed\n");
+ return PHY_ERROR;
+ }
+
+ /* phy vendor specific configuration */
+ if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) {
+ phy_reserved =
+ mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ);
+ phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
+ phy_reserved |= (PHY_INIT3 | PHY_INIT4);
+ if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) {
+ printf("phy init failed.\n");
+ return PHY_ERROR;
+ }
+ phy_reserved =
+ mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ);
+ phy_reserved |= PHY_INIT5;
+ if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) {
+ printf("phy init failed.\n");
+ return PHY_ERROR;
+ }
+ }
+ if (np->phy_oui == PHY_OUI_CICADA) {
+ phy_reserved =
+ mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ);
+ phy_reserved |= PHY_INIT6;
+ if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) {
+ printf("phy init failed.\n");
+ return PHY_ERROR;
+ }
+ }
+
+ /* restart auto negotiation */
+ mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
+ mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
+ if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) {
+ return PHY_ERROR;
+ }
+
+ return 0;
+}
+
+static void start_rx(struct nic *nic __unused)
+{
+ u8 *base = (u8 *) BASE;
+
+ dprintf(("start_rx\n"));
+ /* Already running? Stop it. */
+ if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
+ writel(0, base + NvRegReceiverControl);
+ pci_push(base);
+ }
+ writel(np->linkspeed, base + NvRegLinkSpeed);
+ pci_push(base);
+ writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
+ pci_push(base);
+}
+
+static void stop_rx(void)
+{
+ u8 *base = (u8 *) BASE;
+
+ dprintf(("stop_rx\n"));
+ writel(0, base + NvRegReceiverControl);
+ reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
+ NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
+ "stop_rx: ReceiverStatus remained busy");
+
+ udelay(NV_RXSTOP_DELAY2);
+ writel(0, base + NvRegLinkSpeed);
+}
+
+static void start_tx(struct nic *nic __unused)
+{
+ u8 *base = (u8 *) BASE;
+
+ dprintf(("start_tx\n"));
+ writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl);
+ pci_push(base);
+}
+
+static void stop_tx(void)
+{
+ u8 *base = (u8 *) BASE;
+
+ dprintf(("stop_tx\n"));
+ writel(0, base + NvRegTransmitterControl);
+ reg_delay(NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
+ NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
+ "stop_tx: TransmitterStatus remained busy");
+
+ udelay(NV_TXSTOP_DELAY2);
+ writel(0, base + NvRegUnknownTransmitterReg);
+}
+
+
+static void txrx_reset(struct nic *nic __unused)
+{
+ u8 *base = (u8 *) BASE;
+
+ dprintf(("txrx_reset\n"));
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver,
+ base + NvRegTxRxControl);
+
+ pci_push(base);
+ udelay(NV_TXRX_RESET_DELAY);
+ writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
+ pci_push(base);
+}
+
+/*
+ * alloc_rx: fill rx ring entries.
+ * Return 1 if the allocations for the skbs failed and the
+ * rx engine is without Available descriptors
+ */
+static int alloc_rx(struct nic *nic __unused)
+{
+ unsigned int refill_rx = np->refill_rx;
+ int i;
+ //while (np->cur_rx != refill_rx) {
+ for (i = 0; i < RX_RING; i++) {
+ //int nr = refill_rx % RX_RING;
+ rx_ring[i].PacketBuffer =
+ virt_to_le32desc(&rxb[i * RX_NIC_BUFSIZE]);
+ wmb();
+ rx_ring[i].FlagLen =
+ cpu_to_le32(RX_NIC_BUFSIZE | NV_RX_AVAIL);
+ /* printf("alloc_rx: Packet %d marked as Available\n",
+ refill_rx); */
+ refill_rx++;
+ }
+ np->refill_rx = refill_rx;
+ if (np->cur_rx - refill_rx == RX_RING)
+ return 1;
+ return 0;
+}
+
+static int update_linkspeed(struct nic *nic)
+{
+ int adv, lpa;
+ u32 newls;
+ int newdup = np->duplex;
+ u32 mii_status;
+ int retval = 0;
+ u32 control_1000, status_1000, phyreg;
+ u8 *base = (u8 *) BASE;
+ int i;
+
+ /* BMSR_LSTATUS is latched, read it twice:
+ * we want the current value.
+ */
+ mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
+ mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
+
+#if 1
+ //yhlu
+ for(i=0;i<30;i++) {
+ mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
+ if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break;
+ mdelay(100);
+ }
+#endif
+
+ if (!(mii_status & BMSR_LSTATUS)) {
+ printf
+ ("no link detected by phy - falling back to 10HD.\n");
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ retval = 0;
+ goto set_speed;
+ }
+
+ /* check auto negotiation is complete */
+ if (!(mii_status & BMSR_ANEGCOMPLETE)) {
+ /* still in autonegotiation - configure nic for 10 MBit HD and wait. */
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ retval = 0;
+ printf("autoneg not completed - falling back to 10HD.\n");
+ goto set_speed;
+ }
+
+ retval = 1;
+ if (np->gigabit == PHY_GIGABIT) {
+ control_1000 =
+ mii_rw(nic, np->phyaddr, MII_CTRL1000, MII_READ);
+ status_1000 =
+ mii_rw(nic, np->phyaddr, MII_STAT1000, MII_READ);
+
+ if ((control_1000 & ADVERTISE_1000FULL) &&
+ (status_1000 & LPA_1000FULL)) {
+ printf
+ ("update_linkspeed: GBit ethernet detected.\n");
+ newls =
+ NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000;
+ newdup = 1;
+ goto set_speed;
+ }
+ }
+
+ adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
+ lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);
+ dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n",
+ adv, lpa));
+
+ /* FIXME: handle parallel detection properly, handle gigabit ethernet */
+ lpa = lpa & adv;
+ if (lpa & LPA_100FULL) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100;
+ newdup = 1;
+ } else if (lpa & LPA_100HALF) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100;
+ newdup = 0;
+ } else if (lpa & LPA_10FULL) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 1;
+ } else if (lpa & LPA_10HALF) {
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ } else {
+ printf("bad ability %hX - falling back to 10HD.\n", lpa);
+ newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ newdup = 0;
+ }
+
+ set_speed:
+ if (np->duplex == newdup && np->linkspeed == newls)
+ return retval;
+
+ dprintf(("changing link setting from %d/%s to %d/%s.\n",
+ np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex"));
+
+ np->duplex = newdup;
+ np->linkspeed = newls;
+
+ if (np->gigabit == PHY_GIGABIT) {
+ phyreg = readl(base + NvRegRandomSeed);
+ phyreg &= ~(0x3FF00);
+ if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
+ phyreg |= NVREG_RNDSEED_FORCE3;
+ else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
+ phyreg |= NVREG_RNDSEED_FORCE2;
+ else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
+ phyreg |= NVREG_RNDSEED_FORCE;
+ writel(phyreg, base + NvRegRandomSeed);
+ }
+
+ phyreg = readl(base + NvRegPhyInterface);
+ phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000);
+ if (np->duplex == 0)
+ phyreg |= PHY_HALF;
+ if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
+ phyreg |= PHY_100;
+ else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
+ phyreg |= PHY_1000;
+ writel(phyreg, base + NvRegPhyInterface);
+
+ writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD),
+ base + NvRegMisc1);
+ pci_push(base);
+ writel(np->linkspeed, base + NvRegLinkSpeed);
+ pci_push(base);
+
+ return retval;
+}
+
+#if 0 /* Not used */
+static void nv_linkchange(struct nic *nic)
+{
+ if (update_linkspeed(nic)) {
+// if (netif_carrier_ok(nic)) {
+ stop_rx();
+//= } else {
+ // netif_carrier_on(dev);
+ // printk(KERN_INFO "%s: link up.\n", dev->name);
+ // }
+ start_rx(nic);
+ } else {
+ // if (netif_carrier_ok(dev)) {
+ // netif_carrier_off(dev);
+ // printk(KERN_INFO "%s: link down.\n", dev->name);
+ stop_rx();
+ // }
+ }
+}
+#endif
+
+static int init_ring(struct nic *nic)
+{
+ int i;
+
+ np->next_tx = np->nic_tx = 0;
+ for (i = 0; i < TX_RING; i++)
+ tx_ring[i].FlagLen = 0;
+
+ np->cur_rx = 0;
+ np->refill_rx = 0;
+ for (i = 0; i < RX_RING; i++)
+ rx_ring[i].FlagLen = 0;
+ return alloc_rx(nic);
+}
+
+static void set_multicast(struct nic *nic)
+{
+
+ u8 *base = (u8 *) BASE;
+ u32 addr[2];
+ u32 mask[2];
+ u32 pff;
+ u32 alwaysOff[2];
+ u32 alwaysOn[2];
+
+ memset(addr, 0, sizeof(addr));
+ memset(mask, 0, sizeof(mask));
+
+ pff = NVREG_PFF_MYADDR;
+
+ alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
+
+ addr[0] = alwaysOn[0];
+ addr[1] = alwaysOn[1];
+ mask[0] = alwaysOn[0] | alwaysOff[0];
+ mask[1] = alwaysOn[1] | alwaysOff[1];
+
+ addr[0] |= NVREG_MCASTADDRA_FORCE;
+ pff |= NVREG_PFF_ALWAYS;
+ stop_rx();
+ writel(addr[0], base + NvRegMulticastAddrA);
+ writel(addr[1], base + NvRegMulticastAddrB);
+ writel(mask[0], base + NvRegMulticastMaskA);
+ writel(mask[1], base + NvRegMulticastMaskB);
+ writel(pff, base + NvRegPacketFilterFlags);
+ start_rx(nic);
+}
+
+/**************************************************************************
+RESET - Reset the NIC to prepare for use
+***************************************************************************/
+static int forcedeth_reset(struct nic *nic)
+{
+ u8 *base = (u8 *) BASE;
+ int ret, oom, i;
+ ret = 0;
+ dprintf(("forcedeth: open\n"));
+
+ /* 1) erase previous misconfiguration */
+ /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
+ writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
+ writel(0, base + NvRegMulticastAddrB);
+ writel(0, base + NvRegMulticastMaskA);
+ writel(0, base + NvRegMulticastMaskB);
+ writel(0, base + NvRegPacketFilterFlags);
+
+ writel(0, base + NvRegTransmitterControl);
+ writel(0, base + NvRegReceiverControl);
+
+ writel(0, base + NvRegAdapterControl);
+
+ /* 2) initialize descriptor rings */
+ oom = init_ring(nic);
+
+ writel(0, base + NvRegLinkSpeed);
+ writel(0, base + NvRegUnknownTransmitterReg);
+ txrx_reset(nic);
+ writel(0, base + NvRegUnknownSetupReg6);
+
+ np->in_shutdown = 0;
+
+ /* 3) set mac address */
+ {
+ u32 mac[2];
+
+ mac[0] =
+ (nic->node_addr[0] << 0) + (nic->node_addr[1] << 8) +
+ (nic->node_addr[2] << 16) + (nic->node_addr[3] << 24);
+ mac[1] =
+ (nic->node_addr[4] << 0) + (nic->node_addr[5] << 8);
+
+ writel(mac[0], base + NvRegMacAddrA);
+ writel(mac[1], base + NvRegMacAddrB);
+ }
+
+ /* 4) give hw rings */
+ writel((u32) virt_to_le32desc(&rx_ring[0]),
+ base + NvRegRxRingPhysAddr);
+ writel((u32) virt_to_le32desc(&tx_ring[0]),
+ base + NvRegTxRingPhysAddr);
+
+ writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) +
+ ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT),
+ base + NvRegRingSizes);
+
+ /* 5) continue setup */
+ np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
+ np->duplex = 0;
+ writel(np->linkspeed, base + NvRegLinkSpeed);
+ writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
+ writel(np->desc_ver, base + NvRegTxRxControl);
+ pci_push(base);
+ writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl);
+ reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31,
+ NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY,
+ NV_SETUP5_DELAYMAX,
+ "open: SetupReg5, Bit 31 remained off\n");
+
+ writel(0, base + NvRegUnknownSetupReg4);
+// writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+ writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
+#if 0
+ printf("%d-Mbs Link, %s-Duplex\n",
+ np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100,
+ np->duplex ? "Full" : "Half");
+#endif
+
+ /* 6) continue setup */
+ writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
+ writel(readl(base + NvRegTransmitterStatus),
+ base + NvRegTransmitterStatus);
+ writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
+ writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
+
+ writel(readl(base + NvRegReceiverStatus),
+ base + NvRegReceiverStatus);
+
+ /* Get a random number */
+ i = random();
+ writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK),
+ base + NvRegRandomSeed);
+ writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
+ writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
+ writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);
+ writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
+ writel((np->
+ phyaddr << NVREG_ADAPTCTL_PHYSHIFT) |
+ NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING,
+ base + NvRegAdapterControl);
+ writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed);
+ writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
+ writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
+
+ i = readl(base + NvRegPowerState);
+ if ((i & NVREG_POWERSTATE_POWEREDUP) == 0)
+ writel(NVREG_POWERSTATE_POWEREDUP | i,
+ base + NvRegPowerState);
+
+ pci_push(base);
+ udelay(10);
+ writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID,
+ base + NvRegPowerState);
+
+ writel(0, base + NvRegIrqMask);
+ pci_push(base);
+ writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
+ writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+ pci_push(base);
+/*
+ writel(np->irqmask, base + NvRegIrqMask);
+*/
+ writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
+ writel(0, base + NvRegMulticastAddrB);
+ writel(0, base + NvRegMulticastMaskA);
+ writel(0, base + NvRegMulticastMaskB);
+ writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR,
+ base + NvRegPacketFilterFlags);
+
+ set_multicast(nic);
+ /* One manual link speed update: Interrupts are enabled, future link
+ * speed changes cause interrupts and are handled by nv_link_irq().
+ */
+ {
+ u32 miistat;
+ miistat = readl(base + NvRegMIIStatus);
+ writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+ dprintf(("startup: got 0x%hX.\n", miistat));
+ }
+ ret = update_linkspeed(nic);
+
+ //start_rx(nic);
+ start_tx(nic);
+
+ if (ret) {
+ //Start Connection netif_carrier_on(dev);
+ } else {
+ printf("no link during initialization.\n");
+ }
+
+ return ret;
+}
+
+/*
+ * extern void hex_dump(const char *data, const unsigned int len);
+*/
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int forcedeth_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+
+ int len;
+ int i;
+ u32 Flags;
+
+ i = np->cur_rx % RX_RING;
+
+ Flags = le32_to_cpu(rx_ring[i].FlagLen);
+ len = nv_descr_getlength(&rx_ring[i], np->desc_ver);
+
+ if (Flags & NV_RX_AVAIL)
+ return 0; /* still owned by hardware, */
+
+ if (np->desc_ver == DESC_VER_1) {
+ if (!(Flags & NV_RX_DESCRIPTORVALID))
+ return 0;
+ } else {
+ if (!(Flags & NV_RX2_DESCRIPTORVALID))
+ return 0;
+ }
+
+ if (!retrieve)
+ return 1;
+
+ /* got a valid packet - forward it to the network core */
+ nic->packetlen = len;
+ memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen);
+/*
+ * hex_dump(rxb + (i * RX_NIC_BUFSIZE), len);
+*/
+ wmb();
+ np->cur_rx++;
+ alloc_rx(nic);
+ return 1;
+}
+
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void forcedeth_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ /* send the packet to destination */
+ u8 *ptxb;
+ u16 nstype;
+ u8 *base = (u8 *) BASE;
+ int nr = np->next_tx % TX_RING;
+
+ /* point to the current txb incase multiple tx_rings are used */
+ ptxb = txb + (nr * RX_NIC_BUFSIZE);
+ //np->tx_skbuff[nr] = ptxb;
+
+ /* copy the packet to ring buffer */
+ memcpy(ptxb, d, ETH_ALEN); /* dst */
+ memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+ nstype = htons((u16) t); /* type */
+ memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */
+ memcpy(ptxb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN) /* pad to min length */
+ ptxb[s++] = '\0';
+
+ tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);
+
+ wmb();
+ tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags);
+
+ writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl);
+ pci_push(base);
+ np->next_tx++;
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void forcedeth_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ */
+ u8 *base = (u8 *) BASE;
+ np->in_shutdown = 1;
+ stop_tx();
+ stop_rx();
+
+ /* disable interrupts on the nic or we will lock up */
+ writel(0, base + NvRegIrqMask);
+ pci_push(base);
+ dprintf(("Irqmask is zero again\n"));
+
+ /* specia op:o write back the misordered MAC address - otherwise
+ * the next probe_nic would see a wrong address.
+ */
+ writel(np->orig_mac[0], base + NvRegMacAddrA);
+ writel(np->orig_mac[1], base + NvRegMacAddrB);
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void forcedeth_irq(struct nic *nic __unused,
+ irq_action_t action __unused)
+{
+ switch (action) {
+ case DISABLE:
+ break;
+ case ENABLE:
+ break;
+ case FORCE:
+ break;
+ }
+}
+
+static struct nic_operations forcedeth_operations = {
+ .connect = dummy_connect,
+ .poll = forcedeth_poll,
+ .transmit = forcedeth_transmit,
+ .irq = forcedeth_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+#define IORESOURCE_MEM 0x00000200
+#define board_found 1
+#define valid_link 0
+static int forcedeth_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ unsigned long addr;
+ int sz;
+ u8 *base;
+ int i;
+ struct pci_device_id *ids = pci->driver->ids;
+ int id_count = pci->driver->id_count;
+ unsigned int flags = 0;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ printf("forcedeth.c: Found %s, vendor=0x%hX, device=0x%hX\n",
+ pci->driver_name, pci->vendor, pci->device);
+
+ nic->ioaddr = pci->ioaddr;
+ nic->irqno = 0;
+
+ /* point to private storage */
+ np = &npx;
+
+ adjust_pci_device(pci);
+
+ addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0);
+ sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0);
+
+ /* BASE is used throughout to address the card */
+ BASE = (unsigned long) ioremap(addr, sz);
+ if (!BASE)
+ return 0;
+
+ /* handle different descriptor versions */
+ if (pci->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||
+ pci->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||
+ pci->device == PCI_DEVICE_ID_NVIDIA_NVENET_3)
+ np->desc_ver = DESC_VER_1;
+ else
+ np->desc_ver = DESC_VER_2;
+
+ //rx_ring[0] = rx_ring;
+ //tx_ring[0] = tx_ring;
+
+ /* read the mac address */
+ base = (u8 *) BASE;
+ np->orig_mac[0] = readl(base + NvRegMacAddrA);
+ np->orig_mac[1] = readl(base + NvRegMacAddrB);
+
+ /* lookup the flags from pci_device_id */
+ for(i = 0; i < id_count; i++) {
+ if(pci->vendor == ids[i].vendor &&
+ pci->device == ids[i].device) {
+ flags = ids[i].driver_data;
+ break;
+ }
+ }
+
+ /* read MAC address */
+ if(flags & MAC_ADDR_CORRECT) {
+ nic->node_addr[0] = (np->orig_mac[0] >> 0) & 0xff;
+ nic->node_addr[1] = (np->orig_mac[0] >> 8) & 0xff;
+ nic->node_addr[2] = (np->orig_mac[0] >> 16) & 0xff;
+ nic->node_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
+ nic->node_addr[4] = (np->orig_mac[1] >> 0) & 0xff;
+ nic->node_addr[5] = (np->orig_mac[1] >> 8) & 0xff;
+ } else {
+ nic->node_addr[0] = (np->orig_mac[1] >> 8) & 0xff;
+ nic->node_addr[1] = (np->orig_mac[1] >> 0) & 0xff;
+ nic->node_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
+ nic->node_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
+ nic->node_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
+ nic->node_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
+ }
+#ifdef LINUX
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ /*
+ * Bad mac address. At least one bios sets the mac address
+ * to 01:23:45:67:89:ab
+ */
+ printk(KERN_ERR
+ "%s: Invalid Mac address detected: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pci_name(pci_dev), dev->dev_addr[0],
+ dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4],
+ dev->dev_addr[5]);
+ printk(KERN_ERR
+ "Please complain to your hardware vendor. Switching to a random MAC.\n");
+ dev->dev_addr[0] = 0x00;
+ dev->dev_addr[1] = 0x00;
+ dev->dev_addr[2] = 0x6c;
+ get_random_bytes(&dev->dev_addr[3], 3);
+ }
+#endif
+
+ DBG ( "%s: MAC Address %s\n", pci->driver_name, eth_ntoa ( nic->node_addr ) );
+
+ /* disable WOL */
+ writel(0, base + NvRegWakeUpFlags);
+ np->wolenabled = 0;
+
+ if (np->desc_ver == DESC_VER_1) {
+ np->tx_flags = NV_TX_LASTPACKET | NV_TX_VALID;
+ } else {
+ np->tx_flags = NV_TX2_LASTPACKET | NV_TX2_VALID;
+ }
+
+ switch (pci->device) {
+ case 0x01C3: // nforce
+ // DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
+ np->irqmask = NVREG_IRQMASK_WANTED_2 | NVREG_IRQ_TIMER;
+ // np->need_linktimer = 1;
+ // np->link_timeout = jiffies + LINK_TIMEOUT;
+ break;
+ case 0x0066:
+ /* Fall Through */
+ case 0x00D6:
+ // DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER
+ np->irqmask = NVREG_IRQMASK_WANTED_2;
+ np->irqmask |= NVREG_IRQ_TIMER;
+ // np->need_linktimer = 1;
+ // np->link_timeout = jiffies + LINK_TIMEOUT;
+ if (np->desc_ver == DESC_VER_1)
+ np->tx_flags |= NV_TX_LASTPACKET1;
+ else
+ np->tx_flags |= NV_TX2_LASTPACKET1;
+ break;
+ case 0x0373:
+ /* Fall Through */
+ case 0x0086:
+ /* Fall Through */
+ case 0x008c:
+ /* Fall Through */
+ case 0x00e6:
+ /* Fall Through */
+ case 0x00df:
+ /* Fall Through */
+ case 0x0056:
+ /* Fall Through */
+ case 0x0057:
+ /* Fall Through */
+ case 0x0037:
+ /* Fall Through */
+ case 0x0038:
+ //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
+ np->irqmask = NVREG_IRQMASK_WANTED_2;
+ np->irqmask |= NVREG_IRQ_TIMER;
+ // np->need_linktimer = 1;
+ // np->link_timeout = jiffies + LINK_TIMEOUT;
+ if (np->desc_ver == DESC_VER_1)
+ np->tx_flags |= NV_TX_LASTPACKET1;
+ else
+ np->tx_flags |= NV_TX2_LASTPACKET1;
+ break;
+ default:
+ printf
+ ("Your card was undefined in this driver. Review driver_data in Linux driver and send a patch\n");
+ }
+
+ /* find a suitable phy */
+ for (i = 1; i < 32; i++) {
+ int id1, id2;
+ id1 = mii_rw(nic, i, MII_PHYSID1, MII_READ);
+ if (id1 < 0 || id1 == 0xffff)
+ continue;
+ id2 = mii_rw(nic, i, MII_PHYSID2, MII_READ);
+ if (id2 < 0 || id2 == 0xffff)
+ continue;
+ id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
+ id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
+ dprintf
+ (("%s: open: Found PHY %hX:%hX at address %d.\n",
+ pci->driver_name, id1, id2, i));
+ np->phyaddr = i;
+ np->phy_oui = id1 | id2;
+ break;
+ }
+ if (i == 32) {
+ /* PHY in isolate mode? No phy attached and user wants to
+ * test loopback? Very odd, but can be correct.
+ */
+ printf
+ ("%s: open: Could not find a valid PHY.\n", pci->driver_name);
+ }
+
+ if (i != 32) {
+ /* reset it */
+ phy_init(nic);
+ }
+
+ dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
+ pci->driver_name, pci->vendor, pci->dev_id, pci->driver_name));
+ if(!forcedeth_reset(nic)) return 0; // no valid link
+
+ /* point to NIC specific routines */
+ nic->nic_op = &forcedeth_operations;
+ return 1;
+}
+
+static struct pci_device_id forcedeth_nics[] = {
+PCI_ROM(0x10de, 0x01C3, "nforce", "nForce NVENET_1 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0066, "nforce2", "nForce NVENET_2 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x00D6, "nforce3", "nForce NVENET_3 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0086, "nforce4", "nForce NVENET_4 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x008c, "nforce5", "nForce NVENET_5 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x00e6, "nforce6", "nForce NVENET_6 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x00df, "nforce7", "nForce NVENET_7 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0056, "nforce8", "nForce NVENET_8 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0057, "nforce9", "nForce NVENET_9 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0037, "nforce10", "nForce NVENET_10 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0038, "nforce11", "nForce NVENET_11 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0373, "nforce15", "nForce NVENET_15 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0269, "nforce16", "nForce NVENET_16 Ethernet Controller", 0),
+PCI_ROM(0x10de, 0x0760, "nforce17", "nForce NVENET_17 Ethernet Controller", MAC_ADDR_CORRECT),
+};
+
+PCI_DRIVER ( forcedeth_driver, forcedeth_nics, PCI_NO_CLASS );
+
+DRIVER ( "forcedeth", nic_driver, pci_driver, forcedeth_driver,
+ forcedeth_probe, forcedeth_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ipoib.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ipoib.c
new file mode 100644
index 0000000..dde4ee5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ipoib.c
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_pathrec.h>
+#include <gpxe/ib_mcast.h>
+#include <gpxe/ipoib.h>
+
+/** @file
+ *
+ * IP over Infiniband
+ */
+
+/** Number of IPoIB send work queue entries */
+#define IPOIB_NUM_SEND_WQES 2
+
+/** Number of IPoIB receive work queue entries */
+#define IPOIB_NUM_RECV_WQES 4
+
+/** Number of IPoIB completion entries */
+#define IPOIB_NUM_CQES 8
+
+/** An IPoIB device */
+struct ipoib_device {
+ /** Network device */
+ struct net_device *netdev;
+ /** Underlying Infiniband device */
+ struct ib_device *ibdev;
+ /** Completion queue */
+ struct ib_completion_queue *cq;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Broadcast MAC */
+ struct ipoib_mac broadcast;
+ /** Joined to IPv4 broadcast multicast group
+ *
+ * This flag indicates whether or not we have initiated the
+ * join to the IPv4 broadcast multicast group.
+ */
+ int broadcast_joined;
+ /** IPv4 broadcast multicast group membership */
+ struct ib_mc_membership broadcast_membership;
+};
+
+/** Broadcast IPoIB address */
+static struct ipoib_mac ipoib_broadcast = {
+ .qpn = htonl ( IB_QPN_BROADCAST ),
+ .gid.u.bytes = { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
+};
+
+/****************************************************************************
+ *
+ * IPoIB peer cache
+ *
+ ****************************************************************************
+ */
+
+/**
+ * IPoIB peer address
+ *
+ * The IPoIB link-layer header is only four bytes long and so does not
+ * have sufficient room to store IPoIB MAC address(es). We therefore
+ * maintain a cache of MAC addresses identified by a single-byte key,
+ * and abuse the spare two bytes within the link-layer header to
+ * communicate these MAC addresses between the link-layer code and the
+ * netdevice driver.
+ */
+struct ipoib_peer {
+ /** Key */
+ uint8_t key;
+ /** MAC address */
+ struct ipoib_mac mac;
+};
+
+/** Number of IPoIB peer cache entries
+ *
+ * Must be a power of two.
+ */
+#define IPOIB_NUM_CACHED_PEERS 4
+
+/** IPoIB peer address cache */
+static struct ipoib_peer ipoib_peer_cache[IPOIB_NUM_CACHED_PEERS];
+
+/** Oldest IPoIB peer cache entry index */
+static unsigned int ipoib_peer_cache_idx = 1;
+
+/**
+ * Look up cached peer by key
+ *
+ * @v key Peer cache key
+ * @ret peer Peer cache entry, or NULL
+ */
+static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) {
+ struct ipoib_peer *peer;
+ unsigned int i;
+
+ for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
+ peer = &ipoib_peer_cache[i];
+ if ( peer->key == key )
+ return peer;
+ }
+
+ if ( key != 0 ) {
+ DBG ( "IPoIB warning: peer cache lost track of key %x while "
+ "still in use\n", key );
+ }
+ return NULL;
+}
+
+/**
+ * Store GID and QPN in peer cache
+ *
+ * @v gid Peer GID
+ * @v qpn Peer QPN
+ * @ret peer Peer cache entry
+ */
+static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) {
+ struct ipoib_peer *peer;
+ unsigned int key;
+ unsigned int i;
+
+ /* Look for existing cache entry */
+ for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
+ peer = &ipoib_peer_cache[i];
+ if ( memcmp ( &peer->mac, mac, sizeof ( peer->mac ) ) == 0 )
+ return peer;
+ }
+
+ /* No entry found: create a new one */
+ key = ipoib_peer_cache_idx++;
+ peer = &ipoib_peer_cache[ key % IPOIB_NUM_CACHED_PEERS ];
+ if ( peer->key )
+ DBG ( "IPoIB peer %x evicted from cache\n", peer->key );
+
+ memset ( peer, 0, sizeof ( *peer ) );
+ peer->key = key;
+ memcpy ( &peer->mac, mac, sizeof ( peer->mac ) );
+ DBG ( "IPoIB peer %x has MAC %s\n",
+ peer->key, ipoib_ntoa ( &peer->mac ) );
+ return peer;
+}
+
+/****************************************************************************
+ *
+ * IPoIB link layer
+ *
+ ****************************************************************************
+ */
+
+/**
+ * Add IPoIB link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+static int ipoib_push ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source __unused, uint16_t net_proto ) {
+ struct ipoib_hdr *ipoib_hdr =
+ iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
+ const struct ipoib_mac *dest_mac = ll_dest;
+ const struct ipoib_mac *src_mac = ll_source;
+ struct ipoib_peer *dest;
+ struct ipoib_peer *src;
+
+ /* Add link-layer addresses to cache */
+ dest = ipoib_cache_peer ( dest_mac );
+ src = ipoib_cache_peer ( src_mac );
+
+ /* Build IPoIB header */
+ ipoib_hdr->proto = net_proto;
+ ipoib_hdr->u.peer.dest = dest->key;
+ ipoib_hdr->u.peer.src = src->key;
+
+ return 0;
+}
+
+/**
+ * Remove IPoIB link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Source link-layer address
+ * @ret net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+static int ipoib_pull ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void **ll_dest,
+ const void **ll_source, uint16_t *net_proto ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ipoib_hdr *ipoib_hdr = iobuf->data;
+ struct ipoib_peer *dest;
+ struct ipoib_peer *source;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
+ DBG ( "IPoIB packet too short for link-layer header\n" );
+ DBG_HD ( iobuf->data, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Strip off IPoIB header */
+ iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
+
+ /* Identify source and destination addresses, and clear
+ * reserved word in IPoIB header
+ */
+ dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
+ source = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.src );
+ ipoib_hdr->u.reserved = 0;
+
+ /* Fill in required fields */
+ *ll_dest = ( dest ? &dest->mac : &ipoib->broadcast );
+ *ll_source = ( source ? &source->mac : &ipoib->broadcast );
+ *net_proto = ipoib_hdr->proto;
+
+ return 0;
+}
+
+/**
+ * Initialise IPoIB link-layer address
+ *
+ * @v hw_addr Hardware address
+ * @v ll_addr Link-layer address
+ */
+static void ipoib_init_addr ( const void *hw_addr, void *ll_addr ) {
+ const struct ib_gid_half *guid = hw_addr;
+ struct ipoib_mac *mac = ll_addr;
+
+ memset ( mac, 0, sizeof ( *mac ) );
+ memcpy ( &mac->gid.u.half[1], guid, sizeof ( mac->gid.u.half[1] ) );
+}
+
+/**
+ * Transcribe IPoIB link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Link-layer address in human-readable format
+ */
+const char * ipoib_ntoa ( const void *ll_addr ) {
+ static char buf[45];
+ const struct ipoib_mac *mac = ll_addr;
+
+ snprintf ( buf, sizeof ( buf ), "%08x:%08x:%08x:%08x:%08x",
+ htonl ( mac->qpn ), htonl ( mac->gid.u.dwords[0] ),
+ htonl ( mac->gid.u.dwords[1] ),
+ htonl ( mac->gid.u.dwords[2] ),
+ htonl ( mac->gid.u.dwords[3] ) );
+ return buf;
+}
+
+/**
+ * Hash multicast address
+ *
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
+ */
+static int ipoib_mc_hash ( unsigned int af __unused,
+ const void *net_addr __unused,
+ void *ll_addr __unused ) {
+
+ return -ENOTSUP;
+}
+
+/** IPoIB protocol */
+struct ll_protocol ipoib_protocol __ll_protocol = {
+ .name = "IPoIB",
+ .ll_proto = htons ( ARPHRD_INFINIBAND ),
+ .hw_addr_len = sizeof ( struct ib_gid_half ),
+ .ll_addr_len = IPOIB_ALEN,
+ .ll_header_len = IPOIB_HLEN,
+ .push = ipoib_push,
+ .pull = ipoib_pull,
+ .init_addr = ipoib_init_addr,
+ .ntoa = ipoib_ntoa,
+ .mc_hash = ipoib_mc_hash,
+};
+
+/**
+ * Allocate IPoIB device
+ *
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * alloc_ipoibdev ( size_t priv_size ) {
+ struct net_device *netdev;
+
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ipoib_protocol;
+ netdev->ll_broadcast = ( uint8_t * ) &ipoib_broadcast;
+ netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE;
+ }
+ return netdev;
+}
+
+/****************************************************************************
+ *
+ * IPoIB network device
+ *
+ ****************************************************************************
+ */
+
+/**
+ * Transmit packet via IPoIB network device
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int ipoib_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct ipoib_hdr *ipoib_hdr;
+ struct ipoib_peer *dest;
+ struct ib_address_vector av;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
+ DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
+ return -EINVAL;
+ }
+ ipoib_hdr = iobuf->data;
+
+ /* Attempting transmission while link is down will put the
+ * queue pair into an error state, so don't try it.
+ */
+ if ( ! ib_link_ok ( ibdev ) )
+ return -ENETUNREACH;
+
+ /* Identify destination address */
+ dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
+ if ( ! dest )
+ return -ENXIO;
+ ipoib_hdr->u.reserved = 0;
+
+ /* Construct address vector */
+ memset ( &av, 0, sizeof ( av ) );
+ av.qpn = ntohl ( dest->mac.qpn );
+ av.gid_present = 1;
+ memcpy ( &av.gid, &dest->mac.gid, sizeof ( av.gid ) );
+ if ( ( rc = ib_resolve_path ( ibdev, &av ) ) != 0 ) {
+ /* Path not resolved yet */
+ return rc;
+ }
+
+ return ib_post_send ( ibdev, ipoib->qp, &av, iobuf );
+}
+
+/**
+ * Handle IPoIB send completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ipoib_complete_send ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+ struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
+
+ netdev_tx_complete_err ( ipoib->netdev, iobuf, rc );
+}
+
+/**
+ * Handle IPoIB receive completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ipoib_complete_recv ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+ struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
+ struct net_device *netdev = ipoib->netdev;
+ struct ipoib_hdr *ipoib_hdr;
+ struct ipoib_mac ll_src;
+ struct ipoib_peer *src;
+
+ if ( rc != 0 ) {
+ netdev_rx_err ( netdev, iobuf, rc );
+ return;
+ }
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( struct ipoib_hdr ) ) {
+ DBGC ( ipoib, "IPoIB %p received packet too short to "
+ "contain IPoIB header\n", ipoib );
+ DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ return;
+ }
+ ipoib_hdr = iobuf->data;
+
+ /* Parse source address */
+ if ( av->gid_present ) {
+ ll_src.qpn = htonl ( av->qpn );
+ memcpy ( &ll_src.gid, &av->gid, sizeof ( ll_src.gid ) );
+ src = ipoib_cache_peer ( &ll_src );
+ ipoib_hdr->u.peer.src = src->key;
+ }
+
+ /* Hand off to network layer */
+ netdev_rx ( netdev, iobuf );
+}
+
+/** IPoIB completion operations */
+static struct ib_completion_queue_operations ipoib_cq_op = {
+ .complete_send = ipoib_complete_send,
+ .complete_recv = ipoib_complete_recv,
+};
+
+/**
+ * Poll IPoIB network device
+ *
+ * @v netdev Network device
+ */
+static void ipoib_poll ( struct net_device *netdev ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+
+ ib_poll_eq ( ibdev );
+}
+
+/**
+ * Enable/disable interrupts on IPoIB network device
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void ipoib_irq ( struct net_device *netdev __unused,
+ int enable __unused ) {
+ /* No implementation */
+}
+
+/**
+ * Handle IPv4 broadcast multicast group join completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ * @v rc Status code
+ * @v mad Response MAD (or NULL on error)
+ */
+void ipoib_join_complete ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp __unused,
+ struct ib_mc_membership *membership, int rc,
+ union ib_mad *mad __unused ) {
+ struct ipoib_device *ipoib = container_of ( membership,
+ struct ipoib_device, broadcast_membership );
+
+ /* Record join status as link status */
+ netdev_link_err ( ipoib->netdev, rc );
+}
+
+/**
+ * Join IPv4 broadcast multicast group
+ *
+ * @v ipoib IPoIB device
+ * @ret rc Return status code
+ */
+static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
+ int rc;
+
+ if ( ( rc = ib_mcast_join ( ipoib->ibdev, ipoib->qp,
+ &ipoib->broadcast_membership,
+ &ipoib->broadcast.gid,
+ ipoib_join_complete ) ) != 0 ) {
+ DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
+ ipoib, strerror ( rc ) );
+ return rc;
+ }
+ ipoib->broadcast_joined = 1;
+
+ return 0;
+}
+
+/**
+ * Leave IPv4 broadcast multicast group
+ *
+ * @v ipoib IPoIB device
+ */
+static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
+
+ if ( ipoib->broadcast_joined ) {
+ ib_mcast_leave ( ipoib->ibdev, ipoib->qp,
+ &ipoib->broadcast_membership );
+ ipoib->broadcast_joined = 0;
+ }
+}
+
+/**
+ * Open IPoIB network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int ipoib_open ( struct net_device *netdev ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+ int rc;
+
+ /* Open IB device */
+ if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
+ DBGC ( ipoib, "IPoIB %p could not open device: %s\n",
+ ipoib, strerror ( rc ) );
+ goto err_ib_open;
+ }
+
+ /* Allocate completion queue */
+ ipoib->cq = ib_create_cq ( ibdev, IPOIB_NUM_CQES, &ipoib_cq_op );
+ if ( ! ipoib->cq ) {
+ DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
+ ipoib );
+ rc = -ENOMEM;
+ goto err_create_cq;
+ }
+
+ /* Allocate queue pair */
+ ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD,
+ IPOIB_NUM_SEND_WQES, ipoib->cq,
+ IPOIB_NUM_RECV_WQES, ipoib->cq );
+ if ( ! ipoib->qp ) {
+ DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n",
+ ipoib );
+ rc = -ENOMEM;
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( ipoib->qp, ipoib );
+
+ /* Update MAC address with QPN */
+ mac->qpn = htonl ( ipoib->qp->qpn );
+
+ /* Fill receive rings */
+ ib_refill_recv ( ibdev, ipoib->qp );
+
+ /* Fake a link status change to join the broadcast group */
+ ipoib_link_state_changed ( ibdev );
+
+ return 0;
+
+ ib_destroy_qp ( ibdev, ipoib->qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, ipoib->cq );
+ err_create_cq:
+ ib_close ( ibdev );
+ err_ib_open:
+ return rc;
+}
+
+/**
+ * Close IPoIB network device
+ *
+ * @v netdev Network device
+ */
+static void ipoib_close ( struct net_device *netdev ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+
+ /* Leave broadcast group */
+ ipoib_leave_broadcast_group ( ipoib );
+
+ /* Remove QPN from MAC address */
+ mac->qpn = 0;
+
+ /* Tear down the queues */
+ ib_destroy_qp ( ibdev, ipoib->qp );
+ ib_destroy_cq ( ibdev, ipoib->cq );
+
+ /* Close IB device */
+ ib_close ( ibdev );
+}
+
+/** IPoIB network device operations */
+static struct net_device_operations ipoib_operations = {
+ .open = ipoib_open,
+ .close = ipoib_close,
+ .transmit = ipoib_transmit,
+ .poll = ipoib_poll,
+ .irq = ipoib_irq,
+};
+
+/**
+ * Handle link status change
+ *
+ * @v ibdev Infiniband device
+ */
+void ipoib_link_state_changed ( struct ib_device *ibdev ) {
+ struct net_device *netdev = ib_get_ownerdata ( ibdev );
+ struct ipoib_device *ipoib = netdev->priv;
+ struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+ int rc;
+
+ /* Leave existing broadcast group */
+ ipoib_leave_broadcast_group ( ipoib );
+
+ /* Update MAC address based on potentially-new GID prefix */
+ memcpy ( &mac->gid.u.half[0], &ibdev->gid.u.half[0],
+ sizeof ( mac->gid.u.half[0] ) );
+
+ /* Update broadcast GID based on potentially-new partition key */
+ ipoib->broadcast.gid.u.words[2] = htons ( ibdev->pkey );
+
+ /* Set net device link state to reflect Infiniband link state */
+ if ( ib_link_ok ( ibdev ) ) {
+ netdev_link_up ( netdev );
+ } else {
+ netdev_link_down ( netdev );
+ }
+
+ /* Join new broadcast group */
+ if ( ib_link_ok ( ibdev ) &&
+ ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) ) {
+ DBGC ( ipoib, "IPoIB %p could not rejoin broadcast group: "
+ "%s\n", ipoib, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Probe IPoIB device
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+int ipoib_probe ( struct ib_device *ibdev ) {
+ struct net_device *netdev;
+ struct ipoib_device *ipoib;
+ int rc;
+
+ /* Allocate network device */
+ netdev = alloc_ipoibdev ( sizeof ( *ipoib ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &ipoib_operations );
+ ipoib = netdev->priv;
+ ib_set_ownerdata ( ibdev, netdev );
+ netdev->dev = ibdev->dev;
+ memset ( ipoib, 0, sizeof ( *ipoib ) );
+ ipoib->netdev = netdev;
+ ipoib->ibdev = ibdev;
+
+ /* Extract hardware address */
+ memcpy ( netdev->hw_addr, &ibdev->gid.u.half[1],
+ sizeof ( ibdev->gid.u.half[1] ) );
+
+ /* Set default broadcast address */
+ memcpy ( &ipoib->broadcast, &ipoib_broadcast,
+ sizeof ( ipoib->broadcast ) );
+ netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ return 0;
+
+ err_register_netdev:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+/**
+ * Remove IPoIB device
+ *
+ * @v ibdev Infiniband device
+ */
+void ipoib_remove ( struct ib_device *ibdev ) {
+ struct net_device *netdev = ib_get_ownerdata ( ibdev );
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/legacy.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/legacy.c
new file mode 100644
index 0000000..4a77c27
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/legacy.c
@@ -0,0 +1,157 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <nic.h>
+
+/*
+ * Quick and dirty compatibility layer
+ *
+ * This should allow old-API PCI drivers to at least function until
+ * they are updated. It will not help non-PCI drivers.
+ *
+ * No drivers should rely on this code. It will be removed asap.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct nic nic;
+
+static int legacy_registered = 0;
+
+static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ struct nic *nic = netdev->priv;
+ struct ethhdr *ethhdr;
+
+ DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) );
+ iob_pad ( iobuf, ETH_ZLEN );
+ ethhdr = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *ethhdr ) );
+ nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
+ ntohs ( ethhdr->h_protocol ),
+ iob_len ( iobuf ), iobuf->data );
+ netdev_tx_complete ( netdev, iobuf );
+ return 0;
+}
+
+static void legacy_poll ( struct net_device *netdev ) {
+ struct nic *nic = netdev->priv;
+ struct io_buffer *iobuf;
+
+ iobuf = alloc_iob ( ETH_FRAME_LEN );
+ if ( ! iobuf )
+ return;
+
+ nic->packet = iobuf->data;
+ if ( nic->nic_op->poll ( nic, 1 ) ) {
+ DBG ( "Received %d bytes\n", nic->packetlen );
+ iob_put ( iobuf, nic->packetlen );
+ netdev_rx ( netdev, iobuf );
+ } else {
+ free_iob ( iobuf );
+ }
+}
+
+static int legacy_open ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+static void legacy_close ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
+static void legacy_irq ( struct net_device *netdev __unused, int enable ) {
+ struct nic *nic = netdev->priv;
+
+ nic->nic_op->irq ( nic, ( enable ? ENABLE : DISABLE ) );
+}
+
+static struct net_device_operations legacy_operations = {
+ .open = legacy_open,
+ .close = legacy_close,
+ .transmit = legacy_transmit,
+ .poll = legacy_poll,
+ .irq = legacy_irq,
+};
+
+int legacy_probe ( void *hwdev,
+ void ( * set_drvdata ) ( void *hwdev, void *priv ),
+ struct device *dev,
+ int ( * probe ) ( struct nic *nic, void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
+ struct net_device *netdev;
+ int rc;
+
+ if ( legacy_registered )
+ return -EBUSY;
+
+ netdev = alloc_etherdev ( 0 );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &legacy_operations );
+ netdev->priv = &nic;
+ memset ( &nic, 0, sizeof ( nic ) );
+ set_drvdata ( hwdev, netdev );
+ netdev->dev = dev;
+
+ nic.node_addr = netdev->hw_addr;
+ // nic.irqno = dev->desc.irq;
+
+ if ( ! probe ( &nic, hwdev ) ) {
+ rc = -ENODEV;
+ goto err_probe;
+ }
+
+ /* Overwrite the IRQ number. Some legacy devices set
+ * nic->irqno to 0 in the probe routine to indicate that they
+ * don't support interrupts; doing this allows the timer
+ * interrupt to be used instead.
+ */
+ // dev->desc.irq = nic.irqno;
+
+ /* Mark as link up; legacy devices don't handle link state */
+ netdev_link_up ( netdev );
+
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register;
+
+ /* Do not remove this message */
+ printf ( "WARNING: Using legacy NIC wrapper on %s\n",
+ netdev->ll_protocol->ntoa ( nic.node_addr ) );
+
+ legacy_registered = 1;
+ return 0;
+
+ err_register:
+ disable ( &nic, hwdev );
+ err_probe:
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+void legacy_remove ( void *hwdev,
+ void * ( * get_drvdata ) ( void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) ) {
+ struct net_device *netdev = get_drvdata ( hwdev );
+ struct nic *nic = netdev->priv;
+
+ unregister_netdev ( netdev );
+ disable ( nic, hwdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ legacy_registered = 0;
+}
+
+int dummy_connect ( struct nic *nic __unused ) {
+ return 1;
+}
+
+void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) {
+ return;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/mtd80x.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/mtd80x.c
new file mode 100644
index 0000000..7cf59b0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/mtd80x.c
@@ -0,0 +1,1022 @@
+/**************************************************************************
+*
+* mtd80x.c: Etherboot device driver for the mtd80x Ethernet chip.
+* Written 2004-2004 by Erdem Güven <zuencap@yahoo.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* fealnx.c: A Linux device driver for the mtd80x Ethernet chip
+* Written 1998-2000 by Donald Becker
+*
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include <mii.h>
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+#define get_unaligned(ptr) (*(ptr))
+
+
+/* Operational parameters that are set at compile time. */
+
+/* Keep the ring sizes a power of two for compile efficiency. */
+/* The compiler will convert <unsigned>'%'<2^N> into a bit mask. */
+/* Making the Tx ring too large decreases the effectiveness of channel */
+/* bonding and packet priority. */
+/* There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE 2
+#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
+#define RX_RING_SIZE 4
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define HZ 100
+#define TX_TIME_OUT (6*HZ)
+
+/* Allocation size of Rx buffers with normal sized Ethernet frames.
+ Do not change this value without good reason. This is not a limit,
+ but a way to keep a consistent allocation size among drivers.
+ */
+#define PKT_BUF_SZ 1536
+
+/* for different PHY */
+enum phy_type_flags {
+ MysonPHY = 1,
+ AhdocPHY = 2,
+ SeeqPHY = 3,
+ MarvellPHY = 4,
+ Myson981 = 5,
+ LevelOnePHY = 6,
+ OtherPHY = 10,
+};
+
+/* A chip capabilities table*/
+enum chip_capability_flags {
+ HAS_MII_XCVR,
+ HAS_CHIP_XCVR,
+};
+
+#if 0 /* not used */
+static
+struct chip_info
+{
+ u16 dev_id;
+ int flag;
+}
+mtd80x_chips[] = {
+ {0x0800, HAS_MII_XCVR},
+ {0x0803, HAS_CHIP_XCVR},
+ {0x0891, HAS_MII_XCVR}
+ };
+static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
+#endif
+
+/* Offsets to the Command and Status Registers. */
+enum mtd_offsets {
+ PAR0 = 0x0, /* physical address 0-3 */
+ PAR1 = 0x04, /* physical address 4-5 */
+ MAR0 = 0x08, /* multicast address 0-3 */
+ MAR1 = 0x0C, /* multicast address 4-7 */
+ FAR0 = 0x10, /* flow-control address 0-3 */
+ FAR1 = 0x14, /* flow-control address 4-5 */
+ TCRRCR = 0x18, /* receive & transmit configuration */
+ BCR = 0x1C, /* bus command */
+ TXPDR = 0x20, /* transmit polling demand */
+ RXPDR = 0x24, /* receive polling demand */
+ RXCWP = 0x28, /* receive current word pointer */
+ TXLBA = 0x2C, /* transmit list base address */
+ RXLBA = 0x30, /* receive list base address */
+ ISR = 0x34, /* interrupt status */
+ IMR = 0x38, /* interrupt mask */
+ FTH = 0x3C, /* flow control high/low threshold */
+ MANAGEMENT = 0x40, /* bootrom/eeprom and mii management */
+ TALLY = 0x44, /* tally counters for crc and mpa */
+ TSR = 0x48, /* tally counter for transmit status */
+ BMCRSR = 0x4c, /* basic mode control and status */
+ PHYIDENTIFIER = 0x50, /* phy identifier */
+ ANARANLPAR = 0x54, /* auto-negotiation advertisement and link
+ partner ability */
+ ANEROCR = 0x58, /* auto-negotiation expansion and pci conf. */
+ BPREMRPSR = 0x5c, /* bypass & receive error mask and phy status */
+};
+
+/* Bits in the interrupt status/enable registers. */
+/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
+enum intr_status_bits {
+ RFCON = 0x00020000, /* receive flow control xon packet */
+ RFCOFF = 0x00010000, /* receive flow control xoff packet */
+ LSCStatus = 0x00008000, /* link status change */
+ ANCStatus = 0x00004000, /* autonegotiation completed */
+ FBE = 0x00002000, /* fatal bus error */
+ FBEMask = 0x00001800, /* mask bit12-11 */
+ ParityErr = 0x00000000, /* parity error */
+ TargetErr = 0x00001000, /* target abort */
+ MasterErr = 0x00000800, /* master error */
+ TUNF = 0x00000400, /* transmit underflow */
+ ROVF = 0x00000200, /* receive overflow */
+ ETI = 0x00000100, /* transmit early int */
+ ERI = 0x00000080, /* receive early int */
+ CNTOVF = 0x00000040, /* counter overflow */
+ RBU = 0x00000020, /* receive buffer unavailable */
+ TBU = 0x00000010, /* transmit buffer unavilable */
+ TI = 0x00000008, /* transmit interrupt */
+ RI = 0x00000004, /* receive interrupt */
+ RxErr = 0x00000002, /* receive error */
+};
+
+/* Bits in the NetworkConfig register. */
+enum rx_mode_bits {
+ RxModeMask = 0xe0,
+ AcceptAllPhys = 0x80, /* promiscuous mode */
+ AcceptBroadcast = 0x40, /* accept broadcast */
+ AcceptMulticast = 0x20, /* accept mutlicast */
+ AcceptRunt = 0x08, /* receive runt pkt */
+ ALP = 0x04, /* receive long pkt */
+ AcceptErr = 0x02, /* receive error pkt */
+
+ AcceptMyPhys = 0x00000000,
+ RxEnable = 0x00000001,
+ RxFlowCtrl = 0x00002000,
+ TxEnable = 0x00040000,
+ TxModeFDX = 0x00100000,
+ TxThreshold = 0x00e00000,
+
+ PS1000 = 0x00010000,
+ PS10 = 0x00080000,
+ FD = 0x00100000,
+};
+
+/* Bits in network_desc.status */
+enum rx_desc_status_bits {
+ RXOWN = 0x80000000, /* own bit */
+ FLNGMASK = 0x0fff0000, /* frame length */
+ FLNGShift = 16,
+ MARSTATUS = 0x00004000, /* multicast address received */
+ BARSTATUS = 0x00002000, /* broadcast address received */
+ PHYSTATUS = 0x00001000, /* physical address received */
+ RXFSD = 0x00000800, /* first descriptor */
+ RXLSD = 0x00000400, /* last descriptor */
+ ErrorSummary = 0x80, /* error summary */
+ RUNT = 0x40, /* runt packet received */
+ LONG = 0x20, /* long packet received */
+ FAE = 0x10, /* frame align error */
+ CRC = 0x08, /* crc error */
+ RXER = 0x04, /* receive error */
+};
+
+enum rx_desc_control_bits {
+ RXIC = 0x00800000, /* interrupt control */
+ RBSShift = 0,
+};
+
+enum tx_desc_status_bits {
+ TXOWN = 0x80000000, /* own bit */
+ JABTO = 0x00004000, /* jabber timeout */
+ CSL = 0x00002000, /* carrier sense lost */
+ LC = 0x00001000, /* late collision */
+ EC = 0x00000800, /* excessive collision */
+ UDF = 0x00000400, /* fifo underflow */
+ DFR = 0x00000200, /* deferred */
+ HF = 0x00000100, /* heartbeat fail */
+ NCRMask = 0x000000ff, /* collision retry count */
+ NCRShift = 0,
+};
+
+enum tx_desc_control_bits {
+ TXIC = 0x80000000, /* interrupt control */
+ ETIControl = 0x40000000, /* early transmit interrupt */
+ TXLD = 0x20000000, /* last descriptor */
+ TXFD = 0x10000000, /* first descriptor */
+ CRCEnable = 0x08000000, /* crc control */
+ PADEnable = 0x04000000, /* padding control */
+ RetryTxLC = 0x02000000, /* retry late collision */
+ PKTSMask = 0x3ff800, /* packet size bit21-11 */
+ PKTSShift = 11,
+ TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */
+ TBSShift = 0,
+};
+
+/* BootROM/EEPROM/MII Management Register */
+#define MASK_MIIR_MII_READ 0x00000000
+#define MASK_MIIR_MII_WRITE 0x00000008
+#define MASK_MIIR_MII_MDO 0x00000004
+#define MASK_MIIR_MII_MDI 0x00000002
+#define MASK_MIIR_MII_MDC 0x00000001
+
+/* ST+OP+PHYAD+REGAD+TA */
+#define OP_READ 0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
+#define OP_WRITE 0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */
+
+/* ------------------------------------------------------------------------- */
+/* Constants for Myson PHY */
+/* ------------------------------------------------------------------------- */
+#define MysonPHYID 0xd0000302
+/* 89-7-27 add, (begin) */
+#define MysonPHYID0 0x0302
+#define StatusRegister 18
+#define SPEED100 0x0400 // bit10
+#define FULLMODE 0x0800 // bit11
+/* 89-7-27 add, (end) */
+
+/* ------------------------------------------------------------------------- */
+/* Constants for Seeq 80225 PHY */
+/* ------------------------------------------------------------------------- */
+#define SeeqPHYID0 0x0016
+
+#define MIIRegister18 18
+#define SPD_DET_100 0x80
+#define DPLX_DET_FULL 0x40
+
+/* ------------------------------------------------------------------------- */
+/* Constants for Ahdoc 101 PHY */
+/* ------------------------------------------------------------------------- */
+#define AhdocPHYID0 0x0022
+
+#define DiagnosticReg 18
+#define DPLX_FULL 0x0800
+#define Speed_100 0x0400
+
+/* 89/6/13 add, */
+/* -------------------------------------------------------------------------- */
+/* Constants */
+/* -------------------------------------------------------------------------- */
+#define MarvellPHYID0 0x0141
+#define LevelOnePHYID0 0x0013
+
+#define MII1000BaseTControlReg 9
+#define MII1000BaseTStatusReg 10
+#define SpecificReg 17
+
+/* for 1000BaseT Control Register */
+#define PHYAbletoPerform1000FullDuplex 0x0200
+#define PHYAbletoPerform1000HalfDuplex 0x0100
+#define PHY1000AbilityMask 0x300
+
+// for phy specific status register, marvell phy.
+#define SpeedMask 0x0c000
+#define Speed_1000M 0x08000
+#define Speed_100M 0x4000
+#define Speed_10M 0
+#define Full_Duplex 0x2000
+
+// 89/12/29 add, for phy specific status register, levelone phy, (begin)
+#define LXT1000_100M 0x08000
+#define LXT1000_1000M 0x0c000
+#define LXT1000_Full 0x200
+// 89/12/29 add, for phy specific status register, levelone phy, (end)
+
+#if 0
+/* for 3-in-1 case */
+#define PS10 0x00080000
+#define FD 0x00100000
+#define PS1000 0x00010000
+#endif
+
+/* for PHY */
+#define LinkIsUp 0x0004
+#define LinkIsUp2 0x00040000
+
+/* Create a static buffer of size PKT_BUF_SZ for each
+RX and TX Descriptor. All descriptors point to a
+part of this buffer */
+struct {
+ u8 txb[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned(8)));
+ u8 rxb[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned(8)));
+} mtd80x_bufs __shared;
+#define txb mtd80x_bufs.txb
+#define rxb mtd80x_bufs.rxb
+
+/* The Tulip Rx and Tx buffer descriptors. */
+struct mtd_desc
+{
+ s32 status;
+ s32 control;
+ u32 buffer;
+ u32 next_desc;
+ struct mtd_desc *next_desc_logical;
+ u8* skbuff;
+ u32 reserved1;
+ u32 reserved2;
+};
+
+struct mtd_private
+{
+ struct mtd_desc rx_ring[RX_RING_SIZE];
+ struct mtd_desc tx_ring[TX_RING_SIZE];
+
+ /* Frequently used values: keep some adjacent for cache effect. */
+ int flags;
+ struct pci_dev *pci_dev;
+ unsigned long crvalue;
+ unsigned long bcrvalue;
+ /*unsigned long imrvalue;*/
+ struct mtd_desc *cur_rx;
+ struct mtd_desc *lack_rxbuf;
+ int really_rx_count;
+ struct mtd_desc *cur_tx;
+ struct mtd_desc *cur_tx_copy;
+ int really_tx_count;
+ int free_tx_count;
+ unsigned int rx_buf_sz; /* Based on MTU+slack. */
+
+ /* These values are keep track of the transceiver/media in use. */
+ unsigned int linkok;
+ unsigned int line_speed;
+ unsigned int duplexmode;
+ unsigned int default_port:
+ 4; /* Last dev->if_port value. */
+ unsigned int PHYType;
+
+ /* MII transceiver section. */
+ int mii_cnt; /* MII device addresses. */
+ unsigned char phys[1]; /* MII device addresses. */
+
+ /*other*/
+ const char *nic_name;
+ int ioaddr;
+ u16 dev_id;
+};
+
+static struct mtd_private mtdx;
+
+static int mdio_read(struct nic * , int phy_id, int location);
+static void getlinktype(struct nic * );
+static void getlinkstatus(struct nic * );
+static void set_rx_mode(struct nic *);
+
+/**************************************************************************
+ * init_ring - setup the tx and rx descriptors
+ *************************************************************************/
+static void init_ring(struct nic *nic __unused)
+{
+ int i;
+
+ mtdx.cur_rx = &mtdx.rx_ring[0];
+
+ mtdx.rx_buf_sz = PKT_BUF_SZ;
+ /*mtdx.rx_head_desc = &mtdx.rx_ring[0];*/
+
+ /* Initialize all Rx descriptors. */
+ /* Fill in the Rx buffers. Handle allocation failure gracefully. */
+ for (i = 0; i < RX_RING_SIZE; i++)
+ {
+ mtdx.rx_ring[i].status = RXOWN;
+ mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift;
+ mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]);
+ mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1];
+ mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
+ mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ];
+ }
+ /* Mark the last entry as wrapping the ring. */
+ mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]);
+ mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0];
+
+ /* We only use one transmit buffer, but two
+ * descriptors so transmit engines have somewhere
+ * to point should they feel the need */
+ mtdx.tx_ring[0].status = 0x00000000;
+ mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]);
+ mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]);
+
+ /* This descriptor is never used */
+ mtdx.tx_ring[1].status = 0x00000000;
+ mtdx.tx_ring[1].buffer = 0; /*virt_to_bus(&txb[1]); */
+ mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]);
+
+ return;
+}
+
+/**************************************************************************
+RESET - Reset Adapter
+***************************************************************************/
+static void mtd_reset( struct nic *nic )
+{
+ /* Reset the chip to erase previous misconfiguration. */
+ outl(0x00000001, mtdx.ioaddr + BCR);
+
+ init_ring(nic);
+
+ outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA);
+ outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
+
+ /* Initialize other registers. */
+ /* Configure the PCI bus bursts and FIFO thresholds. */
+ mtdx.bcrvalue = 0x10; /* little-endian, 8 burst length */
+ mtdx.crvalue = 0xa00; /* rx 128 burst length */
+
+ if ( mtdx.dev_id == 0x891 ) {
+ mtdx.bcrvalue |= 0x200; /* set PROG bit */
+ mtdx.crvalue |= 0x02000000; /* set enhanced bit */
+ }
+
+ outl( mtdx.bcrvalue, mtdx.ioaddr + BCR);
+
+ /* Restart Rx engine if stopped. */
+ outl(0, mtdx.ioaddr + RXPDR);
+
+ getlinkstatus(nic);
+ if (mtdx.linkok)
+ {
+ static const char* texts[]={"half","full","10","100","1000"};
+ getlinktype(nic);
+ DBG ( "Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] );
+ } else
+ {
+ DBG ( "No link!!!\n" );
+ }
+
+ mtdx.crvalue |= /*TxEnable |*/ RxEnable | TxThreshold;
+ set_rx_mode(nic);
+
+ /* Clear interrupts by setting the interrupt mask. */
+ outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR);
+ outl( 0, mtdx.ioaddr + IMR);
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int mtd_poll(struct nic *nic, __unused int retrieve)
+{
+ s32 rx_status = mtdx.cur_rx->status;
+ int retval = 0;
+
+ if( ( rx_status & RXOWN ) != 0 )
+ {
+ return 0;
+ }
+
+ if (rx_status & ErrorSummary)
+ { /* there was a fatal error */
+ printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n",
+ mtdx.nic_name, (unsigned int) rx_status,
+ (rx_status & (LONG | RUNT)) ? "length_error ":"",
+ (rx_status & RXER) ? "frame_error ":"",
+ (rx_status & CRC) ? "crc_error ":"" );
+ retval = 0;
+ } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) )
+ {
+ /* this pkt is too long, over one rx buffer */
+ printf("Pkt is too long, over one rx buffer.\n");
+ retval = 0;
+ } else
+ { /* this received pkt is ok */
+ /* Omit the four octet CRC from the length. */
+ short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
+
+ DBG ( " netdev_rx() normal Rx pkt length %d"
+ " status %x.\n", pkt_len, (unsigned int) rx_status );
+
+ nic->packetlen = pkt_len;
+ memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len);
+
+ retval = 1;
+ }
+
+ while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
+ {
+ mtdx.cur_rx->status = RXOWN;
+ mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
+ }
+
+ /* Restart Rx engine if stopped. */
+ outl(0, mtdx.ioaddr + RXPDR);
+
+ return retval;
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void mtd_transmit(
+ struct nic *nic,
+ const char *dest, /* Destination */
+ unsigned int type, /* Type */
+ unsigned int size, /* size */
+ const char *data) /* Packet */
+{
+ u32 to;
+ u32 tx_status;
+ unsigned int nstype = htons ( type );
+
+ memcpy( txb, dest, ETH_ALEN );
+ memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN );
+ memcpy( txb + 2 * ETH_ALEN, &nstype, 2 );
+ memcpy( txb + ETH_HLEN, data, size );
+
+ size += ETH_HLEN;
+ size &= 0x0FFF;
+ while( size < ETH_ZLEN )
+ {
+ txb[size++] = '\0';
+ }
+
+ mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable;
+ mtdx.tx_ring[0].control |= (size << PKTSShift); /* pkt size */
+ mtdx.tx_ring[0].control |= (size << TBSShift); /* buffer size */
+ mtdx.tx_ring[0].status = TXOWN;
+
+ /* Point to transmit descriptor */
+ outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
+ /* Enable Tx */
+ outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR);
+ /* Wake the potentially-idle transmit channel. */
+ outl(0, mtdx.ioaddr + TXPDR);
+
+ to = currticks() + TX_TIME_OUT;
+ while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to));
+
+ /* Disable Tx */
+ outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR);
+
+ tx_status = mtdx.tx_ring[0].status;
+ if (currticks() >= to){
+ DBG ( "TX Time Out" );
+ } else if( tx_status & (CSL | LC | EC | UDF | HF)){
+ printf( "Transmit error: %8.8x %s %s %s %s %s\n",
+ (unsigned int) tx_status,
+ tx_status & EC ? "abort" : "",
+ tx_status & CSL ? "carrier" : "",
+ tx_status & LC ? "late" : "",
+ tx_status & UDF ? "fifo" : "",
+ tx_status & HF ? "heartbeat" : "" );
+ }
+
+ /*hex_dump( txb, size );*/
+ /*pause();*/
+
+ DBG ( "TRANSMIT\n" );
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void mtd_disable ( struct nic *nic ) {
+
+ /* Disable Tx Rx*/
+ outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
+
+ /* Reset the chip to erase previous misconfiguration. */
+ mtd_reset(nic);
+
+ DBG ( "DISABLE\n" );
+}
+
+static struct nic_operations mtd_operations = {
+ .connect = dummy_connect,
+ .poll = mtd_poll,
+ .transmit = mtd_transmit,
+ .irq = dummy_irq,
+
+};
+
+static struct pci_device_id mtd80x_nics[] = {
+ PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800", 0),
+ PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X", 0),
+ PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891", 0),
+};
+
+PCI_DRIVER ( mtd80x_driver, mtd80x_nics, PCI_NO_CLASS );
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+
+static int mtd_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ adjust_pci_device(pci);
+
+ nic->ioaddr = pci->ioaddr;
+ nic->irqno = 0;
+
+ mtdx.nic_name = pci->driver_name;
+ mtdx.dev_id = pci->device;
+ mtdx.ioaddr = nic->ioaddr;
+
+ /* read ethernet id */
+ for (i = 0; i < 6; ++i)
+ {
+ nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i);
+ }
+
+ if (memcmp(nic->node_addr, "\0\0\0\0\0\0", 6) == 0)
+ {
+ return 0;
+ }
+
+ DBG ( "%s: ioaddr %4.4x MAC %s\n", mtdx.nic_name, mtdx.ioaddr, eth_ntoa ( nic->node_addr ) );
+
+ /* Reset the chip to erase previous misconfiguration. */
+ outl(0x00000001, mtdx.ioaddr + BCR);
+
+ /* find the connected MII xcvrs */
+
+ if( mtdx.dev_id != 0x803 )
+ {
+ int phy, phy_idx = 0;
+
+ for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
+ int mii_status = mdio_read(nic, phy, 1);
+
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ mtdx.phys[phy_idx] = phy;
+
+ DBG ( "%s: MII PHY found at address %d, status "
+ "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
+ /* get phy type */
+ {
+ unsigned int data;
+
+ data = mdio_read(nic, mtdx.phys[phy_idx], 2);
+ if (data == SeeqPHYID0)
+ mtdx.PHYType = SeeqPHY;
+ else if (data == AhdocPHYID0)
+ mtdx.PHYType = AhdocPHY;
+ else if (data == MarvellPHYID0)
+ mtdx.PHYType = MarvellPHY;
+ else if (data == MysonPHYID0)
+ mtdx.PHYType = Myson981;
+ else if (data == LevelOnePHYID0)
+ mtdx.PHYType = LevelOnePHY;
+ else
+ mtdx.PHYType = OtherPHY;
+ }
+ phy_idx++;
+ }
+ }
+
+ mtdx.mii_cnt = phy_idx;
+ if (phy_idx == 0) {
+ printf("%s: MII PHY not found -- this device may "
+ "not operate correctly.\n", mtdx.nic_name);
+ }
+ } else {
+ mtdx.phys[0] = 32;
+ /* get phy type */
+ if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) {
+ mtdx.PHYType = MysonPHY;
+ DBG ( "MysonPHY\n" );
+ } else {
+ mtdx.PHYType = OtherPHY;
+ DBG ( "OtherPHY\n" );
+ }
+ }
+
+ getlinkstatus(nic);
+ if( !mtdx.linkok )
+ {
+ printf("No link!!!\n");
+ return 0;
+ }
+
+ mtd_reset( nic );
+
+ /* point to NIC specific routines */
+ nic->nic_op = &mtd_operations;
+ return 1;
+}
+
+
+/**************************************************************************/
+static void set_rx_mode(struct nic *nic __unused)
+{
+ u32 mc_filter[2]; /* Multicast hash filter */
+ u32 rx_mode;
+
+ /* Too many to match, or accept all multicasts. */
+ mc_filter[1] = mc_filter[0] = ~0;
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+
+ outl(mc_filter[0], mtdx.ioaddr + MAR0);
+ outl(mc_filter[1], mtdx.ioaddr + MAR1);
+
+ mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode;
+ outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR);
+}
+/**************************************************************************/
+static unsigned int m80x_read_tick(void)
+/* function: Reads the Timer tick count register which decrements by 2 from */
+/* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */
+/* count represents 838 nsec's. */
+/* input : none. */
+/* output : none. */
+{
+ unsigned char tmp;
+ int value;
+
+ outb((char) 0x06, 0x43); // Command 8254 to latch T0's count
+
+ // now read the count.
+ tmp = (unsigned char) inb(0x40);
+ value = ((int) tmp) << 8;
+ tmp = (unsigned char) inb(0x40);
+ value |= (((int) tmp) & 0xff);
+ return (value);
+}
+
+static void m80x_delay(unsigned int interval)
+/* function: to wait for a specified time. */
+/* input : interval ... the specified time. */
+/* output : none. */
+{
+ unsigned int interval1, interval2, i = 0;
+
+ interval1 = m80x_read_tick(); // get initial value
+ do
+ {
+ interval2 = m80x_read_tick();
+ if (interval1 < interval2)
+ interval1 += 65536;
+ ++i;
+ } while (((interval1 - interval2) < (u16) interval) && (i < 65535));
+}
+
+
+static u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
+{
+ u32 miir;
+ int i;
+ unsigned int mask, data;
+
+ /* enable MII output */
+ miir = (u32) inl(miiport);
+ miir &= 0xfffffff0;
+
+ miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
+
+ /* send 32 1's preamble */
+ for (i = 0; i < 32; i++) {
+ /* low MDC; MDO is already high (miir) */
+ miir &= ~MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+
+ /* high MDC */
+ miir |= MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+ }
+
+ /* calculate ST+OP+PHYAD+REGAD+TA */
+ data = opcode | (phyad << 7) | (regad << 2);
+
+ /* sent out */
+ mask = 0x8000;
+ while (mask) {
+ /* low MDC, prepare MDO */
+ miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
+ if (mask & data)
+ miir |= MASK_MIIR_MII_MDO;
+
+ outl(miir, miiport);
+ /* high MDC */
+ miir |= MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+ m80x_delay(30);
+
+ /* next */
+ mask >>= 1;
+ if (mask == 0x2 && opcode == OP_READ)
+ miir &= ~MASK_MIIR_MII_WRITE;
+ }
+ return miir;
+}
+
+static int mdio_read(struct nic *nic __unused, int phyad, int regad)
+{
+ long miiport = mtdx.ioaddr + MANAGEMENT;
+ u32 miir;
+ unsigned int mask, data;
+
+ miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
+
+ /* read data */
+ mask = 0x8000;
+ data = 0;
+ while (mask)
+ {
+ /* low MDC */
+ miir &= ~MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+
+ /* read MDI */
+ miir = inl(miiport);
+ if (miir & MASK_MIIR_MII_MDI)
+ data |= mask;
+
+ /* high MDC, and wait */
+ miir |= MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+ m80x_delay((int) 30);
+
+ /* next */
+ mask >>= 1;
+ }
+
+ /* low MDC */
+ miir &= ~MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+
+ return data & 0xffff;
+}
+
+#if 0 /* not used */
+static void mdio_write(struct nic *nic __unused, int phyad, int regad,
+ int data)
+{
+ long miiport = mtdx.ioaddr + MANAGEMENT;
+ u32 miir;
+ unsigned int mask;
+
+ miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
+
+ /* write data */
+ mask = 0x8000;
+ while (mask)
+ {
+ /* low MDC, prepare MDO */
+ miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
+ if (mask & data)
+ miir |= MASK_MIIR_MII_MDO;
+ outl(miir, miiport);
+
+ /* high MDC */
+ miir |= MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+
+ /* next */
+ mask >>= 1;
+ }
+
+ /* low MDC */
+ miir &= ~MASK_MIIR_MII_MDC;
+ outl(miir, miiport);
+
+ return;
+}
+#endif
+
+static void getlinkstatus(struct nic *nic)
+/* function: Routine will read MII Status Register to get link status. */
+/* input : dev... pointer to the adapter block. */
+/* output : none. */
+{
+ unsigned int i, DelayTime = 0x1000;
+
+ mtdx.linkok = 0;
+
+ if (mtdx.PHYType == MysonPHY)
+ {
+ for (i = 0; i < DelayTime; ++i) {
+ if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) {
+ mtdx.linkok = 1;
+ return;
+ }
+ // delay
+ m80x_delay(100);
+ }
+ } else
+ {
+ for (i = 0; i < DelayTime; ++i) {
+ if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
+ mtdx.linkok = 1;
+ return;
+ }
+ // delay
+ m80x_delay(100);
+ }
+ }
+}
+
+
+static void getlinktype(struct nic *dev)
+{
+ if (mtdx.PHYType == MysonPHY)
+ { /* 3-in-1 case */
+ if (inl(mtdx.ioaddr + TCRRCR) & FD)
+ mtdx.duplexmode = 2; /* full duplex */
+ else
+ mtdx.duplexmode = 1; /* half duplex */
+ if (inl(mtdx.ioaddr + TCRRCR) & PS10)
+ mtdx.line_speed = 1; /* 10M */
+ else
+ mtdx.line_speed = 2; /* 100M */
+ } else
+ {
+ if (mtdx.PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */
+ unsigned int data;
+
+ data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
+ if (data & SPD_DET_100)
+ mtdx.line_speed = 2; /* 100M */
+ else
+ mtdx.line_speed = 1; /* 10M */
+ if (data & DPLX_DET_FULL)
+ mtdx.duplexmode = 2; /* full duplex mode */
+ else
+ mtdx.duplexmode = 1; /* half duplex mode */
+ } else if (mtdx.PHYType == AhdocPHY) {
+ unsigned int data;
+
+ data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
+ if (data & Speed_100)
+ mtdx.line_speed = 2; /* 100M */
+ else
+ mtdx.line_speed = 1; /* 10M */
+ if (data & DPLX_FULL)
+ mtdx.duplexmode = 2; /* full duplex mode */
+ else
+ mtdx.duplexmode = 1; /* half duplex mode */
+ }
+ /* 89/6/13 add, (begin) */
+ else if (mtdx.PHYType == MarvellPHY) {
+ unsigned int data;
+
+ data = mdio_read(dev, mtdx.phys[0], SpecificReg);
+ if (data & Full_Duplex)
+ mtdx.duplexmode = 2; /* full duplex mode */
+ else
+ mtdx.duplexmode = 1; /* half duplex mode */
+ data &= SpeedMask;
+ if (data == Speed_1000M)
+ mtdx.line_speed = 3; /* 1000M */
+ else if (data == Speed_100M)
+ mtdx.line_speed = 2; /* 100M */
+ else
+ mtdx.line_speed = 1; /* 10M */
+ }
+ /* 89/6/13 add, (end) */
+ /* 89/7/27 add, (begin) */
+ else if (mtdx.PHYType == Myson981) {
+ unsigned int data;
+
+ data = mdio_read(dev, mtdx.phys[0], StatusRegister);
+
+ if (data & SPEED100)
+ mtdx.line_speed = 2;
+ else
+ mtdx.line_speed = 1;
+
+ if (data & FULLMODE)
+ mtdx.duplexmode = 2;
+ else
+ mtdx.duplexmode = 1;
+ }
+ /* 89/7/27 add, (end) */
+ /* 89/12/29 add */
+ else if (mtdx.PHYType == LevelOnePHY) {
+ unsigned int data;
+
+ data = mdio_read(dev, mtdx.phys[0], SpecificReg);
+ if (data & LXT1000_Full)
+ mtdx.duplexmode = 2; /* full duplex mode */
+ else
+ mtdx.duplexmode = 1; /* half duplex mode */
+ data &= SpeedMask;
+ if (data == LXT1000_1000M)
+ mtdx.line_speed = 3; /* 1000M */
+ else if (data == LXT1000_100M)
+ mtdx.line_speed = 2; /* 100M */
+ else
+ mtdx.line_speed = 1; /* 10M */
+ }
+ // chage crvalue
+ // mtdx.crvalue&=(~PS10)&(~FD);
+ mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
+ if (mtdx.line_speed == 1)
+ mtdx.crvalue |= PS10;
+ else if (mtdx.line_speed == 3)
+ mtdx.crvalue |= PS1000;
+ if (mtdx.duplexmode == 2)
+ mtdx.crvalue |= FD;
+ }
+}
+
+DRIVER ( "MTD80X", nic_driver, pci_driver, mtd80x_driver,
+ mtd_probe, mtd_disable );
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.c
new file mode 100644
index 0000000..8ca6271
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.c
@@ -0,0 +1,609 @@
+/*
+ natsemi.c - gPXE driver for the NatSemi DP8381x series.
+
+ Based on:
+
+ natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
+
+ Copyright (C) 2001 Entity Cyber, Inc.
+
+ This development of this Etherboot driver was funded by
+
+ Sicom Systems: http://www.sicompos.com/
+
+ Author: Marty Connor <mdc@etherboot.org>
+ Adapted from a Linux driver which was written by Donald Becker
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License (GPL), incorporated herein by reference.
+
+ Original Copyright Notice:
+
+ Written/copyright 1999-2001 by Donald Becker.
+
+ This software may be used and distributed according to the terms of
+ the GNU General Public License (GPL), incorporated herein by reference.
+ Drivers based on or derived from this code fall under the GPL and must
+ retain the authorship, copyright and license notice. This file is not
+ a complete program and may only be used when the entire operating
+ system is licensed under the GPL. License for under other terms may be
+ available. Contact the original author for details.
+
+ The original author may be reached as becker@scyld.com, or at
+ Scyld Computing Corporation
+ 410 Severn Ave., Suite 210
+ Annapolis MD 21403
+
+ Support information and updates available at
+ http://www.scyld.com/network/netsemi.html
+
+ References:
+
+ http://www.scyld.com/expert/100mbps.html
+ http://www.scyld.com/expert/NWay.html
+ Datasheet is available from:
+ http://www.national.com/pf/DP/DP83815.html
+
+*/
+
+FILE_LICENCE ( GPL_ANY );
+
+/* Revision History */
+
+/*
+ 02 Jul 2007 Udayan Kumar 1.2 ported the driver from etherboot to gPXE API.
+ Fully rewritten,adapting the old driver.
+ Added a circular buffer for transmit and receive.
+ transmit routine will not wait for transmission to finish.
+ poll routine deals with it.
+ 13 Dec 2003 Tim Legge 1.1 Enabled Multicast Support
+ 29 May 2001 Marty Connor 1.0 Initial Release. Tested with Netgear FA311 and FA312 boards
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <gpxe/io.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <unistd.h>
+#include <gpxe/pci.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/spi_bit.h>
+#include <gpxe/threewire.h>
+#include <gpxe/nvo.h>
+#include "natsemi.h"
+
+/* Function Prototypes: */
+
+static int natsemi_spi_read_bit ( struct bit_basher *, unsigned int );
+static void natsemi_spi_write_bit ( struct bit_basher *,unsigned int, unsigned long );
+static void natsemi_init_eeprom ( struct natsemi_private * );
+static int natsemi_probe (struct pci_device *pci, const struct pci_device_id *id);
+static void natsemi_reset (struct net_device *netdev);
+static int natsemi_open (struct net_device *netdev);
+static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf);
+static void natsemi_poll (struct net_device *netdev);
+static void natsemi_close (struct net_device *netdev);
+static void natsemi_irq (struct net_device *netdev, int enable);
+static void natsemi_remove (struct pci_device *pci);
+
+/** natsemi net device operations */
+static struct net_device_operations natsemi_operations = {
+ .open = natsemi_open,
+ .close = natsemi_close,
+ .transmit = natsemi_transmit,
+ .poll = natsemi_poll,
+ .irq = natsemi_irq,
+};
+
+static int natsemi_spi_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id ) {
+ struct natsemi_private *np = container_of ( basher, struct natsemi_private,
+ spibit.basher );
+ uint8_t mask = natsemi_ee_bits[bit_id];
+ uint8_t eereg;
+
+ eereg = inb ( np->ioaddr + EE_REG );
+ return ( eereg & mask );
+}
+
+static void natsemi_spi_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data ) {
+ struct natsemi_private *np = container_of ( basher, struct natsemi_private,
+ spibit.basher );
+ uint8_t mask = natsemi_ee_bits[bit_id];
+ uint8_t eereg;
+
+ eereg = inb ( np->ioaddr + EE_REG );
+ eereg &= ~mask;
+ eereg |= ( data & mask );
+ outb ( eereg, np->ioaddr + EE_REG );
+}
+
+static struct bit_basher_operations natsemi_basher_ops = {
+ .read = natsemi_spi_read_bit,
+ .write = natsemi_spi_write_bit,
+};
+
+/* It looks that this portion of EEPROM can be used for
+ * non-volatile stored options. Data sheet does not talk about this region.
+ * Currently it is not working. But with some efforts it can.
+ */
+static struct nvo_fragment natsemi_nvo_fragments[] = {
+ { 0x0c, 0x68 },
+ { 0, 0 }
+};
+
+/*
+ * Set up for EEPROM access
+ *
+ * @v NAT NATSEMI NIC
+ */
+static void natsemi_init_eeprom ( struct natsemi_private *np ) {
+
+ /* Initialise three-wire bus
+ */
+ np->spibit.basher.op = &natsemi_basher_ops;
+ np->spibit.bus.mode = SPI_MODE_THREEWIRE;
+ np->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
+ init_spi_bit_basher ( &np->spibit );
+
+ /*natsemi DP 83815 only supports at93c46
+ */
+ init_at93c46 ( &np->eeprom, 16 );
+ np->eeprom.bus = &np->spibit.bus;
+ np->nvo.nvs = &np->eeprom.nvs;
+ np->nvo.fragments = natsemi_nvo_fragments;
+}
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int natsemi_probe (struct pci_device *pci,
+ const struct pci_device_id *id __unused) {
+ struct net_device *netdev;
+ struct natsemi_private *np = NULL;
+ uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
+ uint8_t last=0,last1=0;
+ uint8_t prev_bytes[2];
+ int i;
+ int rc;
+
+ /* Allocate net device
+ */
+ netdev = alloc_etherdev (sizeof (*np));
+ if (! netdev)
+ return -ENOMEM;
+
+ netdev_init (netdev, &natsemi_operations);
+ np = netdev->priv;
+ pci_set_drvdata (pci, netdev);
+ netdev->dev = &pci->dev;
+ memset (np, 0, sizeof (*np));
+ np->ioaddr = pci->ioaddr;
+
+ adjust_pci_device (pci);
+
+ natsemi_reset (netdev);
+ natsemi_init_eeprom ( np );
+ nvs_read ( &np->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
+ nvs_read ( &np->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
+
+ /* decoding the MAC address read from NVS
+ * and save it in netdev->ll_addr
+ */
+ last = prev_bytes[1] >> 7;
+ for ( i = 0 ; i < ETH_ALEN ; i++ ) {
+ last1 = ll_addr_encoded[i] >> 7;
+ netdev->hw_addr[i] = ll_addr_encoded[i] << 1 | last;
+ last = last1;
+ }
+
+ /* Mark as link up; we don't yet handle link state */
+ netdev_link_up ( netdev );
+
+ if ((rc = register_netdev (netdev)) != 0)
+ goto err_register_netdev;
+
+ return 0;
+
+err_register_netdev:
+
+ natsemi_reset (netdev);
+ netdev_put (netdev);
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void natsemi_remove (struct pci_device *pci) {
+ struct net_device *netdev = pci_get_drvdata (pci);
+
+ unregister_netdev (netdev);
+ natsemi_reset (netdev);
+ netdev_nullify ( netdev );
+ netdev_put (netdev);
+}
+
+/**
+ * Reset NIC
+ *
+ * @v NATSEMI NIC
+ *
+ * Issues a hardware reset and waits for the reset to complete.
+ */
+static void natsemi_reset (struct net_device *netdev)
+{
+ struct natsemi_private *np = netdev->priv;
+ int i;
+ u32 cfg;
+ u32 wcsr;
+ u32 rfcr;
+ u16 pmatch[3];
+ u16 sopass[3];
+
+ natsemi_irq (netdev, 0);
+
+ /*
+ * Resetting the chip causes some registers to be lost.
+ * Natsemi suggests NOT reloading the EEPROM while live, so instead
+ * we save the state that would have been loaded from EEPROM
+ * on a normal power-up (see the spec EEPROM map).
+ */
+
+ /* CFG */
+ cfg = inl (np->ioaddr + ChipConfig) & CFG_RESET_SAVE;
+
+ /* WCSR */
+ wcsr = inl (np->ioaddr + WOLCmd) & WCSR_RESET_SAVE;
+
+ /* RFCR */
+ rfcr = readl (np->ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
+
+ /* PMATCH */
+ for (i = 0; i < 3; i++) {
+ outl(i*2, np->ioaddr + RxFilterAddr);
+ pmatch[i] = inw(np->ioaddr + RxFilterData);
+ }
+
+ /* SOPAS */
+ for (i = 0; i < 3; i++) {
+ outl(0xa+(i*2), np->ioaddr + RxFilterAddr);
+ sopass[i] = inw(np->ioaddr + RxFilterData);
+ }
+
+ /* now whack the chip */
+ outl(ChipReset, np->ioaddr + ChipCmd);
+ for (i=0; i<NATSEMI_HW_TIMEOUT; i++) {
+ if (! (inl (np->ioaddr + ChipCmd) & ChipReset))
+ break;
+ udelay(5);
+ }
+ if (i == NATSEMI_HW_TIMEOUT) {
+ DBG ("natsemi_reset: reset did not complete in %d usec.\n", i*5);
+ }
+
+ /* restore CFG */
+ cfg |= inl(np->ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
+ cfg &= ~(CfgExtPhy | CfgPhyDis);
+ outl (cfg, np->ioaddr + ChipConfig);
+
+ /* restore WCSR */
+ wcsr |= inl (np->ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
+ outl (wcsr, np->ioaddr + WOLCmd);
+
+ /* read RFCR */
+ rfcr |= inl (np->ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
+
+ /* restore PMATCH */
+ for (i = 0; i < 3; i++) {
+ outl (i*2, np->ioaddr + RxFilterAddr);
+ outw (pmatch[i], np->ioaddr + RxFilterData);
+ }
+ for (i = 0; i < 3; i++) {
+ outl (0xa+(i*2), np->ioaddr + RxFilterAddr);
+ outw (sopass[i], np->ioaddr + RxFilterData);
+ }
+ /* restore RFCR */
+ outl (rfcr, np->ioaddr + RxFilterAddr);
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Net device
+ * @ret rc Return status code
+ */
+static int natsemi_open (struct net_device *netdev)
+{
+ struct natsemi_private *np = netdev->priv;
+ uint32_t tx_config, rx_config;
+ int i;
+
+ /* Disable PME:
+ * The PME bit is initialized from the EEPROM contents.
+ * PCI cards probably have PME disabled, but motherboard
+ * implementations may have PME set to enable WakeOnLan.
+ * With PME set the chip will scan incoming packets but
+ * nothing will be written to memory.
+ */
+ outl (inl (np->ioaddr + ClkRun) & ~0x100, np->ioaddr + ClkRun);
+
+ /* Set MAC address in NIC
+ */
+ for (i = 0 ; i < ETH_ALEN ; i+=2) {
+ outl (i, np->ioaddr + RxFilterAddr);
+ outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8),
+ np->ioaddr + RxFilterData);
+ }
+
+ /* Setup Tx Ring
+ */
+ np->tx_cur = 0;
+ np->tx_dirty = 0;
+ for (i = 0 ; i < TX_RING_SIZE ; i++) {
+ np->tx[i].link = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]);
+ np->tx[i].cmdsts = 0;
+ np->tx[i].bufptr = 0;
+ }
+ outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr);
+
+ DBG ("Natsemi Tx descriptor loaded with: %#08x\n",
+ inl (np->ioaddr + TxRingPtr));
+
+ /* Setup RX ring
+ */
+ np->rx_cur = 0;
+ for (i = 0 ; i < NUM_RX_DESC ; i++) {
+ np->iobuf[i] = alloc_iob (RX_BUF_SIZE);
+ if (! np->iobuf[i])
+ goto memory_alloc_err;
+ np->rx[i].link = virt_to_bus ((i + 1 < NUM_RX_DESC)
+ ? &np->rx[i + 1] : &np->rx[0]);
+ np->rx[i].cmdsts = RX_BUF_SIZE;
+ np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data);
+ DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i,
+ &np->iobuf[i], &np->iobuf[i]->data);
+ }
+ outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr);
+
+ DBG ("Natsemi Rx descriptor loaded with: %#08x\n",
+ inl (np->ioaddr + RxRingPtr));
+
+ /* Setup RX Filter
+ */
+ outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
+ np->ioaddr + RxFilterAddr);
+
+ /* Initialize other registers.
+ * Configure the PCI bus bursts and FIFO thresholds.
+ * Configure for standard, in-spec Ethernet.
+ */
+ if (inl (np->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
+ DBG ("Full duplex\n");
+ tx_config = 0xD0801002 | 0xC0000000;
+ rx_config = 0x10000020 | 0x10000000;
+ } else {
+ DBG ("Half duplex\n");
+ tx_config = 0x10801002 & ~0xC0000000;
+ rx_config = 0x00000020 & ~0x10000000;
+ }
+ outl (tx_config, np->ioaddr + TxConfig);
+ outl (rx_config, np->ioaddr + RxConfig);
+
+ DBG ("Tx config register = %#08x Rx config register = %#08x\n",
+ inl (np->ioaddr + TxConfig),
+ inl (np->ioaddr + RxConfig));
+
+ /*Set the Interrupt Mask register
+ */
+ outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask);
+ /*start the receiver
+ */
+ outl (RxOn, np->ioaddr + ChipCmd);
+
+ return 0;
+
+memory_alloc_err:
+
+ /* Frees any allocated buffers when memory
+ * for all buffers requested is not available
+ */
+ i = 0;
+ while (np->rx[i].cmdsts == RX_BUF_SIZE) {
+ free_iob (np->iobuf[i]);
+ i++;
+ }
+ return -ENOMEM;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Net device
+ */
+static void natsemi_close (struct net_device *netdev)
+{
+ struct natsemi_private *np = netdev->priv;
+ int i;
+
+ natsemi_reset (netdev);
+
+ for (i = 0; i < NUM_RX_DESC ; i++) {
+ free_iob (np->iobuf[i]);
+ }
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf)
+{
+ struct natsemi_private *np = netdev->priv;
+
+ if (np->tx[np->tx_cur].cmdsts != 0) {
+ DBG ("TX overflow\n");
+ return -ENOBUFS;
+ }
+
+ /* Used by netdev_tx_complete ()
+ */
+ np->tx_iobuf[np->tx_cur] = iobuf;
+
+ /* Pad and align packet has not been used because its not required
+ * by the hardware.
+ * iob_pad (iobuf, ETH_ZLEN);
+ * can be used to achieve it, if required
+ */
+
+ /* Add the packet to TX ring
+ */
+ np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data);
+ np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN;
+
+ DBG ("TX id %d at %#08lx + %#08zx\n", np->tx_cur,
+ virt_to_bus (&iobuf->data), iob_len (iobuf));
+
+ /* increment the circular buffer pointer to the next buffer location
+ */
+ np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE;
+
+ /*start the transmitter
+ */
+ outl (TxOn, np->ioaddr + ChipCmd);
+
+ return 0;
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void natsemi_poll (struct net_device *netdev)
+{
+ struct natsemi_private *np = netdev->priv;
+ unsigned int tx_status;
+ unsigned int rx_status;
+ unsigned int intr_status;
+ unsigned int rx_len;
+ struct io_buffer *rx_iob;
+ int i;
+
+ /* read the interrupt register
+ */
+ intr_status = inl (np->ioaddr + IntrStatus);
+
+ if (!intr_status)
+ goto end;
+
+ DBG ("natsemi_poll: intr_status = %#08x\n", intr_status);
+
+ /* Check status of transmitted packets
+ */
+ i = np->tx_dirty;
+ while (i != np->tx_cur) {
+ tx_status = np->tx[np->tx_dirty].cmdsts;
+
+ DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
+ np->tx_dirty, np->tx_cur, tx_status);
+
+ if (tx_status & OWN)
+ break;
+
+ if (! (tx_status & DescPktOK)) {
+ netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL);
+ DBG ("Error transmitting packet, tx_status: %#08x\n",
+ tx_status);
+ } else {
+ netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]);
+ DBG ("Success transmitting packet\n");
+ }
+
+ np->tx[np->tx_dirty].cmdsts = 0;
+ np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE;
+ i = (i + 1) % TX_RING_SIZE;
+ }
+
+ /* Process received packets
+ */
+ rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts;
+ while ((rx_status & OWN)) {
+ rx_len = (rx_status & DSIZE) - CRC_SIZE;
+
+ DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
+ np->rx_cur, rx_status, rx_len);
+
+ if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) {
+ netdev_rx_err (netdev, NULL, -EINVAL);
+
+ DBG ("natsemi_poll: Corrupted packet received!"
+ " Status = %#08x\n",
+ np->rx[np->rx_cur].cmdsts);
+
+ } else {
+
+
+ /* If unable allocate space for this packet,
+ * try again next poll
+ */
+ rx_iob = alloc_iob (rx_len);
+ if (! rx_iob)
+ goto end;
+ memcpy (iob_put (rx_iob, rx_len),
+ np->iobuf[np->rx_cur]->data, rx_len);
+ /* Add this packet to the receive queue.
+ */
+ netdev_rx (netdev, rx_iob);
+ }
+ np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE;
+ np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC;
+ rx_status = np->rx[np->rx_cur].cmdsts;
+ }
+end:
+ /* re-enable the potentially idle receive state machine
+ */
+ outl (RxOn, np->ioaddr + ChipCmd);
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Non-zero for enable, zero for disable
+ */
+static void natsemi_irq (struct net_device *netdev, int enable)
+{
+ struct natsemi_private *np = netdev->priv;
+
+ outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0),
+ np->ioaddr + IntrMask);
+ outl ((enable ? 1 : 0), np->ioaddr + IntrEnable);
+}
+
+static struct pci_device_id natsemi_nics[] = {
+ PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815", 0),
+};
+
+struct pci_driver natsemi_driver __pci_driver = {
+ .ids = natsemi_nics,
+ .id_count = (sizeof (natsemi_nics) / sizeof (natsemi_nics[0])),
+ .probe = natsemi_probe,
+ .remove = natsemi_remove,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.h
new file mode 100644
index 0000000..ae827ba
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/natsemi.h
@@ -0,0 +1,232 @@
+FILE_LICENCE ( GPL_ANY );
+
+#define NATSEMI_HW_TIMEOUT 400
+
+#define TX_RING_SIZE 4
+#define NUM_RX_DESC 4
+#define RX_BUF_SIZE 1536
+#define OWN 0x80000000
+#define DSIZE 0x00000FFF
+#define CRC_SIZE 4
+
+struct natsemi_tx {
+ uint32_t link;
+ uint32_t cmdsts;
+ uint32_t bufptr;
+};
+
+struct natsemi_rx {
+ uint32_t link;
+ uint32_t cmdsts;
+ uint32_t bufptr;
+};
+
+struct natsemi_private {
+ unsigned short ioaddr;
+ unsigned short tx_cur;
+ unsigned short tx_dirty;
+ unsigned short rx_cur;
+ struct natsemi_tx tx[TX_RING_SIZE];
+ struct natsemi_rx rx[NUM_RX_DESC];
+
+ /* need to add iobuf as we cannot free iobuf->data in close without this
+ * alternatively substracting sizeof(head) and sizeof(list_head) can also
+ * give the same.
+ */
+ struct io_buffer *iobuf[NUM_RX_DESC];
+
+ /* netdev_tx_complete needs pointer to the iobuf of the data so as to free
+ * it from the memory.
+ */
+ struct io_buffer *tx_iobuf[TX_RING_SIZE];
+ struct spi_bit_basher spibit;
+ struct spi_device eeprom;
+ struct nvo_block nvo;
+};
+
+/*
+ * Support for fibre connections on Am79C874:
+ * This phy needs a special setup when connected to a fibre cable.
+ * http://www.amd.com/files/connectivitysolutions/networking/archivednetworking/22235.pdf
+ */
+#define PHYID_AM79C874 0x0022561b
+
+enum {
+ MII_MCTRL = 0x15, /* mode control register */
+ MII_FX_SEL = 0x0001, /* 100BASE-FX (fiber) */
+ MII_EN_SCRM = 0x0004, /* enable scrambler (tp) */
+};
+
+
+
+/* values we might find in the silicon revision register */
+#define SRR_DP83815_C 0x0302
+#define SRR_DP83815_D 0x0403
+#define SRR_DP83816_A4 0x0504
+#define SRR_DP83816_A5 0x0505
+
+/* NATSEMI: Offsets to the device registers.
+ * Unlike software-only systems, device drivers interact with complex hardware.
+ * It's not useful to define symbolic names for every register bit in the
+ * device.
+ */
+enum register_offsets {
+ ChipCmd = 0x00,
+ ChipConfig = 0x04,
+ EECtrl = 0x08,
+ PCIBusCfg = 0x0C,
+ IntrStatus = 0x10,
+ IntrMask = 0x14,
+ IntrEnable = 0x18,
+ TxRingPtr = 0x20,
+ TxConfig = 0x24,
+ RxRingPtr = 0x30,
+ RxConfig = 0x34,
+ ClkRun = 0x3C,
+ WOLCmd = 0x40,
+ PauseCmd = 0x44,
+ RxFilterAddr = 0x48,
+ RxFilterData = 0x4C,
+ BootRomAddr = 0x50,
+ BootRomData = 0x54,
+ SiliconRev = 0x58,
+ StatsCtrl = 0x5C,
+ StatsData = 0x60,
+ RxPktErrs = 0x60,
+ RxMissed = 0x68,
+ RxCRCErrs = 0x64,
+ PCIPM = 0x44,
+ PhyStatus = 0xC0,
+ MIntrCtrl = 0xC4,
+ MIntrStatus = 0xC8,
+
+ /* These are from the spec, around page 78... on a separate table.
+ */
+ PGSEL = 0xCC,
+ PMDCSR = 0xE4,
+ TSTDAT = 0xFC,
+ DSPCFG = 0xF4,
+ SDCFG = 0x8C,
+ BasicControl = 0x80,
+ BasicStatus = 0x84
+
+};
+
+/* the values for the 'magic' registers above (PGSEL=1) */
+#define PMDCSR_VAL 0x189c /* enable preferred adaptation circuitry */
+#define TSTDAT_VAL 0x0
+#define DSPCFG_VAL 0x5040
+#define SDCFG_VAL 0x008c /* set voltage thresholds for Signal Detect */
+#define DSPCFG_LOCK 0x20 /* coefficient lock bit in DSPCFG */
+#define DSPCFG_COEF 0x1000 /* see coefficient (in TSTDAT) bit in DSPCFG */
+#define TSTDAT_FIXED 0xe8 /* magic number for bad coefficients */
+
+/* Bit in ChipCmd.
+ */
+enum ChipCmdBits {
+ ChipReset = 0x100,
+ RxReset = 0x20,
+ TxReset = 0x10,
+ RxOff = 0x08,
+ RxOn = 0x04,
+ TxOff = 0x02,
+ TxOn = 0x01
+};
+
+enum ChipConfig_bits {
+ CfgPhyDis = 0x200,
+ CfgPhyRst = 0x400,
+ CfgExtPhy = 0x1000,
+ CfgAnegEnable = 0x2000,
+ CfgAneg100 = 0x4000,
+ CfgAnegFull = 0x8000,
+ CfgAnegDone = 0x8000000,
+ CfgFullDuplex = 0x20000000,
+ CfgSpeed100 = 0x40000000,
+ CfgLink = 0x80000000,
+};
+
+
+/* Bits in the RxMode register.
+ */
+enum rx_mode_bits {
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0xC0000000,
+ AcceptMulticast = 0x00200000,
+ AcceptAllMulticast = 0x20000000,
+ AcceptAllPhys = 0x10000000,
+ AcceptMyPhys = 0x08000000,
+ RxFilterEnable = 0x80000000
+};
+
+/* Bits in network_desc.status
+ */
+enum desc_status_bits {
+ DescOwn = 0x80000000,
+ DescMore = 0x40000000,
+ DescIntr = 0x20000000,
+ DescNoCRC = 0x10000000,
+ DescPktOK = 0x08000000,
+ RxTooLong = 0x00400000
+};
+
+/*Bits in Interrupt Mask register
+ */
+enum Intr_mask_register_bits {
+ RxOk = 0x001,
+ RxErr = 0x004,
+ TxOk = 0x040,
+ TxErr = 0x100
+};
+
+enum MIntrCtrl_bits {
+ MICRIntEn = 0x2,
+};
+
+/* CFG bits [13:16] [18:23] */
+#define CFG_RESET_SAVE 0xfde000
+/* WCSR bits [0:4] [9:10] */
+#define WCSR_RESET_SAVE 0x61f
+/* RFCR bits [20] [22] [27:31] */
+#define RFCR_RESET_SAVE 0xf8500000;
+
+/* Delay between EEPROM clock transitions.
+ No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
+ a delay. */
+#define eeprom_delay(ee_addr) inl(ee_addr)
+
+enum EEPROM_Ctrl_Bits {
+ EE_ShiftClk = 0x04,
+ EE_DataIn = 0x01,
+ EE_ChipSelect = 0x08,
+ EE_DataOut = 0x02
+};
+
+#define EE_Write0 (EE_ChipSelect)
+#define EE_Write1 (EE_ChipSelect | EE_DataIn)
+
+/* The EEPROM commands include the alway-set leading bit. */
+enum EEPROM_Cmds {
+ EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
+};
+
+/* EEPROM access , values are devices specific
+ */
+#define EE_CS 0x08 /* EEPROM chip select */
+#define EE_SK 0x04 /* EEPROM shift clock */
+#define EE_DI 0x01 /* Data in */
+#define EE_DO 0x02 /* Data out */
+
+/* Offsets within EEPROM (these are word offsets)
+ */
+#define EE_MAC 7
+#define EE_REG EECtrl
+
+static const uint8_t natsemi_ee_bits[] = {
+ [SPI_BIT_SCLK] = EE_SK,
+ [SPI_BIT_MOSI] = EE_DI,
+ [SPI_BIT_MISO] = EE_DO,
+ [SPI_BIT_SS(0)] = EE_CS,
+};
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ne2k_isa.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ne2k_isa.c
new file mode 100644
index 0000000..603d1ed
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ne2k_isa.c
@@ -0,0 +1,375 @@
+/**************************************************************************
+ ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+ Author: Martin Renters
+ Date: May/94
+
+ This code is based heavily on David Greenman's if_ed.c driver
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+ Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
+ Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
+ Card Detect support adapted from the eCos driver (Christian Plessl <cplessl@ee.ethz.ch>)
+ Extracted from ns8390.c and adapted by Pantelis Koukousoulas <pktoss@gmail.com>
+ **************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+#include "ns8390.h"
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/ethernet.h>
+#include <gpxe/isa.h>
+#include <errno.h>
+
+#define ASIC_PIO NE_DATA
+
+static unsigned char eth_vendor, eth_flags;
+static unsigned short eth_nic_base, eth_asic_base;
+static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
+static Address eth_bmem, eth_rmem;
+static unsigned char eth_drain_receiver;
+
+static struct nic_operations ne_operations;
+static void ne_reset(struct nic *nic, struct isa_device *isa);
+
+static isa_probe_addr_t ne_probe_addrs[] = { 0x300, 0x280, 0x320, 0x340, 0x380, 0x220, };
+
+/**************************************************************************
+ ETH_PIO_READ - Read a frame via Programmed I/O
+ **************************************************************************/
+static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {
+ outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
+ outb(src, eth_nic_base + D8390_P0_RSAR0);
+ outb(src >> 8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD0 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while (cnt--) {
+ if (eth_flags & FLAG_16BIT) {
+ *((unsigned short *) dst) = inw(eth_asic_base + ASIC_PIO);
+ dst += 2;
+ } else
+ *(dst++) = inb(eth_asic_base + ASIC_PIO);
+ }
+}
+
+/**************************************************************************
+ ETH_PIO_WRITE - Write a frame via Programmed I/O
+ **************************************************************************/
+static void eth_pio_write(const unsigned char *src, unsigned int dst,
+ unsigned int cnt) {
+ outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
+ outb(dst, eth_nic_base + D8390_P0_RSAR0);
+ outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while (cnt--) {
+
+ if (eth_flags & FLAG_16BIT) {
+ outw(*((unsigned short *) src), eth_asic_base + ASIC_PIO);
+ src += 2;
+ } else
+ outb(*(src++), eth_asic_base + ASIC_PIO);
+ }
+}
+
+/**************************************************************************
+ enable_multicast - Enable Multicast
+ **************************************************************************/
+static void enable_multicast(unsigned short eth_nic_base) {
+ unsigned char mcfilter[8];
+ int i;
+
+ memset(mcfilter, 0xFF, 8);
+ outb(4, eth_nic_base + D8390_P0_RCR);
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
+ for (i = 0; i < 8; i++) {
+ outb(mcfilter[i], eth_nic_base + 8 + i);
+ if (inb(eth_nic_base + 8 + i) != mcfilter[i])
+ DBG("Error SMC 83C690 Multicast filter read/write mishap %d\n",
+ i);
+ }
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
+ outb(4 | 0x08, eth_nic_base + D8390_P0_RCR);
+}
+
+/**************************************************************************
+ NE_PROBE1 - Look for an adapter on the ISA bus
+ **************************************************************************/
+static int ne_probe1(isa_probe_addr_t ioaddr) {
+ //From the eCos driver
+ unsigned int regd;
+ unsigned int state;
+
+ state = inb(ioaddr);
+ outb(ioaddr, D8390_COMMAND_RD2 | D8390_COMMAND_PS1 | D8390_COMMAND_STP);
+ regd = inb(ioaddr + D8390_P0_TCR);
+
+ if (inb(ioaddr + D8390_P0_TCR)) {
+ outb(ioaddr, state);
+ outb(ioaddr + 0x0d, regd);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+ NE_PROBE - Initialize an adapter ???
+ **************************************************************************/
+static int ne_probe(struct nic *nic, struct isa_device *isa) {
+ int i;
+ unsigned char c;
+ unsigned char romdata[16];
+ unsigned char testbuf[32];
+
+ eth_vendor = VENDOR_NONE;
+ eth_drain_receiver = 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+ eth_nic_base = isa->ioaddr;
+
+ /******************************************************************
+ Search for NE1000/2000 if no WD/SMC or 3com cards
+ ******************************************************************/
+ if (eth_vendor == VENDOR_NONE) {
+
+ static unsigned char test[] = "NE*000 memory";
+
+ eth_bmem = 0; /* No shared memory */
+
+ eth_flags = FLAG_PIO;
+ eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
+ eth_memsize = MEM_16384;
+ eth_tx_start = 32;
+ eth_rx_start = 32 + D8390_TXBUF_SIZE;
+ c = inb(eth_asic_base + NE_RESET);
+ outb(c, eth_asic_base + NE_RESET);
+ (void) inb(0x84);
+ outb(D8390_COMMAND_STP | D8390_COMMAND_RD2, eth_nic_base
+ + D8390_P0_COMMAND);
+ outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
+ outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
+ outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
+ eth_pio_write((unsigned char *) test, 8192, sizeof(test));
+ eth_pio_read(8192, testbuf, sizeof(test));
+ if (!memcmp(test, testbuf, sizeof(test)))
+ goto out;
+ eth_flags |= FLAG_16BIT;
+ eth_memsize = MEM_32768;
+ eth_tx_start = 64;
+ eth_rx_start = 64 + D8390_TXBUF_SIZE;
+ outb(D8390_DCR_WTS | D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base
+ + D8390_P0_DCR);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
+ eth_pio_write((unsigned char *) test, 16384, sizeof(test));
+ eth_pio_read(16384, testbuf, sizeof(test));
+ if (!memcmp(testbuf, test, sizeof(test)))
+ goto out;
+
+
+out:
+ if (eth_nic_base == 0)
+ return (0);
+ if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
+ eth_flags |= FLAG_16BIT;
+ eth_vendor = VENDOR_NOVELL;
+ eth_pio_read(0, romdata, sizeof(romdata));
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
+ }
+ nic->ioaddr = eth_nic_base;
+ DBG("\nNE%c000 base %4.4x, MAC Addr %s\n",
+ (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base, eth_ntoa(
+ nic->node_addr));
+ }
+
+ if (eth_vendor == VENDOR_NONE)
+ return (0);
+
+ if (eth_vendor != VENDOR_3COM)
+ eth_rmem = eth_bmem;
+
+ ne_reset(nic, isa);
+ nic->nic_op = &ne_operations;
+ return 1;
+}
+
+
+/**************************************************************************
+ NE_DISABLE - Turn off adapter
+ **************************************************************************/
+static void ne_disable(struct nic *nic, struct isa_device *isa) {
+ ne_reset(nic, isa);
+}
+
+
+/**************************************************************************
+ NE_RESET - Reset adapter
+ **************************************************************************/
+static void ne_reset(struct nic *nic, struct isa_device *isa __unused)
+{
+ int i;
+
+ eth_drain_receiver = 0;
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ outb(0x49, eth_nic_base+D8390_P0_DCR);
+ else
+ outb(0x48, eth_nic_base+D8390_P0_DCR);
+ outb(0, eth_nic_base+D8390_P0_RBCR0);
+ outb(0, eth_nic_base+D8390_P0_RBCR1);
+ outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
+ outb(2, eth_nic_base+D8390_P0_TCR);
+ outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
+ outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
+
+ outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
+ outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_IMR);
+ outb(D8390_COMMAND_PS1 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+
+ for (i=0; i<ETH_ALEN; i++)
+ outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
+ for (i=0; i<ETH_ALEN; i++)
+ outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
+ outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
+ outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
+
+ enable_multicast(eth_nic_base);
+}
+
+
+/**************************************************************************
+ NE_POLL - Wait for a frame
+ **************************************************************************/
+static int ne_poll(struct nic *nic __unused, int retrieve __unused)
+{
+ int ret = 0;
+ unsigned char rstat, curr, next;
+ unsigned short len, frag;
+ unsigned short pktoff;
+ unsigned char *p;
+ struct ringbuffer pkthdr;
+
+ rstat = inb(eth_nic_base+D8390_P0_RSR);
+ if (!(rstat & D8390_RSTAT_PRX)) return(0);
+ next = inb(eth_nic_base+D8390_P0_BOUND)+1;
+ if (next >= eth_memsize) next = eth_rx_start;
+ outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
+ curr = inb(eth_nic_base+D8390_P1_CURR);
+ outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
+ if (curr >= eth_memsize) curr=eth_rx_start;
+ if (curr == next) return(0);
+
+ if ( ! retrieve ) return 1;
+
+ pktoff = next << 8;
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
+ else
+ memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
+ pktoff += sizeof(pkthdr);
+ /* incoming length includes FCS so must sub 4 */
+ len = pkthdr.len - 4;
+ if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
+ || len> ETH_FRAME_LEN) {
+ DBG("Bogus packet, ignoring\n");
+ return (0);
+ }
+ else {
+ p = nic->packet;
+ nic->packetlen = len; /* available to caller */
+ frag = (eth_memsize << 8) - pktoff;
+ if (len> frag) { /* We have a wrap-around */
+ /* read first part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, frag);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
+ pktoff = eth_rx_start << 8;
+ p += frag;
+ len -= frag;
+ }
+ /* read second part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, len);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
+ ret = 1;
+ }
+ next = pkthdr.next; /* frame number of next packet */
+ if (next == eth_rx_start)
+ next = eth_memsize;
+ outb(next-1, eth_nic_base+D8390_P0_BOUND);
+ return(ret);
+}
+
+
+/**************************************************************************
+ NE_TRANSMIT - Transmit a frame
+ **************************************************************************/
+static void ne_transmit(struct nic *nic, const char *d, /* Destination */
+unsigned int t, /* Type */
+unsigned int s, /* size */
+const char *p) { /* Packet */
+
+ /* Programmed I/O */
+ unsigned short type;
+ type = (t >> 8) | (t << 8);
+ eth_pio_write((unsigned char *) d, eth_tx_start << 8, ETH_ALEN);
+ eth_pio_write(nic->node_addr, (eth_tx_start << 8) + ETH_ALEN, ETH_ALEN);
+ /* bcc generates worse code without (const+const) below */
+ eth_pio_write((unsigned char *) &type, (eth_tx_start << 8) + (ETH_ALEN
+ + ETH_ALEN), 2);
+ eth_pio_write((unsigned char *) p, (eth_tx_start << 8) + ETH_HLEN, s);
+ s += ETH_HLEN;
+ if (s < ETH_ZLEN)
+ s = ETH_ZLEN;
+
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA,
+ eth_nic_base + D8390_P0_COMMAND);
+ outb(eth_tx_start, eth_nic_base + D8390_P0_TPSR);
+ outb(s, eth_nic_base + D8390_P0_TBCR0);
+ outb(s >> 8, eth_nic_base + D8390_P0_TBCR1);
+
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2
+ | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+}
+
+static struct nic_operations ne_operations = { .connect = dummy_connect,
+ .poll = ne_poll, .transmit = ne_transmit, .irq = dummy_irq,
+};
+
+ISA_DRIVER ( ne_driver, ne_probe_addrs, ne_probe1,
+ GENERIC_ISAPNP_VENDOR, 0x0600 );
+
+DRIVER ( "ne", nic_driver, isapnp_driver, ne_driver,
+ ne_probe, ne_disable );
+
+ISA_ROM("ne","NE1000/2000 and clones");
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ns83820.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ns83820.c
new file mode 100644
index 0000000..d5c6694
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ns83820.c
@@ -0,0 +1,1013 @@
+/**************************************************************************
+* ns83820.c: Etherboot device driver for the National Semiconductor 83820
+* Written 2004 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* ns83820.c by Benjamin LaHaise with contributions
+* for Linux kernel 2.4.x.
+*
+* Linux Driver Version 0.20, 20020610
+*
+* This development of this Etherboot driver was funded by:
+*
+* NXTV: http://www.nxtv.com/
+*
+* REVISION HISTORY:
+* ================
+*
+* v1.0 02-16-2004 timlegge Initial port of Linux driver
+* v1.1 02-19-2004 timlegge More rohbust transmit and poll
+*
+* Indent Options: indent -kr -i8
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <gpxe/pci.h>
+
+#if ARCH == ia64 /* Support 64-bit addressing */
+#define USE_64BIT_ADDR
+#endif
+
+//#define DDEBUG
+#ifdef DDEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+#define HZ 100
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* NIC specific static variables go here */
+
+/* Global parameters. See MODULE_PARM near the bottom. */
+// static int ihr = 2;
+static int reset_phy = 0;
+static int lnksts = 0; /* CFG_LNKSTS bit polarity */
+
+#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)
+#define USE_64BIT_ADDR "+"
+#endif
+
+#if defined(USE_64BIT_ADDR)
+#define TRY_DAC 1
+#else
+#define TRY_DAC 0
+#endif
+
+/* tunables */
+#define RX_BUF_SIZE 1500 /* 8192 */
+
+/* Must not exceed ~65000. */
+#define NR_RX_DESC 64
+#define NR_TX_DESC 1
+
+ /* not tunable *//* Extra 6 bytes for 64 bit alignment (divisable by 8) */
+#define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14 + 6) /* rx/tx mac addr + type */
+
+#define MIN_TX_DESC_FREE 8
+
+/* register defines */
+#define CFGCS 0x04
+
+#define CR_TXE 0x00000001
+#define CR_TXD 0x00000002
+/* Ramit : Here's a tip, don't do a RXD immediately followed by an RXE
+ * The Receive engine skips one descriptor and moves
+ * onto the next one!! */
+#define CR_RXE 0x00000004
+#define CR_RXD 0x00000008
+#define CR_TXR 0x00000010
+#define CR_RXR 0x00000020
+#define CR_SWI 0x00000080
+#define CR_RST 0x00000100
+
+#define PTSCR_EEBIST_FAIL 0x00000001
+#define PTSCR_EEBIST_EN 0x00000002
+#define PTSCR_EELOAD_EN 0x00000004
+#define PTSCR_RBIST_FAIL 0x000001b8
+#define PTSCR_RBIST_DONE 0x00000200
+#define PTSCR_RBIST_EN 0x00000400
+#define PTSCR_RBIST_RST 0x00002000
+
+#define MEAR_EEDI 0x00000001
+#define MEAR_EEDO 0x00000002
+#define MEAR_EECLK 0x00000004
+#define MEAR_EESEL 0x00000008
+#define MEAR_MDIO 0x00000010
+#define MEAR_MDDIR 0x00000020
+#define MEAR_MDC 0x00000040
+
+#define ISR_TXDESC3 0x40000000
+#define ISR_TXDESC2 0x20000000
+#define ISR_TXDESC1 0x10000000
+#define ISR_TXDESC0 0x08000000
+#define ISR_RXDESC3 0x04000000
+#define ISR_RXDESC2 0x02000000
+#define ISR_RXDESC1 0x01000000
+#define ISR_RXDESC0 0x00800000
+#define ISR_TXRCMP 0x00400000
+#define ISR_RXRCMP 0x00200000
+#define ISR_DPERR 0x00100000
+#define ISR_SSERR 0x00080000
+#define ISR_RMABT 0x00040000
+#define ISR_RTABT 0x00020000
+#define ISR_RXSOVR 0x00010000
+#define ISR_HIBINT 0x00008000
+#define ISR_PHY 0x00004000
+#define ISR_PME 0x00002000
+#define ISR_SWI 0x00001000
+#define ISR_MIB 0x00000800
+#define ISR_TXURN 0x00000400
+#define ISR_TXIDLE 0x00000200
+#define ISR_TXERR 0x00000100
+#define ISR_TXDESC 0x00000080
+#define ISR_TXOK 0x00000040
+#define ISR_RXORN 0x00000020
+#define ISR_RXIDLE 0x00000010
+#define ISR_RXEARLY 0x00000008
+#define ISR_RXERR 0x00000004
+#define ISR_RXDESC 0x00000002
+#define ISR_RXOK 0x00000001
+
+#define TXCFG_CSI 0x80000000
+#define TXCFG_HBI 0x40000000
+#define TXCFG_MLB 0x20000000
+#define TXCFG_ATP 0x10000000
+#define TXCFG_ECRETRY 0x00800000
+#define TXCFG_BRST_DIS 0x00080000
+#define TXCFG_MXDMA1024 0x00000000
+#define TXCFG_MXDMA512 0x00700000
+#define TXCFG_MXDMA256 0x00600000
+#define TXCFG_MXDMA128 0x00500000
+#define TXCFG_MXDMA64 0x00400000
+#define TXCFG_MXDMA32 0x00300000
+#define TXCFG_MXDMA16 0x00200000
+#define TXCFG_MXDMA8 0x00100000
+
+#define CFG_LNKSTS 0x80000000
+#define CFG_SPDSTS 0x60000000
+#define CFG_SPDSTS1 0x40000000
+#define CFG_SPDSTS0 0x20000000
+#define CFG_DUPSTS 0x10000000
+#define CFG_TBI_EN 0x01000000
+#define CFG_MODE_1000 0x00400000
+/* Ramit : Dont' ever use AUTO_1000, it never works and is buggy.
+ * Read the Phy response and then configure the MAC accordingly */
+#define CFG_AUTO_1000 0x00200000
+#define CFG_PINT_CTL 0x001c0000
+#define CFG_PINT_DUPSTS 0x00100000
+#define CFG_PINT_LNKSTS 0x00080000
+#define CFG_PINT_SPDSTS 0x00040000
+#define CFG_TMRTEST 0x00020000
+#define CFG_MRM_DIS 0x00010000
+#define CFG_MWI_DIS 0x00008000
+#define CFG_T64ADDR 0x00004000
+#define CFG_PCI64_DET 0x00002000
+#define CFG_DATA64_EN 0x00001000
+#define CFG_M64ADDR 0x00000800
+#define CFG_PHY_RST 0x00000400
+#define CFG_PHY_DIS 0x00000200
+#define CFG_EXTSTS_EN 0x00000100
+#define CFG_REQALG 0x00000080
+#define CFG_SB 0x00000040
+#define CFG_POW 0x00000020
+#define CFG_EXD 0x00000010
+#define CFG_PESEL 0x00000008
+#define CFG_BROM_DIS 0x00000004
+#define CFG_EXT_125 0x00000002
+#define CFG_BEM 0x00000001
+
+#define EXTSTS_UDPPKT 0x00200000
+#define EXTSTS_TCPPKT 0x00080000
+#define EXTSTS_IPPKT 0x00020000
+
+#define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0))
+
+#define MIBC_MIBS 0x00000008
+#define MIBC_ACLR 0x00000004
+#define MIBC_FRZ 0x00000002
+#define MIBC_WRN 0x00000001
+
+#define PCR_PSEN (1 << 31)
+#define PCR_PS_MCAST (1 << 30)
+#define PCR_PS_DA (1 << 29)
+#define PCR_STHI_8 (3 << 23)
+#define PCR_STLO_4 (1 << 23)
+#define PCR_FFHI_8K (3 << 21)
+#define PCR_FFLO_4K (1 << 21)
+#define PCR_PAUSE_CNT 0xFFFE
+
+#define RXCFG_AEP 0x80000000
+#define RXCFG_ARP 0x40000000
+#define RXCFG_STRIPCRC 0x20000000
+#define RXCFG_RX_FD 0x10000000
+#define RXCFG_ALP 0x08000000
+#define RXCFG_AIRL 0x04000000
+#define RXCFG_MXDMA512 0x00700000
+#define RXCFG_DRTH 0x0000003e
+#define RXCFG_DRTH0 0x00000002
+
+#define RFCR_RFEN 0x80000000
+#define RFCR_AAB 0x40000000
+#define RFCR_AAM 0x20000000
+#define RFCR_AAU 0x10000000
+#define RFCR_APM 0x08000000
+#define RFCR_APAT 0x07800000
+#define RFCR_APAT3 0x04000000
+#define RFCR_APAT2 0x02000000
+#define RFCR_APAT1 0x01000000
+#define RFCR_APAT0 0x00800000
+#define RFCR_AARP 0x00400000
+#define RFCR_MHEN 0x00200000
+#define RFCR_UHEN 0x00100000
+#define RFCR_ULM 0x00080000
+
+#define VRCR_RUDPE 0x00000080
+#define VRCR_RTCPE 0x00000040
+#define VRCR_RIPE 0x00000020
+#define VRCR_IPEN 0x00000010
+#define VRCR_DUTF 0x00000008
+#define VRCR_DVTF 0x00000004
+#define VRCR_VTREN 0x00000002
+#define VRCR_VTDEN 0x00000001
+
+#define VTCR_PPCHK 0x00000008
+#define VTCR_GCHK 0x00000004
+#define VTCR_VPPTI 0x00000002
+#define VTCR_VGTI 0x00000001
+
+#define CR 0x00
+#define CFG 0x04
+#define MEAR 0x08
+#define PTSCR 0x0c
+#define ISR 0x10
+#define IMR 0x14
+#define IER 0x18
+#define IHR 0x1c
+#define TXDP 0x20
+#define TXDP_HI 0x24
+#define TXCFG 0x28
+#define GPIOR 0x2c
+#define RXDP 0x30
+#define RXDP_HI 0x34
+#define RXCFG 0x38
+#define PQCR 0x3c
+#define WCSR 0x40
+#define PCR 0x44
+#define RFCR 0x48
+#define RFDR 0x4c
+
+#define SRR 0x58
+
+#define VRCR 0xbc
+#define VTCR 0xc0
+#define VDR 0xc4
+#define CCSR 0xcc
+
+#define TBICR 0xe0
+#define TBISR 0xe4
+#define TANAR 0xe8
+#define TANLPAR 0xec
+#define TANER 0xf0
+#define TESR 0xf4
+
+#define TBICR_MR_AN_ENABLE 0x00001000
+#define TBICR_MR_RESTART_AN 0x00000200
+
+#define TBISR_MR_LINK_STATUS 0x00000020
+#define TBISR_MR_AN_COMPLETE 0x00000004
+
+#define TANAR_PS2 0x00000100
+#define TANAR_PS1 0x00000080
+#define TANAR_HALF_DUP 0x00000040
+#define TANAR_FULL_DUP 0x00000020
+
+#define GPIOR_GP5_OE 0x00000200
+#define GPIOR_GP4_OE 0x00000100
+#define GPIOR_GP3_OE 0x00000080
+#define GPIOR_GP2_OE 0x00000040
+#define GPIOR_GP1_OE 0x00000020
+#define GPIOR_GP3_OUT 0x00000004
+#define GPIOR_GP1_OUT 0x00000001
+
+#define LINK_AUTONEGOTIATE 0x01
+#define LINK_DOWN 0x02
+#define LINK_UP 0x04
+
+
+#define __kick_rx() writel(CR_RXE, ns->base + CR)
+
+#define kick_rx() do { \
+ dprintf(("kick_rx: maybe kicking\n")); \
+ writel(virt_to_le32desc(&rx_ring[ns->cur_rx]), ns->base + RXDP); \
+ if (ns->next_rx == ns->next_empty) \
+ printf("uh-oh: next_rx == next_empty???\n"); \
+ __kick_rx(); \
+} while(0)
+
+
+#ifdef USE_64BIT_ADDR
+#define HW_ADDR_LEN 8
+#else
+#define HW_ADDR_LEN 4
+#endif
+
+#define CMDSTS_OWN 0x80000000
+#define CMDSTS_MORE 0x40000000
+#define CMDSTS_INTR 0x20000000
+#define CMDSTS_ERR 0x10000000
+#define CMDSTS_OK 0x08000000
+#define CMDSTS_LEN_MASK 0x0000ffff
+
+#define CMDSTS_DEST_MASK 0x01800000
+#define CMDSTS_DEST_SELF 0x00800000
+#define CMDSTS_DEST_MULTI 0x01000000
+
+#define DESC_SIZE 8 /* Should be cache line sized */
+
+#ifdef USE_64BIT_ADDR
+struct ring_desc {
+ uint64_t link;
+ uint64_t bufptr;
+ u32 cmdsts;
+ u32 extsts; /* Extended status field */
+};
+#else
+struct ring_desc {
+ u32 link;
+ u32 bufptr;
+ u32 cmdsts;
+ u32 extsts; /* Extended status field */
+};
+#endif
+
+/* Private Storage for the NIC */
+static struct ns83820_private {
+ u8 *base;
+ int up;
+ long idle;
+ u32 *next_rx_desc;
+ u16 next_rx, next_empty;
+ u32 cur_rx;
+ u32 *descs;
+ unsigned ihr;
+ u32 CFG_cache;
+ u32 MEAR_cache;
+ u32 IMR_cache;
+ int linkstate;
+ u16 tx_done_idx;
+ u16 tx_idx;
+ u16 tx_intr_idx;
+ u32 phy_descs;
+ u32 *tx_descs;
+
+} nsx;
+static struct ns83820_private *ns;
+
+/* Define the TX and RX Descriptor and Buffers */
+struct {
+ struct ring_desc tx_ring[NR_TX_DESC] __attribute__ ((aligned(8)));
+ unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE];
+ struct ring_desc rx_ring[NR_RX_DESC] __attribute__ ((aligned(8)));
+ unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE]
+ __attribute__ ((aligned(8)));
+} ns83820_bufs __shared;
+#define tx_ring ns83820_bufs.tx_ring
+#define rx_ring ns83820_bufs.rx_ring
+#define txb ns83820_bufs.txb
+#define rxb ns83820_bufs.rxb
+
+static void phy_intr(struct nic *nic __unused)
+{
+ static char *speeds[] =
+ { "10", "100", "1000", "1000(?)", "1000F" };
+ u32 cfg, new_cfg;
+ u32 tbisr, tanar, tanlpar;
+ int speed, fullduplex, newlinkstate;
+
+ cfg = readl(ns->base + CFG) ^ SPDSTS_POLARITY;
+ if (ns->CFG_cache & CFG_TBI_EN) {
+ /* we have an optical transceiver */
+ tbisr = readl(ns->base + TBISR);
+ tanar = readl(ns->base + TANAR);
+ tanlpar = readl(ns->base + TANLPAR);
+ dprintf(("phy_intr: tbisr=%hX, tanar=%hX, tanlpar=%hX\n",
+ tbisr, tanar, tanlpar));
+
+ if ((fullduplex = (tanlpar & TANAR_FULL_DUP)
+ && (tanar & TANAR_FULL_DUP))) {
+
+ /* both of us are full duplex */
+ writel(readl(ns->base + TXCFG)
+ | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,
+ ns->base + TXCFG);
+ writel(readl(ns->base + RXCFG) | RXCFG_RX_FD,
+ ns->base + RXCFG);
+ /* Light up full duplex LED */
+ writel(readl(ns->base + GPIOR) | GPIOR_GP1_OUT,
+ ns->base + GPIOR);
+
+ } else if (((tanlpar & TANAR_HALF_DUP)
+ && (tanar & TANAR_HALF_DUP))
+ || ((tanlpar & TANAR_FULL_DUP)
+ && (tanar & TANAR_HALF_DUP))
+ || ((tanlpar & TANAR_HALF_DUP)
+ && (tanar & TANAR_FULL_DUP))) {
+
+ /* one or both of us are half duplex */
+ writel((readl(ns->base + TXCFG)
+ & ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP,
+ ns->base + TXCFG);
+ writel(readl(ns->base + RXCFG) & ~RXCFG_RX_FD,
+ ns->base + RXCFG);
+ /* Turn off full duplex LED */
+ writel(readl(ns->base + GPIOR) & ~GPIOR_GP1_OUT,
+ ns->base + GPIOR);
+ }
+
+ speed = 4; /* 1000F */
+
+ } else {
+ /* we have a copper transceiver */
+ new_cfg =
+ ns->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
+
+ if (cfg & CFG_SPDSTS1)
+ new_cfg |= CFG_MODE_1000;
+ else
+ new_cfg &= ~CFG_MODE_1000;
+
+ speed = ((cfg / CFG_SPDSTS0) & 3);
+ fullduplex = (cfg & CFG_DUPSTS);
+
+ if (fullduplex)
+ new_cfg |= CFG_SB;
+
+ if ((cfg & CFG_LNKSTS) &&
+ ((new_cfg ^ ns->CFG_cache) & CFG_MODE_1000)) {
+ writel(new_cfg, ns->base + CFG);
+ ns->CFG_cache = new_cfg;
+ }
+
+ ns->CFG_cache &= ~CFG_SPDSTS;
+ ns->CFG_cache |= cfg & CFG_SPDSTS;
+ }
+
+ newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN;
+
+ if (newlinkstate & LINK_UP && ns->linkstate != newlinkstate) {
+ printf("link now %s mbps, %s duplex and up.\n",
+ speeds[speed], fullduplex ? "full" : "half");
+ } else if (newlinkstate & LINK_DOWN
+ && ns->linkstate != newlinkstate) {
+ printf("link now down.\n");
+ }
+ ns->linkstate = newlinkstate;
+}
+static void ns83820_set_multicast(struct nic *nic __unused);
+static void ns83820_setup_rx(struct nic *nic)
+{
+ unsigned i;
+ ns->idle = 1;
+ ns->next_rx = 0;
+ ns->next_rx_desc = ns->descs;
+ ns->next_empty = 0;
+ ns->cur_rx = 0;
+
+
+ for (i = 0; i < NR_RX_DESC; i++) {
+ rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);
+ rx_ring[i].bufptr =
+ virt_to_le32desc(&rxb[i * REAL_RX_BUF_SIZE]);
+ rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);
+ rx_ring[i].extsts = cpu_to_le32(0);
+ }
+// No need to wrap the ring
+// rx_ring[i].link = virt_to_le32desc(&rx_ring[0]);
+ writel(0, ns->base + RXDP_HI);
+ writel(virt_to_le32desc(&rx_ring[0]), ns->base + RXDP);
+
+ dprintf(("starting receiver\n"));
+
+ writel(0x0001, ns->base + CCSR);
+ writel(0, ns->base + RFCR);
+ writel(0x7fc00000, ns->base + RFCR);
+ writel(0xffc00000, ns->base + RFCR);
+
+ ns->up = 1;
+
+ phy_intr(nic);
+
+ /* Okay, let it rip */
+ ns->IMR_cache |= ISR_PHY;
+ ns->IMR_cache |= ISR_RXRCMP;
+ //dev->IMR_cache |= ISR_RXERR;
+ //dev->IMR_cache |= ISR_RXOK;
+ ns->IMR_cache |= ISR_RXORN;
+ ns->IMR_cache |= ISR_RXSOVR;
+ ns->IMR_cache |= ISR_RXDESC;
+ ns->IMR_cache |= ISR_RXIDLE;
+ ns->IMR_cache |= ISR_TXDESC;
+ ns->IMR_cache |= ISR_TXIDLE;
+
+ // No reason to enable interupts...
+ // writel(ns->IMR_cache, ns->base + IMR);
+ // writel(1, ns->base + IER);
+ ns83820_set_multicast(nic);
+ kick_rx();
+}
+
+
+static void ns83820_do_reset(struct nic *nic __unused, u32 which)
+{
+ dprintf(("resetting chip...\n"));
+ writel(which, ns->base + CR);
+ do {
+
+ } while (readl(ns->base + CR) & which);
+ dprintf(("okay!\n"));
+}
+
+static void ns83820_reset(struct nic *nic)
+{
+ unsigned i;
+ dprintf(("ns83820_reset\n"));
+
+ writel(0, ns->base + PQCR);
+
+ ns83820_setup_rx(nic);
+
+ for (i = 0; i < NR_TX_DESC; i++) {
+ tx_ring[i].link = 0;
+ tx_ring[i].bufptr = 0;
+ tx_ring[i].cmdsts = cpu_to_le32(0);
+ tx_ring[i].extsts = cpu_to_le32(0);
+ }
+
+ ns->tx_idx = 0;
+ ns->tx_done_idx = 0;
+ writel(0, ns->base + TXDP_HI);
+ return;
+}
+static void ns83820_getmac(struct nic *nic __unused, u8 * mac)
+{
+ unsigned i;
+ for (i = 0; i < 3; i++) {
+ u32 data;
+ /* Read from the perfect match memory: this is loaded by
+ * the chip from the EEPROM via the EELOAD self test.
+ */
+ writel(i * 2, ns->base + RFCR);
+ data = readl(ns->base + RFDR);
+ *mac++ = data;
+ *mac++ = data >> 8;
+ }
+}
+
+static void ns83820_set_multicast(struct nic *nic __unused)
+{
+ u8 *rfcr = ns->base + RFCR;
+ u32 and_mask = 0xffffffff;
+ u32 or_mask = 0;
+ u32 val;
+
+ /* Support Multicast */
+ and_mask &= ~(RFCR_AAU | RFCR_AAM);
+ or_mask |= RFCR_AAM;
+ val = (readl(rfcr) & and_mask) | or_mask;
+ /* Ramit : RFCR Write Fix doc says RFEN must be 0 modify other bits */
+ writel(val & ~RFCR_RFEN, rfcr);
+ writel(val, rfcr);
+
+}
+static void ns83820_run_bist(struct nic *nic __unused, const char *name,
+ u32 enable, u32 done, u32 fail)
+{
+ int timed_out = 0;
+ long start;
+ u32 status;
+ int loops = 0;
+
+ dprintf(("start %s\n", name))
+
+ start = currticks();
+
+ writel(enable, ns->base + PTSCR);
+ for (;;) {
+ loops++;
+ status = readl(ns->base + PTSCR);
+ if (!(status & enable))
+ break;
+ if (status & done)
+ break;
+ if (status & fail)
+ break;
+ if ((currticks() - start) >= HZ) {
+ timed_out = 1;
+ break;
+ }
+ }
+
+ if (status & fail)
+ printf("%s failed! (0x%hX & 0x%hX)\n", name, (unsigned int) status,
+ (unsigned int) fail);
+ else if (timed_out)
+ printf("run_bist %s timed out! (%hX)\n", name, (unsigned int) status);
+ dprintf(("done %s in %d loops\n", name, loops));
+}
+
+/*************************************
+Check Link
+*************************************/
+static void ns83820_check_intr(struct nic *nic) {
+ int i;
+ u32 isr = readl(ns->base + ISR);
+ if(ISR_PHY & isr)
+ phy_intr(nic);
+ if(( ISR_RXIDLE | ISR_RXDESC | ISR_RXERR) & isr)
+ kick_rx();
+ for (i = 0; i < NR_RX_DESC; i++) {
+ if (rx_ring[i].cmdsts == CMDSTS_OWN) {
+// rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);
+ rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);
+ }
+ }
+}
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int ns83820_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ u32 cmdsts;
+ int entry = ns->cur_rx;
+
+ ns83820_check_intr(nic);
+
+ cmdsts = le32_to_cpu(rx_ring[entry].cmdsts);
+
+ if ( ! ( (CMDSTS_OWN & (cmdsts)) && (cmdsts != (CMDSTS_OWN)) ) )
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ if (! (CMDSTS_OK & cmdsts) )
+ return 0;
+
+ nic->packetlen = cmdsts & 0xffff;
+ memcpy(nic->packet,
+ rxb + (entry * REAL_RX_BUF_SIZE),
+ nic->packetlen);
+ // rx_ring[entry].link = 0;
+ rx_ring[entry].cmdsts = cpu_to_le32(CMDSTS_OWN);
+
+ ns->cur_rx = ++ns->cur_rx % NR_RX_DESC;
+
+ if (ns->cur_rx == 0) /* We have wrapped the ring */
+ kick_rx();
+
+ return 1;
+}
+
+static inline void kick_tx(struct nic *nic __unused)
+{
+ dprintf(("kick_tx\n"));
+ writel(CR_TXE, ns->base + CR);
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void ns83820_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ /* send the packet to destination */
+
+ u16 nstype;
+ u32 cmdsts, extsts;
+ int cur_tx = 0;
+ u32 isr = readl(ns->base + ISR);
+ if (ISR_TXIDLE & isr)
+ kick_tx(nic);
+ /* point to the current txb incase multiple tx_rings are used */
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+ /* Setup the transmit descriptor */
+ extsts = 0;
+ extsts |= EXTSTS_UDPPKT;
+
+ tx_ring[cur_tx].bufptr = virt_to_le32desc(&txb);
+ tx_ring[cur_tx].extsts = cpu_to_le32(extsts);
+
+ cmdsts = cpu_to_le32(0);
+ cmdsts |= cpu_to_le32(CMDSTS_OWN | s);
+ tx_ring[cur_tx].cmdsts = cpu_to_le32(cmdsts);
+
+ writel(virt_to_le32desc(&tx_ring[0]), ns->base + TXDP);
+ kick_tx(nic);
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void ns83820_disable ( struct nic *nic ) {
+
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ */
+ /* disable interrupts */
+ writel(0, ns->base + IMR);
+ writel(0, ns->base + IER);
+ readl(ns->base + IER);
+
+ ns->up = 0;
+
+ ns83820_do_reset(nic, CR_RST);
+
+ ns->IMR_cache &=
+ ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY |
+ ISR_RXIDLE);
+ writel(ns->IMR_cache, ns->base + IMR);
+
+ /* touch the pci bus... */
+ readl(ns->base + IMR);
+
+ /* assumes the transmitter is already disabled and reset */
+ writel(0, ns->base + RXDP_HI);
+ writel(0, ns->base + RXDP);
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void ns83820_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations ns83820_operations = {
+ .connect = dummy_connect,
+ .poll = ns83820_poll,
+ .transmit = ns83820_transmit,
+ .irq = ns83820_irq,
+
+};
+
+static struct pci_device_id ns83820_nics[] = {
+ PCI_ROM(0x100b, 0x0022, "ns83820", "National Semiconductor 83820", 0),
+};
+
+PCI_DRIVER ( ns83820_driver, ns83820_nics, PCI_NO_CLASS );
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+
+#define board_found 1
+#define valid_link 0
+static int ns83820_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ long addr;
+ int using_dac = 0;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ printf("ns83820.c: vendor=0x%hX, device=0x%hX\n",
+ pci->vendor, pci->device);
+
+ /* point to private storage */
+ ns = &nsx;
+
+ adjust_pci_device(pci);
+
+ addr = pci_bar_start(pci, PCI_BASE_ADDRESS_1);
+
+ ns->base = ioremap(addr, (1UL << 12));
+
+ if (!ns->base)
+ return 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr & ~3;
+
+ /* disable interrupts */
+ writel(0, ns->base + IMR);
+ writel(0, ns->base + IER);
+ readl(ns->base + IER);
+
+ ns->IMR_cache = 0;
+
+ ns83820_do_reset(nic, CR_RST);
+
+ /* Must reset the ram bist before running it */
+ writel(PTSCR_RBIST_RST, ns->base + PTSCR);
+ ns83820_run_bist(nic, "sram bist", PTSCR_RBIST_EN,
+ PTSCR_RBIST_DONE, PTSCR_RBIST_FAIL);
+ ns83820_run_bist(nic, "eeprom bist", PTSCR_EEBIST_EN, 0,
+ PTSCR_EEBIST_FAIL);
+ ns83820_run_bist(nic, "eeprom load", PTSCR_EELOAD_EN, 0, 0);
+
+ /* I love config registers */
+ ns->CFG_cache = readl(ns->base + CFG);
+
+ if ((ns->CFG_cache & CFG_PCI64_DET)) {
+ printf("detected 64 bit PCI data bus.\n");
+ /*dev->CFG_cache |= CFG_DATA64_EN; */
+ if (!(ns->CFG_cache & CFG_DATA64_EN))
+ printf
+ ("EEPROM did not enable 64 bit bus. Disabled.\n");
+ } else
+ ns->CFG_cache &= ~(CFG_DATA64_EN);
+
+ ns->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS |
+ CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 |
+ CFG_M64ADDR);
+ ns->CFG_cache |=
+ CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS |
+ CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL;
+ ns->CFG_cache |= CFG_REQALG;
+ ns->CFG_cache |= CFG_POW;
+ ns->CFG_cache |= CFG_TMRTEST;
+
+ /* When compiled with 64 bit addressing, we must always enable
+ * the 64 bit descriptor format.
+ */
+#ifdef USE_64BIT_ADDR
+ ns->CFG_cache |= CFG_M64ADDR;
+#endif
+
+//FIXME: Enable section on dac or remove this
+ if (using_dac)
+ ns->CFG_cache |= CFG_T64ADDR;
+
+ /* Big endian mode does not seem to do what the docs suggest */
+ ns->CFG_cache &= ~CFG_BEM;
+
+ /* setup optical transceiver if we have one */
+ if (ns->CFG_cache & CFG_TBI_EN) {
+ dprintf(("%s: enabling optical transceiver\n", pci->driver_name));
+ writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR);
+
+ /* setup auto negotiation feature advertisement */
+ writel(readl(ns->base + TANAR)
+ | TANAR_HALF_DUP | TANAR_FULL_DUP,
+ ns->base + TANAR);
+
+ /* start auto negotiation */
+ writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,
+ ns->base + TBICR);
+ writel(TBICR_MR_AN_ENABLE, ns->base + TBICR);
+ ns->linkstate = LINK_AUTONEGOTIATE;
+
+ ns->CFG_cache |= CFG_MODE_1000;
+ }
+ writel(ns->CFG_cache, ns->base + CFG);
+ dprintf(("CFG: %hX\n", ns->CFG_cache));
+
+ /* FIXME: reset_phy is defaulted to 0, should we reset anyway? */
+ if (reset_phy) {
+ dprintf(("%s: resetting phy\n", pci->driver_name));
+ writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG);
+ writel(ns->CFG_cache, ns->base + CFG);
+ }
+#if 0 /* Huh? This sets the PCI latency register. Should be done via
+ * the PCI layer. FIXME.
+ */
+ if (readl(dev->base + SRR))
+ writel(readl(dev->base + 0x20c) | 0xfe00,
+ dev->base + 0x20c);
+#endif
+
+ /* Note! The DMA burst size interacts with packet
+ * transmission, such that the largest packet that
+ * can be transmitted is 8192 - FLTH - burst size.
+ * If only the transmit fifo was larger...
+ */
+ /* Ramit : 1024 DMA is not a good idea, it ends up banging
+ * some DELL and COMPAQ SMP systems */
+ writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA512
+ | ((1600 / 32) * 0x100), ns->base + TXCFG);
+
+ /* Set Rx to full duplex, don't accept runt, errored, long or length
+ * range errored packets. Use 512 byte DMA.
+ */
+ /* Ramit : 1024 DMA is not a good idea, it ends up banging
+ * some DELL and COMPAQ SMP systems
+ * Turn on ALP, only we are accpeting Jumbo Packets */
+ writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD
+ | RXCFG_STRIPCRC
+ //| RXCFG_ALP
+ | (RXCFG_MXDMA512) | 0, ns->base + RXCFG);
+
+ /* Disable priority queueing */
+ writel(0, ns->base + PQCR);
+
+ /* Enable IP checksum validation and detetion of VLAN headers.
+ * Note: do not set the reject options as at least the 0x102
+ * revision of the chip does not properly accept IP fragments
+ * at least for UDP.
+ */
+ /* Ramit : Be sure to turn on RXCFG_ARP if VLAN's are enabled, since
+ * the MAC it calculates the packetsize AFTER stripping the VLAN
+ * header, and if a VLAN Tagged packet of 64 bytes is received (like
+ * a ping with a VLAN header) then the card, strips the 4 byte VLAN
+ * tag and then checks the packet size, so if RXCFG_ARP is not enabled,
+ * it discrards it!. These guys......
+ */
+ writel(VRCR_IPEN | VRCR_VTDEN, ns->base + VRCR);
+
+ /* Enable per-packet TCP/UDP/IP checksumming */
+ writel(VTCR_PPCHK, ns->base + VTCR);
+
+ /* Ramit : Enable async and sync pause frames */
+// writel(0, ns->base + PCR);
+ writel((PCR_PS_MCAST | PCR_PS_DA | PCR_PSEN | PCR_FFLO_4K |
+ PCR_FFHI_8K | PCR_STLO_4 | PCR_STHI_8 | PCR_PAUSE_CNT),
+ ns->base + PCR);
+
+ /* Disable Wake On Lan */
+ writel(0, ns->base + WCSR);
+
+ ns83820_getmac(nic, nic->node_addr);
+
+ if (using_dac) {
+ dprintf(("%s: using 64 bit addressing.\n", pci->driver_name));
+ }
+
+ dprintf(("%s: DP83820 %d.%d: %! io=0x%hX\n",
+ pci->driver_name,
+ (unsigned) readl(ns->base + SRR) >> 8,
+ (unsigned) readl(ns->base + SRR) & 0xff,
+ nic->node_addr, pci->ioaddr));
+
+#ifdef PHY_CODE_IS_FINISHED
+ ns83820_probe_phy(dev);
+#endif
+
+ ns83820_reset(nic);
+ /* point to NIC specific routines */
+ nic->nic_op = &ns83820_operations;
+ return 1;
+}
+
+DRIVER ( "NS83820/PCI", nic_driver, pci_driver, ns83820_driver,
+ ns83820_probe, ns83820_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.c
new file mode 100644
index 0000000..97f1141
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.c
@@ -0,0 +1,1037 @@
+/**************************************************************************
+ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters
+ Date: May/94
+
+ This code is based heavily on David Greenman's if_ed.c driver
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
+Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
+3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
+SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
+3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
+RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
+ parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
+SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
+ based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
+
+**************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+/* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
+
+#if 1
+
+#if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
+ !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
+ /* The driver named ns8390 is the PCI driver, often called
+ "PCI ne2000 clones". */
+# define INCLUDE_NS8390 1
+#endif
+
+#include "etherboot.h"
+#include "nic.h"
+#include "ns8390.h"
+#include <gpxe/ethernet.h>
+#ifdef INCLUDE_NS8390
+#include <gpxe/pci.h>
+#else
+#include <gpxe/isa.h>
+#endif
+
+static unsigned char eth_vendor, eth_flags;
+#ifdef INCLUDE_WD
+static unsigned char eth_laar;
+#endif
+static unsigned short eth_nic_base, eth_asic_base;
+static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
+static Address eth_bmem, eth_rmem;
+static unsigned char eth_drain_receiver;
+
+#ifdef INCLUDE_WD
+static struct wd_board {
+ const char *name;
+ char id;
+ char flags;
+ char memsize;
+} wd_boards[] = {
+ {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
+ {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
+ {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
+ {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
+ {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
+ {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
+ {"WD8003EP/WD8013EP",
+ TYPE_WD8013EP, 0, MEM_8192},
+ {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
+ {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
+ {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
+ {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
+ {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
+ {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
+ {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
+ {NULL, 0, 0, 0}
+};
+#endif
+
+#ifdef INCLUDE_3C503
+static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
+#endif
+
+#if defined(INCLUDE_WD)
+#define ASIC_PIO WD_IAR
+#define eth_probe wd_probe
+#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_3C503)
+#define eth_probe t503_probe
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_NE)
+#define eth_probe ne_probe
+#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_NS8390)
+#define eth_probe nepci_probe
+#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
+Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
+#endif
+#endif
+
+#if defined(INCLUDE_3C503)
+#define ASIC_PIO _3COM_RFMSB
+#else
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
+#define ASIC_PIO NE_DATA
+#endif
+#endif
+
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
+/**************************************************************************
+ETH_PIO_READ - Read a frame via Programmed I/O
+**************************************************************************/
+static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
+{
+#ifdef INCLUDE_WD
+ outb(src & 0xff, eth_asic_base + WD_GP2);
+ outb(src >> 8, eth_asic_base + WD_GP2);
+#else
+ outb(D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
+ outb(src, eth_nic_base + D8390_P0_RSAR0);
+ outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD0 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+#ifdef INCLUDE_3C503
+ outb(src & 0xff, eth_asic_base + _3COM_DALSB);
+ outb(src >> 8, eth_asic_base + _3COM_DAMSB);
+ outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
+#endif
+#endif
+
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while(cnt--) {
+#ifdef INCLUDE_3C503
+ while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
+ ;
+#endif
+
+ if (eth_flags & FLAG_16BIT) {
+ *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
+ dst += 2;
+ }
+ else
+ *(dst++) = inb(eth_asic_base + ASIC_PIO);
+ }
+
+#ifdef INCLUDE_3C503
+ outb(t503_output, eth_asic_base + _3COM_CR);
+#endif
+}
+
+/**************************************************************************
+ETH_PIO_WRITE - Write a frame via Programmed I/O
+**************************************************************************/
+static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
+{
+#ifdef COMPEX_RL2000_FIX
+ unsigned int x;
+#endif /* COMPEX_RL2000_FIX */
+#ifdef INCLUDE_WD
+ outb(dst & 0xff, eth_asic_base + WD_GP2);
+ outb(dst >> 8, eth_asic_base + WD_GP2);
+#else
+ outb(D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+ outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
+ outb(cnt, eth_nic_base + D8390_P0_RBCR0);
+ outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
+ outb(dst, eth_nic_base + D8390_P0_RSAR0);
+ outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
+ outb(D8390_COMMAND_RD1 |
+ D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
+
+#ifdef INCLUDE_3C503
+ outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
+ outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
+
+ outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
+#endif
+#endif
+
+ if (eth_flags & FLAG_16BIT)
+ cnt = (cnt + 1) >> 1;
+
+ while(cnt--)
+ {
+#ifdef INCLUDE_3C503
+ while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
+ ;
+#endif
+
+ if (eth_flags & FLAG_16BIT) {
+ outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
+ src += 2;
+ }
+ else
+ outb(*(src++), eth_asic_base + ASIC_PIO);
+ }
+
+#ifdef INCLUDE_3C503
+ outb(t503_output, eth_asic_base + _3COM_CR);
+#else
+#ifdef COMPEX_RL2000_FIX
+ for (x = 0;
+ x < COMPEX_RL2000_TRIES &&
+ (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
+ != D8390_ISR_RDC;
+ ++x);
+ if (x >= COMPEX_RL2000_TRIES)
+ printf("Warning: Compex RL2000 aborted wait!\n");
+#endif /* COMPEX_RL2000_FIX */
+#ifndef INCLUDE_WD
+ while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
+ != D8390_ISR_RDC);
+#endif
+#endif
+}
+#else
+/**************************************************************************
+ETH_PIO_READ - Dummy routine when NE2000 not compiled in
+**************************************************************************/
+static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
+#endif
+
+
+/**************************************************************************
+enable_multycast - Enable Multicast
+**************************************************************************/
+static void enable_multicast(unsigned short eth_nic_base)
+{
+ unsigned char mcfilter[8];
+ int i;
+ memset(mcfilter, 0xFF, 8);
+ outb(4, eth_nic_base+D8390_P0_RCR);
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
+ for(i=0;i<8;i++)
+ {
+ outb(mcfilter[i], eth_nic_base + 8 + i);
+ if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
+ printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
+ }
+ outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
+ outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
+}
+
+/**************************************************************************
+NS8390_RESET - Reset adapter
+**************************************************************************/
+static void ns8390_reset(struct nic *nic)
+{
+ int i;
+
+ eth_drain_receiver = 0;
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ if (eth_flags & FLAG_16BIT)
+ outb(0x49, eth_nic_base+D8390_P0_DCR);
+ else
+ outb(0x48, eth_nic_base+D8390_P0_DCR);
+ outb(0, eth_nic_base+D8390_P0_RBCR0);
+ outb(0, eth_nic_base+D8390_P0_RBCR1);
+ outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
+ outb(2, eth_nic_base+D8390_P0_TCR);
+ outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
+ outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790) {
+#ifdef WD_790_PIO
+ outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
+ outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
+#else
+ outb(0, eth_nic_base + 0x09);
+#endif
+ }
+#endif
+ outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
+ outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_IMR);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS1 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS1 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ for (i=0; i<ETH_ALEN; i++)
+ outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
+ for (i=0; i<ETH_ALEN; i++)
+ outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
+ outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ outb(0xFF, eth_nic_base+D8390_P0_ISR);
+ outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
+ outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
+
+ enable_multicast(eth_nic_base);
+
+#ifdef INCLUDE_3C503
+ /*
+ * No way to tell whether or not we're supposed to use
+ * the 3Com's transceiver unless the user tells us.
+ * 'flags' should have some compile time default value
+ * which can be changed from the command menu.
+ */
+ t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
+ outb(t503_output, eth_asic_base + _3COM_CR);
+#endif
+}
+
+static int ns8390_poll(struct nic *nic, int retrieve);
+
+#ifndef INCLUDE_3C503
+/**************************************************************************
+ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
+**************************************************************************/
+static void eth_rx_overrun(struct nic *nic)
+{
+ int start_time;
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
+
+ /* wait for at least 1.6ms - we wait one timer tick */
+ start_time = currticks();
+ while (currticks() - start_time <= 1)
+ /* Nothing */;
+
+ outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
+ outb(0, eth_nic_base+D8390_P0_RBCR1);
+
+ /*
+ * Linux driver checks for interrupted TX here. This is not necessary,
+ * because the transmit routine waits until the frame is sent.
+ */
+
+ /* enter loopback mode and restart NIC */
+ outb(2, eth_nic_base+D8390_P0_TCR);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+
+ /* clear the RX ring, acknowledge overrun interrupt */
+ eth_drain_receiver = 1;
+ while (ns8390_poll(nic, 1))
+ /* Nothing */;
+ eth_drain_receiver = 0;
+ outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
+
+ /* leave loopback mode - no packets to be resent (see Linux driver) */
+ outb(0, eth_nic_base+D8390_P0_TCR);
+}
+#endif /* INCLUDE_3C503 */
+
+/**************************************************************************
+NS8390_TRANSMIT - Transmit a frame
+**************************************************************************/
+static void ns8390_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+#if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
+ Address eth_vmem = bus_to_virt(eth_bmem);
+#endif
+#ifdef INCLUDE_3C503
+ if (!(eth_flags & FLAG_PIO)) {
+ memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
+ memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+ *((char *)eth_vmem+12) = t>>8; /* type */
+ *((char *)eth_vmem+13) = t;
+ memcpy((char *)eth_vmem+ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
+ }
+#endif
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+#ifndef WD_790_PIO
+ /* Memory interface */
+ if (eth_flags & FLAG_790) {
+ outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+ inb(0x84);
+ memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
+ memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+ *((char *)eth_vmem+12) = t>>8; /* type */
+ *((char *)eth_vmem+13) = t;
+ memcpy((char *)eth_vmem+ETH_HLEN, p, s);
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
+ if (eth_flags & FLAG_790) {
+ outb(0, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+#else
+ inb(0x84);
+#endif
+#endif
+
+#if defined(INCLUDE_3C503)
+ if (eth_flags & FLAG_PIO)
+#endif
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
+ {
+ /* Programmed I/O */
+ unsigned short type;
+ type = (t >> 8) | (t << 8);
+ eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
+ eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
+ /* bcc generates worse code without (const+const) below */
+ eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
+ eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
+ s += ETH_HLEN;
+ if (s < ETH_ZLEN) s = ETH_ZLEN;
+ }
+#endif
+#if defined(INCLUDE_3C503)
+#endif
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
+ outb(s, eth_nic_base+D8390_P0_TBCR0);
+ outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_790)
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+ else
+#endif
+ outb(D8390_COMMAND_PS0 |
+ D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
+ D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
+}
+
+/**************************************************************************
+NS8390_POLL - Wait for a frame
+**************************************************************************/
+static int ns8390_poll(struct nic *nic, int retrieve)
+{
+ int ret = 0;
+ unsigned char rstat, curr, next;
+ unsigned short len, frag;
+ unsigned short pktoff;
+ unsigned char *p;
+ struct ringbuffer pkthdr;
+
+#ifndef INCLUDE_3C503
+ /* avoid infinite recursion: see eth_rx_overrun() */
+ if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
+ eth_rx_overrun(nic);
+ return(0);
+ }
+#endif /* INCLUDE_3C503 */
+ rstat = inb(eth_nic_base+D8390_P0_RSR);
+ if (!(rstat & D8390_RSTAT_PRX)) return(0);
+ next = inb(eth_nic_base+D8390_P0_BOUND)+1;
+ if (next >= eth_memsize) next = eth_rx_start;
+ outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
+ curr = inb(eth_nic_base+D8390_P1_CURR);
+ outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
+ if (curr >= eth_memsize) curr=eth_rx_start;
+ if (curr == next) return(0);
+
+ if ( ! retrieve ) return 1;
+
+#ifdef INCLUDE_WD
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+#ifndef WD_790_PIO
+ if (eth_flags & FLAG_790) {
+ outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+#endif
+ inb(0x84);
+#endif
+ pktoff = next << 8;
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
+ else
+ memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
+ pktoff += sizeof(pkthdr);
+ /* incoming length includes FCS so must sub 4 */
+ len = pkthdr.len - 4;
+ if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
+ || len > ETH_FRAME_LEN) {
+ printf("Bogus packet, ignoring\n");
+ return (0);
+ }
+ else {
+ p = nic->packet;
+ nic->packetlen = len; /* available to caller */
+ frag = (eth_memsize << 8) - pktoff;
+ if (len > frag) { /* We have a wrap-around */
+ /* read first part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, frag);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
+ pktoff = eth_rx_start << 8;
+ p += frag;
+ len -= frag;
+ }
+ /* read second part */
+ if (eth_flags & FLAG_PIO)
+ eth_pio_read(pktoff, p, len);
+ else
+ memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
+ ret = 1;
+ }
+#ifdef INCLUDE_WD
+#ifndef WD_790_PIO
+ if (eth_flags & FLAG_790) {
+ outb(0, eth_asic_base + WD_MSR);
+ inb(0x84);
+ }
+#endif
+ if (eth_flags & FLAG_16BIT) {
+ outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ inb(0x84);
+ }
+ inb(0x84);
+#endif
+ next = pkthdr.next; /* frame number of next packet */
+ if (next == eth_rx_start)
+ next = eth_memsize;
+ outb(next-1, eth_nic_base+D8390_P0_BOUND);
+ return(ret);
+}
+
+/**************************************************************************
+NS8390_DISABLE - Turn off adapter
+**************************************************************************/
+static void ns8390_disable ( struct nic *nic ) {
+ ns8390_reset(nic);
+}
+
+/**************************************************************************
+NS8390_IRQ - Enable, Disable, or Force interrupts
+**************************************************************************/
+static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations ns8390_operations;
+static struct nic_operations ns8390_operations = {
+ .connect = dummy_connect,
+ .poll = ns8390_poll,
+ .transmit = ns8390_transmit,
+ .irq = ns8390_irq,
+};
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+**************************************************************************/
+#ifdef INCLUDE_NS8390
+static int eth_probe (struct nic *nic, struct pci_device *pci)
+#else
+static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
+#endif
+{
+ int i;
+#ifdef INCLUDE_NS8390
+ unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
+ unsigned short *probe_addrs = pci_probe_addrs;
+#endif
+ eth_vendor = VENDOR_NONE;
+ eth_drain_receiver = 0;
+
+ nic->irqno = 0;
+
+#ifdef INCLUDE_WD
+{
+ /******************************************************************
+ Search for WD/SMC cards
+ ******************************************************************/
+ struct wd_board *brd;
+ unsigned short chksum;
+ unsigned char c;
+ for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
+ eth_asic_base += 0x20) {
+ chksum = 0;
+ for (i=8; i<16; i++)
+ chksum += inb(eth_asic_base+i);
+ /* Extra checks to avoid soundcard */
+ if ((chksum & 0xFF) == 0xFF &&
+ inb(eth_asic_base+8) != 0xFF &&
+ inb(eth_asic_base+9) != 0xFF)
+ break;
+ }
+ if (eth_asic_base > WD_HIGH_BASE)
+ return (0);
+ /* We've found a board */
+ eth_vendor = VENDOR_WD;
+ eth_nic_base = eth_asic_base + WD_NIC_ADDR;
+
+ nic->ioaddr = eth_nic_base;
+
+ c = inb(eth_asic_base+WD_BID); /* Get board id */
+ for (brd = wd_boards; brd->name; brd++)
+ if (brd->id == c) break;
+ if (!brd->name) {
+ printf("Unknown WD/SMC NIC type %hhX\n", c);
+ return (0); /* Unknown type */
+ }
+ eth_flags = brd->flags;
+ eth_memsize = brd->memsize;
+ eth_tx_start = 0;
+ eth_rx_start = D8390_TXBUF_SIZE;
+ if ((c == TYPE_WD8013EP) &&
+ (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
+ eth_flags = FLAG_16BIT;
+ eth_memsize = MEM_16384;
+ }
+ if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
+ eth_bmem = (0x80000 |
+ ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
+ } else
+ eth_bmem = WD_DEFAULT_MEM;
+ if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
+ /* from Linux driver, 8416BT detects as 8216 sometimes */
+ unsigned int addr = inb(eth_asic_base + 0xb);
+ if (((addr >> 4) & 3) == 0) {
+ brd += 2;
+ eth_memsize = brd->memsize;
+ }
+ }
+ outb(0x80, eth_asic_base + WD_MSR); /* Reset */
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
+ }
+ DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
+ if (eth_flags & FLAG_790) {
+#ifdef WD_790_PIO
+ DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
+ eth_bmem = 0;
+ eth_flags |= FLAG_PIO; /* force PIO mode */
+ outb(0, eth_asic_base+WD_MSR);
+#else
+ DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
+
+ outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
+ outb((inb(eth_asic_base+0x04) |
+ 0x80), eth_asic_base+0x04);
+ outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
+ ((unsigned)(eth_bmem >> 11) & 0x40) |
+ (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
+ outb((inb(eth_asic_base+0x04) &
+ ~0x80), eth_asic_base+0x04);
+#endif
+ } else {
+
+ DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
+
+ outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
+ }
+ if (eth_flags & FLAG_16BIT) {
+ if (eth_flags & FLAG_790) {
+ eth_laar = inb(eth_asic_base + WD_LAAR);
+ outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
+ } else {
+ outb((eth_laar =
+ WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
+/*
+ The previous line used to be
+ WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
+ jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
+ it work for WD8013s. This seems to work for my 8013 boards. I
+ don't know what is really happening. I wish I had data sheets
+ or more time to decode the Linux driver. - Ken
+*/
+ }
+ inb(0x84);
+ }
+}
+#endif
+#ifdef INCLUDE_3C503
+#ifdef T503_AUI
+ nic->flags = 1; /* aui */
+#else
+ nic->flags = 0; /* no aui */
+#endif
+ /******************************************************************
+ Search for 3Com 3c503 if no WD/SMC cards
+ ******************************************************************/
+ if (eth_vendor == VENDOR_NONE) {
+ int idx;
+ int iobase_reg, membase_reg;
+ static unsigned short base[] = {
+ 0x300, 0x310, 0x330, 0x350,
+ 0x250, 0x280, 0x2A0, 0x2E0, 0 };
+
+ /* Loop through possible addresses checking each one */
+
+ for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
+
+ eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
+/*
+ * Note that we use the same settings for both 8 and 16 bit cards:
+ * both have an 8K bank of memory at page 1 while only the 16 bit
+ * cards have a bank at page 0.
+ */
+ eth_memsize = MEM_16384;
+ eth_tx_start = 32;
+ eth_rx_start = 32 + D8390_TXBUF_SIZE;
+
+ /* Check our base address. iobase and membase should */
+ /* both have a maximum of 1 bit set or be 0. */
+
+ iobase_reg = inb(eth_asic_base + _3COM_BCFR);
+ membase_reg = inb(eth_asic_base + _3COM_PCFR);
+
+ if ((iobase_reg & (iobase_reg - 1)) ||
+ (membase_reg & (membase_reg - 1)))
+ continue; /* nope */
+
+ /* Now get the shared memory address */
+
+ eth_flags = 0;
+
+ switch (membase_reg) {
+ case _3COM_PCFR_DC000:
+ eth_bmem = 0xdc000;
+ break;
+ case _3COM_PCFR_D8000:
+ eth_bmem = 0xd8000;
+ break;
+ case _3COM_PCFR_CC000:
+ eth_bmem = 0xcc000;
+ break;
+ case _3COM_PCFR_C8000:
+ eth_bmem = 0xc8000;
+ break;
+ case _3COM_PCFR_PIO:
+ eth_flags |= FLAG_PIO;
+ eth_bmem = 0;
+ break;
+ default:
+ continue; /* nope */
+ }
+ break;
+ }
+
+ if (base[idx] == 0) /* not found */
+ return (0);
+#ifndef T503_SHMEM
+ eth_flags |= FLAG_PIO; /* force PIO mode */
+ eth_bmem = 0;
+#endif
+ eth_vendor = VENDOR_3COM;
+
+
+ /* Need this to make ns8390_poll() happy. */
+
+ eth_rmem = eth_bmem - 0x2000;
+
+ /* Reset NIC and ASIC */
+
+ outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
+ outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
+
+ /* Get our ethernet address */
+
+ outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
+ nic->ioaddr = eth_nic_base;
+ DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
+ if (eth_flags & FLAG_PIO)
+ DBG ( "PIO mode" );
+ else
+ DBG ( "memory %4.4x", eth_bmem );
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = inb(eth_nic_base+i);
+ }
+ DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
+ eth_ntoa ( nic->node_addr ) );
+
+ outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
+ /*
+ * Initialize GA configuration register. Set bank and enable shared
+ * mem. We always use bank 1. Disable interrupts.
+ */
+ outb(_3COM_GACFR_RSEL |
+ _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
+
+ outb(0xff, eth_asic_base + _3COM_VPTR2);
+ outb(0xff, eth_asic_base + _3COM_VPTR1);
+ outb(0x00, eth_asic_base + _3COM_VPTR0);
+ /*
+ * Clear memory and verify that it worked (we use only 8K)
+ */
+
+ if (!(eth_flags & FLAG_PIO)) {
+ memset(bus_to_virt(eth_bmem), 0, 0x2000);
+ for(i = 0; i < 0x2000; ++i)
+ if (*((char *)(bus_to_virt(eth_bmem+i)))) {
+ printf ("Failed to clear 3c503 shared mem.\n");
+ return (0);
+ }
+ }
+ /*
+ * Initialize GA page/start/stop registers.
+ */
+ outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
+ outb(eth_memsize, eth_asic_base + _3COM_PSPR);
+ }
+#endif
+#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
+{
+ /******************************************************************
+ Search for NE1000/2000 if no WD/SMC or 3com cards
+ ******************************************************************/
+ unsigned char c;
+ if (eth_vendor == VENDOR_NONE) {
+ unsigned char romdata[16];
+ unsigned char testbuf[32];
+ int idx;
+ static unsigned char test[] = "NE*000 memory";
+ static unsigned short base[] = {
+#ifdef NE_SCAN
+ NE_SCAN,
+#endif
+ 0 };
+ /* if no addresses supplied, fall back on defaults */
+ if (probe_addrs == 0 || probe_addrs[0] == 0)
+ probe_addrs = base;
+ eth_bmem = 0; /* No shared memory */
+ for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
+ eth_flags = FLAG_PIO;
+ eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
+ eth_memsize = MEM_16384;
+ eth_tx_start = 32;
+ eth_rx_start = 32 + D8390_TXBUF_SIZE;
+ c = inb(eth_asic_base + NE_RESET);
+ outb(c, eth_asic_base + NE_RESET);
+ (void) inb(0x84);
+ outb(D8390_COMMAND_STP |
+ D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
+ outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
+ outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
+ outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
+#ifdef NS8390_FORCE_16BIT
+ eth_flags |= FLAG_16BIT; /* force 16-bit mode */
+#endif
+
+ eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
+ eth_pio_read(8192, testbuf, sizeof(test));
+ if (!memcmp(test, testbuf, sizeof(test)))
+ break;
+ eth_flags |= FLAG_16BIT;
+ eth_memsize = MEM_32768;
+ eth_tx_start = 64;
+ eth_rx_start = 64 + D8390_TXBUF_SIZE;
+ outb(D8390_DCR_WTS |
+ D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
+ outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
+ outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
+ eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
+ eth_pio_read(16384, testbuf, sizeof(test));
+ if (!memcmp(testbuf, test, sizeof(test)))
+ break;
+ }
+ if (eth_nic_base == 0)
+ return (0);
+ if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
+ eth_flags |= FLAG_16BIT;
+ eth_vendor = VENDOR_NOVELL;
+ eth_pio_read(0, romdata, sizeof(romdata));
+ for (i=0; i<ETH_ALEN; i++) {
+ nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
+ }
+ nic->ioaddr = eth_nic_base;
+ DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
+ (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
+ eth_ntoa ( nic->node_addr ) );
+ }
+}
+#endif
+ if (eth_vendor == VENDOR_NONE)
+ return(0);
+ if (eth_vendor != VENDOR_3COM)
+ eth_rmem = eth_bmem;
+ ns8390_reset(nic);
+ nic->nic_op = &ns8390_operations;
+
+ /* Based on PnP ISA map */
+#ifdef INCLUDE_WD
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.device_id = htons(0x812a);
+#endif
+#ifdef INCLUDE_3C503
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.device_id = htons(0x80f3);
+#endif
+#ifdef INCLUDE_NE
+ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
+ dev->devid.device_id = htons(0x80d6);
+#endif
+ return 1;
+}
+
+#ifdef INCLUDE_WD
+struct isa_driver wd_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "WD",
+ .probe = wd_probe,
+ .ioaddrs = 0,
+};
+ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
+#endif
+
+#ifdef INCLUDE_3C503
+struct isa_driver t503_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "3C503",
+ .probe = t503_probe,
+ .ioaddrs = 0,
+};
+ISA_ROM("3c503","3Com503, Etherlink II[/16]");
+#endif
+
+#ifdef INCLUDE_NE
+struct isa_driver ne_driver __isa_driver = {
+ .type = NIC_DRIVER,
+ .name = "NE*000",
+ .probe = ne_probe,
+ .ioaddrs = 0,
+};
+ISA_ROM("ne","NE1000/2000 and clones");
+#endif
+
+#ifdef INCLUDE_NS8390
+static struct pci_device_id nepci_nics[] = {
+/* A few NE2000 PCI clones, list not exhaustive */
+PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
+PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
+PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0), /* Winbond 86C940 / 89C940 */
+PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0), /* Winbond 89C940F */
+PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
+PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
+PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
+PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
+PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
+PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
+PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
+};
+
+PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
+
+DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
+ nepci_probe, ns8390_disable );
+
+#endif /* INCLUDE_NS8390 */
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.h
new file mode 100644
index 0000000..79728e7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/ns8390.h
@@ -0,0 +1,240 @@
+/**************************************************************************
+ETHERBOOT - BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters
+ Date: Jun/94
+
+**************************************************************************/
+
+FILE_LICENCE ( BSD2 );
+
+#define VENDOR_NONE 0
+#define VENDOR_WD 1
+#define VENDOR_NOVELL 2
+#define VENDOR_3COM 3
+
+#define FLAG_PIO 0x01
+#define FLAG_16BIT 0x02
+#define FLAG_790 0x04
+
+#define MEM_8192 32
+#define MEM_16384 64
+#define MEM_32768 128
+
+#define ISA_MAX_ADDR 0x400
+
+/**************************************************************************
+Western Digital/SMC Board Definitions
+**************************************************************************/
+#define WD_LOW_BASE 0x200
+#define WD_HIGH_BASE 0x3e0
+#ifndef WD_DEFAULT_MEM
+#define WD_DEFAULT_MEM 0xD0000
+#endif
+#define WD_NIC_ADDR 0x10
+
+/**************************************************************************
+Western Digital/SMC ASIC Addresses
+**************************************************************************/
+#define WD_MSR 0x00
+#define WD_ICR 0x01
+#define WD_IAR 0x02
+#define WD_BIO 0x03
+#define WD_IRR 0x04
+#define WD_LAAR 0x05
+#define WD_IJR 0x06
+#define WD_GP2 0x07
+#define WD_LAR 0x08
+#define WD_BID 0x0E
+
+#define WD_ICR_16BIT 0x01
+
+#define WD_MSR_MENB 0x40
+
+#define WD_LAAR_L16EN 0x40
+#define WD_LAAR_M16EN 0x80
+
+#define WD_SOFTCONFIG 0x20
+
+/**************************************************************************
+Western Digital/SMC Board Types
+**************************************************************************/
+#define TYPE_WD8003S 0x02
+#define TYPE_WD8003E 0x03
+#define TYPE_WD8013EBT 0x05
+#define TYPE_WD8003W 0x24
+#define TYPE_WD8003EB 0x25
+#define TYPE_WD8013W 0x26
+#define TYPE_WD8013EP 0x27
+#define TYPE_WD8013WC 0x28
+#define TYPE_WD8013EPC 0x29
+#define TYPE_SMC8216T 0x2a
+#define TYPE_SMC8216C 0x2b
+#define TYPE_SMC8416T 0x00 /* Bogus entries: the 8416 generates the */
+#define TYPE_SMC8416C 0x00 /* the same codes as the 8216. */
+#define TYPE_SMC8013EBP 0x2c
+
+/**************************************************************************
+3com 3c503 definitions
+**************************************************************************/
+
+#ifndef _3COM_BASE
+#define _3COM_BASE 0x300
+#endif
+
+#define _3COM_TX_PAGE_OFFSET_8BIT 0x20
+#define _3COM_TX_PAGE_OFFSET_16BIT 0x0
+#define _3COM_RX_PAGE_OFFSET_16BIT 0x20
+
+#define _3COM_ASIC_OFFSET 0x400
+#define _3COM_NIC_OFFSET 0x0
+
+#define _3COM_PSTR 0
+#define _3COM_PSPR 1
+
+#define _3COM_BCFR 3
+#define _3COM_BCFR_2E0 0x01
+#define _3COM_BCFR_2A0 0x02
+#define _3COM_BCFR_280 0x04
+#define _3COM_BCFR_250 0x08
+#define _3COM_BCFR_350 0x10
+#define _3COM_BCFR_330 0x20
+#define _3COM_BCFR_310 0x40
+#define _3COM_BCFR_300 0x80
+#define _3COM_PCFR 4
+#define _3COM_PCFR_PIO 0
+#define _3COM_PCFR_C8000 0x10
+#define _3COM_PCFR_CC000 0x20
+#define _3COM_PCFR_D8000 0x40
+#define _3COM_PCFR_DC000 0x80
+#define _3COM_CR 6
+#define _3COM_CR_RST 0x01 /* Reset GA and NIC */
+#define _3COM_CR_XSEL 0x02 /* Transceiver select. BNC=1(def) AUI=0 */
+#define _3COM_CR_EALO 0x04 /* window EA PROM 0-15 to I/O base */
+#define _3COM_CR_EAHI 0x08 /* window EA PROM 16-31 to I/O base */
+#define _3COM_CR_SHARE 0x10 /* select interrupt sharing option */
+#define _3COM_CR_DBSEL 0x20 /* Double buffer select */
+#define _3COM_CR_DDIR 0x40 /* DMA direction select */
+#define _3COM_CR_START 0x80 /* Start DMA controller */
+#define _3COM_GACFR 5
+#define _3COM_GACFR_MBS0 0x01
+#define _3COM_GACFR_MBS1 0x02
+#define _3COM_GACFR_MBS2 0x04
+#define _3COM_GACFR_RSEL 0x08 /* enable shared memory */
+#define _3COM_GACFR_TEST 0x10 /* for GA testing */
+#define _3COM_GACFR_OWS 0x20 /* select 0WS access to GA */
+#define _3COM_GACFR_TCM 0x40 /* Mask DMA interrupts */
+#define _3COM_GACFR_NIM 0x80 /* Mask NIC interrupts */
+#define _3COM_STREG 7
+#define _3COM_STREG_REV 0x07 /* GA revision */
+#define _3COM_STREG_DIP 0x08 /* DMA in progress */
+#define _3COM_STREG_DTC 0x10 /* DMA terminal count */
+#define _3COM_STREG_OFLW 0x20 /* Overflow */
+#define _3COM_STREG_UFLW 0x40 /* Underflow */
+#define _3COM_STREG_DPRDY 0x80 /* Data port ready */
+#define _3COM_IDCFR 8
+#define _3COM_IDCFR_DRQ0 0x01 /* DMA request 1 select */
+#define _3COM_IDCFR_DRQ1 0x02 /* DMA request 2 select */
+#define _3COM_IDCFR_DRQ2 0x04 /* DMA request 3 select */
+#define _3COM_IDCFR_UNUSED 0x08 /* not used */
+#define _3COM_IDCFR_IRQ2 0x10 /* Interrupt request 2 select */
+#define _3COM_IDCFR_IRQ3 0x20 /* Interrupt request 3 select */
+#define _3COM_IDCFR_IRQ4 0x40 /* Interrupt request 4 select */
+#define _3COM_IDCFR_IRQ5 0x80 /* Interrupt request 5 select */
+#define _3COM_IRQ2 2
+#define _3COM_IRQ3 3
+#define _3COM_IRQ4 4
+#define _3COM_IRQ5 5
+#define _3COM_DAMSB 9
+#define _3COM_DALSB 0x0a
+#define _3COM_VPTR2 0x0b
+#define _3COM_VPTR1 0x0c
+#define _3COM_VPTR0 0x0d
+#define _3COM_RFMSB 0x0e
+#define _3COM_RFLSB 0x0f
+
+/**************************************************************************
+NE1000/2000 definitions
+**************************************************************************/
+#define NE_ASIC_OFFSET 0x10
+#define NE_RESET 0x0F /* Used to reset card */
+#define NE_DATA 0x00 /* Used to read/write NIC mem */
+
+#define COMPEX_RL2000_TRIES 200
+
+/**************************************************************************
+8390 Register Definitions
+**************************************************************************/
+#define D8390_P0_COMMAND 0x00
+#define D8390_P0_PSTART 0x01
+#define D8390_P0_PSTOP 0x02
+#define D8390_P0_BOUND 0x03
+#define D8390_P0_TSR 0x04
+#define D8390_P0_TPSR 0x04
+#define D8390_P0_TBCR0 0x05
+#define D8390_P0_TBCR1 0x06
+#define D8390_P0_ISR 0x07
+#define D8390_P0_RSAR0 0x08
+#define D8390_P0_RSAR1 0x09
+#define D8390_P0_RBCR0 0x0A
+#define D8390_P0_RBCR1 0x0B
+#define D8390_P0_RSR 0x0C
+#define D8390_P0_RCR 0x0C
+#define D8390_P0_TCR 0x0D
+#define D8390_P0_DCR 0x0E
+#define D8390_P0_IMR 0x0F
+#define D8390_P1_COMMAND 0x00
+#define D8390_P1_PAR0 0x01
+#define D8390_P1_PAR1 0x02
+#define D8390_P1_PAR2 0x03
+#define D8390_P1_PAR3 0x04
+#define D8390_P1_PAR4 0x05
+#define D8390_P1_PAR5 0x06
+#define D8390_P1_CURR 0x07
+#define D8390_P1_MAR0 0x08
+
+#define D8390_COMMAND_PS0 0x0 /* Page 0 select */
+#define D8390_COMMAND_PS1 0x40 /* Page 1 select */
+#define D8390_COMMAND_PS2 0x80 /* Page 2 select */
+#define D8390_COMMAND_RD2 0x20 /* Remote DMA control */
+#define D8390_COMMAND_RD1 0x10
+#define D8390_COMMAND_RD0 0x08
+#define D8390_COMMAND_TXP 0x04 /* transmit packet */
+#define D8390_COMMAND_STA 0x02 /* start */
+#define D8390_COMMAND_STP 0x01 /* stop */
+
+#define D8390_RCR_MON 0x20 /* monitor mode */
+
+#define D8390_DCR_FT1 0x40
+#define D8390_DCR_LS 0x08 /* Loopback select */
+#define D8390_DCR_WTS 0x01 /* Word transfer select */
+
+#define D8390_ISR_PRX 0x01 /* successful recv */
+#define D8390_ISR_PTX 0x02 /* successful xmit */
+#define D8390_ISR_RXE 0x04 /* receive error */
+#define D8390_ISR_TXE 0x08 /* transmit error */
+#define D8390_ISR_OVW 0x10 /* Overflow */
+#define D8390_ISR_CNT 0x20 /* Counter overflow */
+#define D8390_ISR_RDC 0x40 /* Remote DMA complete */
+#define D8390_ISR_RST 0x80 /* reset */
+
+#define D8390_RSTAT_PRX 0x01 /* successful recv */
+#define D8390_RSTAT_CRC 0x02 /* CRC error */
+#define D8390_RSTAT_FAE 0x04 /* Frame alignment error */
+#define D8390_RSTAT_OVER 0x08 /* FIFO overrun */
+
+#define D8390_TXBUF_SIZE 6
+#define D8390_RXBUF_END 32
+#define D8390_PAGE_SIZE 256
+
+struct ringbuffer {
+ unsigned char status;
+ unsigned char next;
+ unsigned short len;
+};
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/pcnet32.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/pcnet32.c
new file mode 100644
index 0000000..223bc1e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/pcnet32.c
@@ -0,0 +1,1021 @@
+/**************************************************************************
+*
+* pcnet32.c -- Etherboot device driver for the AMD PCnet32
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* pcnet32.c: An AMD PCnet32 ethernet driver for linux:
+*
+* (C) 1996-1999 Thomas Bogendoerfer
+* See Linux Driver for full information
+*
+* The transmit and poll functions were written with reference to:
+* lance.c - LANCE NIC driver for Etherboot written by Ken Yap
+*
+* Linux Driver Version 1.27a, 10.02.2002
+*
+*
+* REVISION HISTORY:
+* ================
+* v1.0 08-06-2003 timlegge Initial port of Linux driver
+* v1.1 08-23-2003 timlegge Add multicast support
+* v1.2 01-17-2004 timlegge Initial driver output cleanup
+* v1.3 03-29-2004 timlegge More driver cleanup
+*
+* Indent Options: indent -kr -i8
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include "mii.h"
+
+/* void hex_dump(const char *data, const unsigned int len); */
+
+/* Etherboot Specific definations */
+#define drv_version "v1.3"
+#define drv_date "03-29-2004"
+
+static u32 ioaddr; /* Globally used for the card's io address */
+static struct nic_operations pcnet32_operations;
+
+#ifdef EDEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* End Etherboot Specific */
+
+static int cards_found = 0 /* __initdata */ ;
+
+#ifdef REMOVE
+/* FIXME: Remove these they are probably pointless */
+
+/*
+ * VLB I/O addresses
+ */
+static unsigned int pcnet32_portlist[] /*__initdata */ =
+{ 0x300, 0x320, 0x340, 0x360, 0 };
+
+static int pcnet32_debug = 1;
+static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
+static int pcnet32vlb; /* check for VLB cards ? */
+
+static struct net_device *pcnet32_dev;
+
+static int max_interrupt_work = 80;
+static int rx_copybreak = 200;
+#endif
+#define PCNET32_PORT_AUI 0x00
+#define PCNET32_PORT_10BT 0x01
+#define PCNET32_PORT_GPSI 0x02
+#define PCNET32_PORT_MII 0x03
+
+#define PCNET32_PORT_PORTSEL 0x03
+#define PCNET32_PORT_ASEL 0x04
+#define PCNET32_PORT_100 0x40
+#define PCNET32_PORT_FD 0x80
+
+#define PCNET32_DMA_MASK 0xffffffff
+
+/*
+ * table to translate option values from tulip
+ * to internal options
+ */
+static unsigned char options_mapping[] = {
+ PCNET32_PORT_ASEL, /* 0 Auto-select */
+ PCNET32_PORT_AUI, /* 1 BNC/AUI */
+ PCNET32_PORT_AUI, /* 2 AUI/BNC */
+ PCNET32_PORT_ASEL, /* 3 not supported */
+ PCNET32_PORT_10BT | PCNET32_PORT_FD, /* 4 10baseT-FD */
+ PCNET32_PORT_ASEL, /* 5 not supported */
+ PCNET32_PORT_ASEL, /* 6 not supported */
+ PCNET32_PORT_ASEL, /* 7 not supported */
+ PCNET32_PORT_ASEL, /* 8 not supported */
+ PCNET32_PORT_MII, /* 9 MII 10baseT */
+ PCNET32_PORT_MII | PCNET32_PORT_FD, /* 10 MII 10baseT-FD */
+ PCNET32_PORT_MII, /* 11 MII (autosel) */
+ PCNET32_PORT_10BT, /* 12 10BaseT */
+ PCNET32_PORT_MII | PCNET32_PORT_100, /* 13 MII 100BaseTx */
+ PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, /* 14 MII 100BaseTx-FD */
+ PCNET32_PORT_ASEL /* 15 not supported */
+};
+
+#define MAX_UNITS 8 /* More are supported, limit only on options */
+static int options[MAX_UNITS];
+static int full_duplex[MAX_UNITS];
+
+/*
+ * Theory of Operation
+ *
+ * This driver uses the same software structure as the normal lance
+ * driver. So look for a verbose description in lance.c. The differences
+ * to the normal lance driver is the use of the 32bit mode of PCnet32
+ * and PCnetPCI chips. Because these chips are 32bit chips, there is no
+ * 16MB limitation and we don't need bounce buffers.
+ */
+
+
+
+/*
+ * Set the number of Tx and Rx buffers, using Log_2(# buffers).
+ * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
+ * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
+ */
+#ifndef PCNET32_LOG_TX_BUFFERS
+#define PCNET32_LOG_TX_BUFFERS 1
+#define PCNET32_LOG_RX_BUFFERS 2
+#endif
+
+#define TX_RING_SIZE (1 << (PCNET32_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+/* FIXME: Fix this to allow multiple tx_ring descriptors */
+#define TX_RING_LEN_BITS 0x0000 /*PCNET32_LOG_TX_BUFFERS) << 12) */
+
+#define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS ((PCNET32_LOG_RX_BUFFERS) << 4)
+
+#define PKT_BUF_SZ 1544
+
+/* Offsets from base I/O address. */
+#define PCNET32_WIO_RDP 0x10
+#define PCNET32_WIO_RAP 0x12
+#define PCNET32_WIO_RESET 0x14
+#define PCNET32_WIO_BDP 0x16
+
+#define PCNET32_DWIO_RDP 0x10
+#define PCNET32_DWIO_RAP 0x14
+#define PCNET32_DWIO_RESET 0x18
+#define PCNET32_DWIO_BDP 0x1C
+
+#define PCNET32_TOTAL_SIZE 0x20
+
+/* The PCNET32 Rx and Tx ring descriptors. */
+struct pcnet32_rx_head {
+ u32 base;
+ s16 buf_length;
+ s16 status;
+ u32 msg_length;
+ u32 reserved;
+};
+
+struct pcnet32_tx_head {
+ u32 base;
+ s16 length;
+ s16 status;
+ u32 misc;
+ u32 reserved;
+};
+
+/* The PCNET32 32-Bit initialization block, described in databook. */
+struct pcnet32_init_block {
+ u16 mode;
+ u16 tlen_rlen;
+ u8 phys_addr[6];
+ u16 reserved;
+ u32 filter[2];
+ /* Receive and transmit ring base, along with extra bits. */
+ u32 rx_ring;
+ u32 tx_ring;
+};
+/* PCnet32 access functions */
+struct pcnet32_access {
+ u16(*read_csr) (unsigned long, int);
+ void (*write_csr) (unsigned long, int, u16);
+ u16(*read_bcr) (unsigned long, int);
+ void (*write_bcr) (unsigned long, int, u16);
+ u16(*read_rap) (unsigned long);
+ void (*write_rap) (unsigned long, u16);
+ void (*reset) (unsigned long);
+};
+
+/* Define the TX and RX Descriptors and Rings */
+struct {
+ struct pcnet32_tx_head tx_ring[TX_RING_SIZE]
+ __attribute__ ((aligned(16)));
+ struct pcnet32_rx_head rx_ring[RX_RING_SIZE]
+ __attribute__ ((aligned(16)));
+ unsigned char txb[TX_RING_SIZE][PKT_BUF_SZ];
+ unsigned char rxb[RX_RING_SIZE][PKT_BUF_SZ];
+} pcnet32_bufs __shared;
+
+
+/*
+ * The first three fields of pcnet32_private are read by the ethernet device
+ * so we allocate the structure should be allocated by pci_alloc_consistent().
+ */
+#define MII_CNT 4
+struct pcnet32_private {
+ struct pcnet32_init_block init_block;
+ struct pci_dev *pci_dev; /* Pointer to the associated pci device structure */
+ const char *name;
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ struct pcnet32_access a;
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ char tx_full;
+ int options;
+ int shared_irq:1, /* shared irq possible */
+ ltint:1, /* enable TxDone-intr inhibitor */
+ dxsuflo:1, /* disable transmit stop on uflo */
+ mii:1; /* mii port available */
+ struct mii_if_info mii_if;
+ unsigned char phys[MII_CNT];
+ struct net_device *next;
+ int full_duplex:1;
+} lpx;
+
+static struct pcnet32_private *lp;
+
+static int mdio_read(struct nic *nic __unused, int phy_id, int reg_num);
+#if 0
+static void mdio_write(struct nic *nic __unused, int phy_id, int reg_num,
+ int val);
+#endif
+enum pci_flags_bit {
+ PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
+ PCI_ADDR0 = 0x10 << 0, PCI_ADDR1 = 0x10 << 1, PCI_ADDR2 =
+ 0x10 << 2, PCI_ADDR3 = 0x10 << 3,
+};
+
+
+static u16 pcnet32_wio_read_csr(unsigned long addr, int index)
+{
+ outw(index, addr + PCNET32_WIO_RAP);
+ return inw(addr + PCNET32_WIO_RDP);
+}
+
+static void pcnet32_wio_write_csr(unsigned long addr, int index, u16 val)
+{
+ outw(index, addr + PCNET32_WIO_RAP);
+ outw(val, addr + PCNET32_WIO_RDP);
+}
+
+static u16 pcnet32_wio_read_bcr(unsigned long addr, int index)
+{
+ outw(index, addr + PCNET32_WIO_RAP);
+ return inw(addr + PCNET32_WIO_BDP);
+}
+
+static void pcnet32_wio_write_bcr(unsigned long addr, int index, u16 val)
+{
+ outw(index, addr + PCNET32_WIO_RAP);
+ outw(val, addr + PCNET32_WIO_BDP);
+}
+
+static u16 pcnet32_wio_read_rap(unsigned long addr)
+{
+ return inw(addr + PCNET32_WIO_RAP);
+}
+
+static void pcnet32_wio_write_rap(unsigned long addr, u16 val)
+{
+ outw(val, addr + PCNET32_WIO_RAP);
+}
+
+static void pcnet32_wio_reset(unsigned long addr)
+{
+ inw(addr + PCNET32_WIO_RESET);
+}
+
+static int pcnet32_wio_check(unsigned long addr)
+{
+ outw(88, addr + PCNET32_WIO_RAP);
+ return (inw(addr + PCNET32_WIO_RAP) == 88);
+}
+
+static struct pcnet32_access pcnet32_wio = {
+ read_csr:pcnet32_wio_read_csr,
+ write_csr:pcnet32_wio_write_csr,
+ read_bcr:pcnet32_wio_read_bcr,
+ write_bcr:pcnet32_wio_write_bcr,
+ read_rap:pcnet32_wio_read_rap,
+ write_rap:pcnet32_wio_write_rap,
+ reset:pcnet32_wio_reset
+};
+
+static u16 pcnet32_dwio_read_csr(unsigned long addr, int index)
+{
+ outl(index, addr + PCNET32_DWIO_RAP);
+ return (inl(addr + PCNET32_DWIO_RDP) & 0xffff);
+}
+
+static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val)
+{
+ outl(index, addr + PCNET32_DWIO_RAP);
+ outl(val, addr + PCNET32_DWIO_RDP);
+}
+
+static u16 pcnet32_dwio_read_bcr(unsigned long addr, int index)
+{
+ outl(index, addr + PCNET32_DWIO_RAP);
+ return (inl(addr + PCNET32_DWIO_BDP) & 0xffff);
+}
+
+static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val)
+{
+ outl(index, addr + PCNET32_DWIO_RAP);
+ outl(val, addr + PCNET32_DWIO_BDP);
+}
+
+static u16 pcnet32_dwio_read_rap(unsigned long addr)
+{
+ return (inl(addr + PCNET32_DWIO_RAP) & 0xffff);
+}
+
+static void pcnet32_dwio_write_rap(unsigned long addr, u16 val)
+{
+ outl(val, addr + PCNET32_DWIO_RAP);
+}
+
+static void pcnet32_dwio_reset(unsigned long addr)
+{
+ inl(addr + PCNET32_DWIO_RESET);
+}
+
+static int pcnet32_dwio_check(unsigned long addr)
+{
+ outl(88, addr + PCNET32_DWIO_RAP);
+ return ((inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88);
+}
+
+static struct pcnet32_access pcnet32_dwio = {
+ read_csr:pcnet32_dwio_read_csr,
+ write_csr:pcnet32_dwio_write_csr,
+ read_bcr:pcnet32_dwio_read_bcr,
+ write_bcr:pcnet32_dwio_write_bcr,
+ read_rap:pcnet32_dwio_read_rap,
+ write_rap:pcnet32_dwio_write_rap,
+ reset:pcnet32_dwio_reset
+};
+
+
+/* Initialize the PCNET32 Rx and Tx rings. */
+static int pcnet32_init_ring(struct nic *nic)
+{
+ int i;
+
+ lp->tx_full = 0;
+ lp->cur_rx = lp->cur_tx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ pcnet32_bufs.rx_ring[i].base =
+ virt_to_le32desc(&pcnet32_bufs.rxb[i]);
+ pcnet32_bufs.rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+ pcnet32_bufs.rx_ring[i].status = le16_to_cpu(0x8000);
+ }
+
+ /* The Tx buffer address is filled in as needed, but we do need to clear
+ the upper ownership bit. */
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ pcnet32_bufs.tx_ring[i].base = 0;
+ pcnet32_bufs.tx_ring[i].status = 0;
+ }
+
+
+ lp->init_block.tlen_rlen =
+ le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+ for (i = 0; i < 6; i++)
+ lp->init_block.phys_addr[i] = nic->node_addr[i];
+ lp->init_block.rx_ring = virt_to_le32desc(&pcnet32_bufs.rx_ring[0]);
+ lp->init_block.tx_ring = virt_to_le32desc(&pcnet32_bufs.tx_ring[0]);
+ return 0;
+}
+
+/**************************************************************************
+RESET - Reset adapter
+***************************************************************************/
+static void pcnet32_reset(struct nic *nic)
+{
+ /* put the card in its initial state */
+ u16 val;
+ int i;
+
+ /* Reset the PCNET32 */
+ lp->a.reset(ioaddr);
+
+ /* switch pcnet32 to 32bit mode */
+ lp->a.write_bcr(ioaddr, 20, 2);
+
+ /* set/reset autoselect bit */
+ val = lp->a.read_bcr(ioaddr, 2) & ~2;
+ if (lp->options & PCNET32_PORT_ASEL)
+ val |= 2;
+ lp->a.write_bcr(ioaddr, 2, val);
+
+ /* handle full duplex setting */
+ if (lp->full_duplex) {
+ val = lp->a.read_bcr(ioaddr, 9) & ~3;
+ if (lp->options & PCNET32_PORT_FD) {
+ val |= 1;
+ if (lp->options ==
+ (PCNET32_PORT_FD | PCNET32_PORT_AUI))
+ val |= 2;
+ } else if (lp->options & PCNET32_PORT_ASEL) {
+ /* workaround of xSeries250, turn on for 79C975 only */
+ i = ((lp->a.
+ read_csr(ioaddr,
+ 88) | (lp->a.read_csr(ioaddr,
+ 89) << 16)) >>
+ 12) & 0xffff;
+ if (i == 0x2627)
+ val |= 3;
+ }
+ lp->a.write_bcr(ioaddr, 9, val);
+ }
+
+ /* set/reset GPSI bit in test register */
+ val = lp->a.read_csr(ioaddr, 124) & ~0x10;
+ if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
+ val |= 0x10;
+ lp->a.write_csr(ioaddr, 124, val);
+
+ if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
+ val = lp->a.read_bcr(ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */
+ if (lp->options & PCNET32_PORT_FD)
+ val |= 0x10;
+ if (lp->options & PCNET32_PORT_100)
+ val |= 0x08;
+ lp->a.write_bcr(ioaddr, 32, val);
+ } else {
+ if (lp->options & PCNET32_PORT_ASEL) { /* enable auto negotiate, setup, disable fd */
+ val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
+ val |= 0x20;
+ lp->a.write_bcr(ioaddr, 32, val);
+ }
+ }
+
+#ifdef DO_DXSUFLO
+ if (lp->dxsuflo) { /* Disable transmit stop on underflow */
+ val = lp->a.read_csr(ioaddr, 3);
+ val |= 0x40;
+ lp->a.write_csr(ioaddr, 3, val);
+ }
+#endif
+ if (1)
+ {
+ //disable interrupts
+ val = lp->a.read_csr(ioaddr, 3);
+ val = val
+ | (1 << 14) //BABLM intr disabled
+ | (1 << 12) //MISSM missed frame mask intr disabled
+ | (1 << 10) //RINTM receive intr disabled
+ | (1 << 9) //TINTM transmit intr disabled
+ | (1 << 8) //IDONM init done intr disabled
+ ;
+ lp->a.write_csr(ioaddr, 3, val);
+ }
+
+ if (lp->ltint) { /* Enable TxDone-intr inhibitor */
+ val = lp->a.read_csr(ioaddr, 5);
+ val |= (1 << 14);
+ lp->a.write_csr(ioaddr, 5, val);
+ }
+ lp->init_block.mode =
+ le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
+ lp->init_block.filter[0] = 0xffffffff;
+ lp->init_block.filter[1] = 0xffffffff;
+
+ pcnet32_init_ring(nic);
+
+
+ /* Re-initialize the PCNET32, and start it when done. */
+ lp->a.write_csr(ioaddr, 1,
+ (virt_to_bus(&lp->init_block)) & 0xffff);
+ lp->a.write_csr(ioaddr, 2, (virt_to_bus(&lp->init_block)) >> 16);
+ lp->a.write_csr(ioaddr, 4, 0x0915);
+ lp->a.write_csr(ioaddr, 0, 0x0001);
+
+
+ i = 0;
+ while (i++ < 100)
+ if (lp->a.read_csr(ioaddr, 0) & 0x0100)
+ break;
+ /*
+ * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
+ * reports that doing so triggers a bug in the '974.
+ */
+ lp->a.write_csr(ioaddr, 0, 0x0042);
+
+ dprintf(("pcnet32 open, csr0 %hX.\n", lp->a.read_csr(ioaddr, 0)));
+
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int pcnet32_poll(struct nic *nic __unused, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+
+ signed char status;
+ int entry;
+
+ entry = lp->cur_rx & RX_RING_MOD_MASK;
+ status = (le16_to_cpu(pcnet32_bufs.rx_ring[entry].status) >> 8);
+
+ if (status < 0)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ if (status == 0x03) {
+ nic->packetlen =
+ (le32_to_cpu(pcnet32_bufs.rx_ring[entry].msg_length)
+ & 0xfff) - 4;
+ memcpy(nic->packet, &pcnet32_bufs.rxb[entry], nic->packetlen);
+
+ /* Andrew Boyd of QNX reports that some revs of the 79C765
+ * clear the buffer length */
+ pcnet32_bufs.rx_ring[entry].buf_length
+ = le16_to_cpu(-PKT_BUF_SZ);
+ /* prime for next receive */
+ pcnet32_bufs.rx_ring[entry].status |= le16_to_cpu(0x8000);
+ /* Switch to the next Rx ring buffer */
+ lp->cur_rx++;
+
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void pcnet32_transmit(struct nic *nic __unused, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ /* send the packet to destination */
+ unsigned long time;
+ u8 *ptxb;
+ u16 nstype;
+ u16 status;
+ int entry = 0; /*lp->cur_tx & TX_RING_MOD_MASK; */
+
+ status = 0x8300;
+ /* point to the current txb incase multiple tx_rings are used */
+ ptxb = pcnet32_bufs.txb[lp->cur_tx];
+
+ /* copy the packet to ring buffer */
+ memcpy(ptxb, d, ETH_ALEN); /* dst */
+ memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
+ nstype = htons((u16) t); /* type */
+ memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */
+ memcpy(ptxb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ while (s < ETH_ZLEN) /* pad to min length */
+ ptxb[s++] = '\0';
+
+ pcnet32_bufs.tx_ring[entry].length = le16_to_cpu(-s);
+ pcnet32_bufs.tx_ring[entry].misc = 0x00000000;
+ pcnet32_bufs.tx_ring[entry].base = (u32) virt_to_le32desc(ptxb);
+
+ /* we set the top byte as the very last thing */
+ pcnet32_bufs.tx_ring[entry].status = le16_to_cpu(status);
+
+
+ /* Trigger an immediate send poll */
+ lp->a.write_csr(ioaddr, 0, 0x0048);
+
+ /* wait for transmit complete */
+ lp->cur_tx = 0; /* (lp->cur_tx + 1); */
+ time = currticks() + TICKS_PER_SEC; /* wait one second */
+ while (currticks() < time &&
+ ((short) le16_to_cpu(pcnet32_bufs.tx_ring[entry].status) < 0));
+
+ if ((short) le16_to_cpu(pcnet32_bufs.tx_ring[entry].status) < 0)
+ printf("PCNET32 timed out on transmit\n");
+
+ /* Stop pointing at the current txb
+ * otherwise the card continues to send the packet */
+ pcnet32_bufs.tx_ring[entry].base = 0;
+
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void pcnet32_disable ( struct nic *nic __unused ) {
+ /* Stop the PCNET32 here -- it ocassionally polls memory if we don't */
+ lp->a.write_csr(ioaddr, 0, 0x0004);
+
+ /*
+ * Switch back to 16-bit mode to avoid problems with dumb
+ * DOS packet driver after a warm reboot
+ */
+ lp->a.write_bcr(ioaddr, 20, 0);
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void pcnet32_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+You should omit the last argument struct pci_device * for a non-PCI NIC
+***************************************************************************/
+static int pcnet32_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i, media;
+ int fdx, mii, fset, dxsuflo, ltint;
+ int chip_version;
+ struct pcnet32_access *a = NULL;
+ char *chipname;
+ u8 promaddr[6];
+ int shared = 1;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ /* BASE is used throughout to address the card */
+ ioaddr = pci->ioaddr;
+ printf("pcnet32.c: Found %s, Vendor=0x%hX Device=0x%hX\n",
+ pci->driver_name, pci->vendor, pci->device);
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr & ~3;
+
+ /* reset the chip */
+ pcnet32_wio_reset(ioaddr);
+
+ /* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */
+ if (pcnet32_wio_read_csr(ioaddr, 0) == 4
+ && pcnet32_wio_check(ioaddr)) {
+ a = &pcnet32_wio;
+ } else {
+ pcnet32_dwio_reset(ioaddr);
+ if (pcnet32_dwio_read_csr(ioaddr, 0) == 4
+ && pcnet32_dwio_check(ioaddr)) {
+ a = &pcnet32_dwio;
+ } else
+ return 0;
+ }
+
+ chip_version =
+ a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr, 89) << 16);
+
+ dprintf(("PCnet chip version is 0x%X\n", chip_version));
+ if ((chip_version & 0xfff) != 0x003)
+ return 0;
+
+ /* initialize variables */
+ fdx = mii = fset = dxsuflo = ltint = 0;
+ chip_version = (chip_version >> 12) & 0xffff;
+
+ switch (chip_version) {
+ case 0x2420:
+ chipname = "PCnet/PCI 79C970"; /* PCI */
+ break;
+ case 0x2430:
+ if (shared)
+ chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */
+ else
+ chipname = "PCnet/32 79C965"; /* 486/VL bus */
+ break;
+ case 0x2621:
+ chipname = "PCnet/PCI II 79C970A"; /* PCI */
+ fdx = 1;
+ break;
+ case 0x2623:
+ chipname = "PCnet/FAST 79C971"; /* PCI */
+ fdx = 1;
+ mii = 1;
+ fset = 1;
+ ltint = 1;
+ break;
+ case 0x2624:
+ chipname = "PCnet/FAST+ 79C972"; /* PCI */
+ fdx = 1;
+ mii = 1;
+ fset = 1;
+ break;
+ case 0x2625:
+ chipname = "PCnet/FAST III 79C973"; /* PCI */
+ fdx = 1;
+ mii = 1;
+ break;
+ case 0x2626:
+ chipname = "PCnet/Home 79C978"; /* PCI */
+ fdx = 1;
+ /*
+ * This is based on specs published at www.amd.com. This section
+ * assumes that a card with a 79C978 wants to go into 1Mb HomePNA
+ * mode. The 79C978 can also go into standard ethernet, and there
+ * probably should be some sort of module option to select the
+ * mode by which the card should operate
+ */
+ /* switch to home wiring mode */
+ media = a->read_bcr(ioaddr, 49);
+
+ printf("media reset to %#x.\n", media);
+ a->write_bcr(ioaddr, 49, media);
+ break;
+ case 0x2627:
+ chipname = "PCnet/FAST III 79C975"; /* PCI */
+ fdx = 1;
+ mii = 1;
+ break;
+ default:
+ chipname = "UNKNOWN";
+ printf("PCnet version %#x, no PCnet32 chip.\n",
+ chip_version);
+ return 0;
+ }
+
+ /*
+ * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit
+ * starting until the packet is loaded. Strike one for reliability, lose
+ * one for latency - although on PCI this isnt a big loss. Older chips
+ * have FIFO's smaller than a packet, so you can't do this.
+ */
+
+ if (fset) {
+ a->write_bcr(ioaddr, 18,
+ (a->read_bcr(ioaddr, 18) | 0x0800));
+ a->write_csr(ioaddr, 80,
+ (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00);
+ dxsuflo = 1;
+ ltint = 1;
+ }
+
+ DBG ( "%s at %hX,", chipname, (unsigned int) ioaddr );
+
+ /* read PROM address */
+ for (i = 0; i < 6; i++)
+ promaddr[i] = inb(ioaddr + i);
+
+ /* Update the nic structure with the MAC Address */
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = promaddr[i];
+ }
+
+ /* Print out some hardware info */
+ DBG ( "%s: IO Addr 0x%hX, MAC Addr %s\n ", chipname, (unsigned int) ioaddr,
+ eth_ntoa ( nic->node_addr ) );
+
+ /* Set to pci bus master */
+ adjust_pci_device(pci);
+
+ /* point to private storage */
+ lp = &lpx;
+
+#if EBDEBUG
+ if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */
+ i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */
+ dprintf((" tx_start_pt(0x%hX):", i));
+ switch (i >> 10) {
+ case 0:
+ dprintf((" 20 bytes,"));
+ break;
+ case 1:
+ dprintf((" 64 bytes,"));
+ break;
+ case 2:
+ dprintf((" 128 bytes,"));
+ break;
+ case 3:
+ dprintf(("~220 bytes,"));
+ break;
+ }
+ i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */
+ dprintf((" BCR18(%hX):", i & 0xffff));
+ if (i & (1 << 5))
+ dprintf(("BurstWrEn "));
+ if (i & (1 << 6))
+ dprintf(("BurstRdEn "));
+ if (i & (1 << 7))
+ dprintf(("DWordIO "));
+ if (i & (1 << 11))
+ dprintf(("NoUFlow "));
+ i = a->read_bcr(ioaddr, 25);
+ dprintf((" SRAMSIZE=0x%hX,", i << 8));
+ i = a->read_bcr(ioaddr, 26);
+ dprintf((" SRAM_BND=0x%hX,", i << 8));
+ i = a->read_bcr(ioaddr, 27);
+ if (i & (1 << 14))
+ dprintf(("LowLatRx"));
+ }
+#endif
+ lp->name = chipname;
+ lp->shared_irq = shared;
+ lp->full_duplex = fdx;
+ lp->dxsuflo = dxsuflo;
+ lp->ltint = ltint;
+ lp->mii = mii;
+ /* FIXME: Fix Options for only one card */
+ if ((cards_found >= MAX_UNITS)
+ || ((unsigned int) options[cards_found] > sizeof(options_mapping)))
+ lp->options = PCNET32_PORT_ASEL;
+ else
+ lp->options = options_mapping[options[cards_found]];
+
+ if (fdx && !(lp->options & PCNET32_PORT_ASEL) &&
+ ((cards_found >= MAX_UNITS) || full_duplex[cards_found]))
+ lp->options |= PCNET32_PORT_FD;
+
+ if (!a) {
+ printf("No access methods\n");
+ return 0;
+ }
+
+ // lp->a = *a;
+ // Causes a loader:
+ // bin/blib.a(pcnet32.o)(.text+0x6b6): In function `pcnet32_probe':
+ // drivers/net/pcnet32.c:871: undefined reference to `memcpy'
+ // make: *** [bin/pcnet32.dsk.tmp] Error 1
+ // So we do:
+ memcpy ( &lp->a, a, sizeof ( lp->a ) );
+ // To explicity call memcpy.
+
+ /* detect special T1/E1 WAN card by checking for MAC address */
+ if (nic->node_addr[0] == 0x00 && nic->node_addr[1] == 0xe0
+ && nic->node_addr[2] == 0x75)
+ lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
+
+ lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
+ lp->init_block.tlen_rlen =
+ le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+ for (i = 0; i < 6; i++)
+ lp->init_block.phys_addr[i] = nic->node_addr[i];
+ lp->init_block.filter[0] = 0xffffffff;
+ lp->init_block.filter[1] = 0xffffffff;
+ lp->init_block.rx_ring = virt_to_bus(&pcnet32_bufs.rx_ring);
+ lp->init_block.tx_ring = virt_to_bus(&pcnet32_bufs.tx_ring);
+
+ /* switch pcnet32 to 32bit mode */
+ a->write_bcr(ioaddr, 20, 2);
+
+ a->write_csr(ioaddr, 1, (virt_to_bus(&lp->init_block)) & 0xffff);
+ a->write_csr(ioaddr, 2, (virt_to_bus(&lp->init_block)) >> 16);
+
+ /*
+ * To auto-IRQ we enable the initialization-done and DMA error
+ * interrupts. For ISA boards we get a DMA error, but VLB and PCI
+ * boards will work.
+ */
+ /* Trigger an initialization just for the interrupt. */
+
+
+// a->write_csr(ioaddr, 0, 0x41);
+// mdelay(1);
+
+ cards_found++;
+
+ /* point to NIC specific routines */
+ pcnet32_reset(nic);
+ if (mii) {
+ int tmp;
+ int phy, phy_idx = 0;
+ u16 mii_lpa;
+ lp->phys[0] = 1; /* Default Setting */
+ for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
+ int mii_status = mdio_read(nic, phy, MII_BMSR);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ lp->phys[phy_idx++] = phy;
+ lp->mii_if.advertising =
+ mdio_read(nic, phy, MII_ADVERTISE);
+ if ((mii_status & 0x0040) == 0) {
+ tmp = phy;
+ dprintf (("MII PHY found at address %d, status "
+ "%hX advertising %hX\n", phy, mii_status,
+ lp->mii_if.advertising));
+ }
+ }
+ }
+ if (phy_idx == 0)
+ printf("No MII transceiver found!\n");
+ lp->mii_if.phy_id = lp->phys[0];
+
+ lp->mii_if.advertising =
+ mdio_read(nic, lp->phys[0], MII_ADVERTISE);
+
+ mii_lpa = mdio_read(nic, lp->phys[0], MII_LPA);
+ lp->mii_if.advertising &= mii_lpa;
+ if (lp->mii_if.advertising & ADVERTISE_100FULL)
+ printf("100Mbps Full-Duplex\n");
+ else if (lp->mii_if.advertising & ADVERTISE_100HALF)
+ printf("100Mbps Half-Duplex\n");
+ else if (lp->mii_if.advertising & ADVERTISE_10FULL)
+ printf("10Mbps Full-Duplex\n");
+ else if (lp->mii_if.advertising & ADVERTISE_10HALF)
+ printf("10Mbps Half-Duplex\n");
+ else
+ printf("\n");
+ } else {
+ /* The older chips are fixed 10Mbps, and some support full duplex,
+ * although not via autonegotiation, but only via configuration. */
+ if (fdx)
+ printf("10Mbps Full-Duplex\n");
+ else
+ printf("10Mbps Half-Duplex\n");
+ }
+
+ nic->nic_op = &pcnet32_operations;
+
+ return 1;
+}
+static int mdio_read(struct nic *nic __unused, int phy_id, int reg_num)
+{
+ u16 val_out;
+ int phyaddr;
+
+ if (!lp->mii)
+ return 0;
+
+ phyaddr = lp->a.read_bcr(ioaddr, 33);
+
+ lp->a.write_bcr(ioaddr, 33,
+ ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+ val_out = lp->a.read_bcr(ioaddr, 34);
+ lp->a.write_bcr(ioaddr, 33, phyaddr);
+
+ return val_out;
+}
+
+#if 0
+static void mdio_write(struct nic *nic __unused, int phy_id, int reg_num,
+ int val)
+{
+ int phyaddr;
+
+ if (!lp->mii)
+ return;
+
+ phyaddr = lp->a.read_bcr(ioaddr, 33);
+
+ lp->a.write_bcr(ioaddr, 33,
+ ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+ lp->a.write_bcr(ioaddr, 34, val);
+ lp->a.write_bcr(ioaddr, 33, phyaddr);
+}
+#endif
+
+static struct nic_operations pcnet32_operations = {
+ .connect = dummy_connect,
+ .poll = pcnet32_poll,
+ .transmit = pcnet32_transmit,
+ .irq = pcnet32_irq,
+
+};
+
+static struct pci_device_id pcnet32_nics[] = {
+ PCI_ROM(0x1022, 0x2000, "pcnet32", "AMD PCnet/PCI", 0),
+ PCI_ROM(0x1022, 0x2625, "pcnetfastiii", "AMD PCNet FAST III", 0),
+ PCI_ROM(0x1022, 0x2001, "amdhomepna", "AMD PCnet/HomePNA", 0),
+};
+
+PCI_DRIVER ( pcnet32_driver, pcnet32_nics, PCI_NO_CLASS );
+
+DRIVER ( "PCNET32/PCI", nic_driver, pci_driver, pcnet32_driver,
+ pcnet32_probe, pcnet32_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/pnic.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/pnic.c
new file mode 100644
index 0000000..cbc6790
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/pnic.c
@@ -0,0 +1,281 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Bochs Pseudo NIC driver for Etherboot
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * See pnic_api.h for an explanation of the Bochs Pseudo NIC.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <gpxe/io.h>
+#include <errno.h>
+#include <gpxe/pci.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+
+#include "pnic_api.h"
+
+struct pnic {
+ unsigned short ioaddr;
+};
+
+/*
+ * Utility functions: issue a PNIC command, retrieve result. Use
+ * pnic_command_quiet if you don't want failure codes to be
+ * automatically printed. Returns the PNIC status code.
+ *
+ * Set output_length to NULL only if you expect to receive exactly
+ * output_max_length bytes, otherwise it'll complain that you didn't
+ * get enough data (on the assumption that if you not interested in
+ * discovering the output length then you're expecting a fixed amount
+ * of data).
+ */
+
+static uint16_t pnic_command_quiet ( struct pnic *pnic, uint16_t command,
+ const void *input, uint16_t input_length,
+ void *output, uint16_t output_max_length,
+ uint16_t *output_length ) {
+ uint16_t status;
+ uint16_t _output_length;
+
+ if ( input != NULL ) {
+ /* Write input length */
+ outw ( input_length, pnic->ioaddr + PNIC_REG_LEN );
+ /* Write input data */
+ outsb ( pnic->ioaddr + PNIC_REG_DATA, input, input_length );
+ }
+ /* Write command */
+ outw ( command, pnic->ioaddr + PNIC_REG_CMD );
+ /* Retrieve status */
+ status = inw ( pnic->ioaddr + PNIC_REG_STAT );
+ /* Retrieve output length */
+ _output_length = inw ( pnic->ioaddr + PNIC_REG_LEN );
+ if ( output_length == NULL ) {
+ if ( _output_length != output_max_length ) {
+ printf ( "pnic_command %#hx: wrong data length "
+ "returned (expected %d, got %d)\n", command,
+ output_max_length, _output_length );
+ }
+ } else {
+ *output_length = _output_length;
+ }
+ if ( output != NULL ) {
+ if ( _output_length > output_max_length ) {
+ printf ( "pnic_command %#hx: output buffer too small "
+ "(have %d, need %d)\n", command,
+ output_max_length, _output_length );
+ _output_length = output_max_length;
+ }
+ /* Retrieve output data */
+ insb ( pnic->ioaddr + PNIC_REG_DATA, output, _output_length );
+ }
+ return status;
+}
+
+static uint16_t pnic_command ( struct pnic *pnic, uint16_t command,
+ const void *input, uint16_t input_length,
+ void *output, uint16_t output_max_length,
+ uint16_t *output_length ) {
+ uint16_t status = pnic_command_quiet ( pnic, command,
+ input, input_length,
+ output, output_max_length,
+ output_length );
+ if ( status == PNIC_STATUS_OK ) return status;
+ printf ( "PNIC command %#hx (len %#hx) failed with status %#hx\n",
+ command, input_length, status );
+ return status;
+}
+
+/* Check API version matches that of NIC */
+static int pnic_api_check ( uint16_t api_version ) {
+ if ( api_version != PNIC_API_VERSION ) {
+ printf ( "Warning: API version mismatch! "
+ "(NIC's is %d.%d, ours is %d.%d)\n",
+ api_version >> 8, api_version & 0xff,
+ PNIC_API_VERSION >> 8, PNIC_API_VERSION & 0xff );
+ }
+ if ( api_version < PNIC_API_VERSION ) {
+ printf ( "** You may need to update your copy of Bochs **\n" );
+ }
+ return ( api_version == PNIC_API_VERSION );
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static void pnic_poll ( struct net_device *netdev ) {
+ struct pnic *pnic = netdev->priv;
+ struct io_buffer *iobuf;
+ uint16_t length;
+ uint16_t qlen;
+
+ /* Fetch all available packets */
+ while ( 1 ) {
+ if ( pnic_command ( pnic, PNIC_CMD_RECV_QLEN, NULL, 0,
+ &qlen, sizeof ( qlen ), NULL )
+ != PNIC_STATUS_OK )
+ return;
+ if ( qlen == 0 )
+ return;
+ iobuf = alloc_iob ( ETH_FRAME_LEN );
+ if ( ! iobuf ) {
+ DBG ( "could not allocate buffer\n" );
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ return;
+ }
+ if ( pnic_command ( pnic, PNIC_CMD_RECV, NULL, 0,
+ iobuf->data, ETH_FRAME_LEN, &length )
+ != PNIC_STATUS_OK ) {
+ netdev_rx_err ( netdev, iobuf, -EIO );
+ return;
+ }
+ iob_put ( iobuf, length );
+ netdev_rx ( netdev, iobuf );
+ }
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static int pnic_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ struct pnic *pnic = netdev->priv;
+
+ /* Pad the packet */
+ iob_pad ( iobuf, ETH_ZLEN );
+
+ /* Send packet */
+ pnic_command ( pnic, PNIC_CMD_XMIT, iobuf->data, iob_len ( iobuf ),
+ NULL, 0, NULL );
+
+ netdev_tx_complete ( netdev, iobuf );
+ return 0;
+}
+
+/**************************************************************************
+OPEN - Open network device
+***************************************************************************/
+static int pnic_open ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+ return 0;
+}
+
+/**************************************************************************
+CLOSE - Close network device
+***************************************************************************/
+static void pnic_close ( struct net_device *netdev __unused ) {
+ /* Nothing to do */
+}
+
+/**************************************************************************
+IRQ - Enable/disable interrupts
+***************************************************************************/
+static void pnic_irq ( struct net_device *netdev, int enable ) {
+ struct pnic *pnic = netdev->priv;
+ uint8_t mask = ( enable ? 1 : 0 );
+
+ pnic_command ( pnic, PNIC_CMD_MASK_IRQ, &mask, sizeof ( mask ),
+ NULL, 0, NULL );
+}
+
+/**************************************************************************
+OPERATIONS TABLE
+***************************************************************************/
+static struct net_device_operations pnic_operations = {
+ .open = pnic_open,
+ .close = pnic_close,
+ .transmit = pnic_transmit,
+ .poll = pnic_poll,
+ .irq = pnic_irq,
+};
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void pnic_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct pnic *pnic = netdev->priv;
+
+ unregister_netdev ( netdev );
+ pnic_command ( pnic, PNIC_CMD_RESET, NULL, 0, NULL, 0, NULL );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int pnic_probe ( struct pci_device *pci,
+ const struct pci_device_id *id __unused ) {
+ struct net_device *netdev;
+ struct pnic *pnic;
+ uint16_t api_version;
+ uint16_t status;
+ int rc;
+
+ /* Allocate net device */
+ netdev = alloc_etherdev ( sizeof ( *pnic ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &pnic_operations );
+ pnic = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ pnic->ioaddr = pci->ioaddr;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* API version check */
+ status = pnic_command_quiet ( pnic, PNIC_CMD_API_VER, NULL, 0,
+ &api_version,
+ sizeof ( api_version ), NULL );
+ if ( status != PNIC_STATUS_OK ) {
+ printf ( "PNIC failed installation check, code %#hx\n",
+ status );
+ rc = -EIO;
+ goto err;
+ }
+ pnic_api_check ( api_version );
+
+ /* Get MAC address */
+ status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
+ netdev->hw_addr, ETH_ALEN, NULL );
+
+ /* Mark as link up; PNIC has no concept of link state */
+ netdev_link_up ( netdev );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ /* Free net device */
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+static struct pci_device_id pnic_nics[] = {
+/* genrules.pl doesn't let us use macros for PCI IDs...*/
+PCI_ROM ( 0xfefe, 0xefef, "pnic", "Bochs Pseudo NIC Adaptor", 0 ),
+};
+
+struct pci_driver pnic_driver __pci_driver = {
+ .ids = pnic_nics,
+ .id_count = ( sizeof ( pnic_nics ) / sizeof ( pnic_nics[0] ) ),
+ .probe = pnic_probe,
+ .remove = pnic_remove,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/pnic_api.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/pnic_api.h
new file mode 100644
index 0000000..27e0236
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/pnic_api.h
@@ -0,0 +1,61 @@
+/*
+ * Constants etc. for the Bochs/Etherboot pseudo-NIC
+ *
+ * This header file must be valid C and C++.
+ *
+ * Operation of the pseudo-NIC (PNIC) is pretty simple. To write a
+ * command plus data, first write the length of the data to
+ * PNIC_REG_LEN, then write the data a byte at a type to
+ * PNIC_REG_DATA, then write the command code to PNIC_REG_CMD. The
+ * status will be available from PNIC_REG_STAT. The length of any
+ * data returned will be in PNIC_REG_LEN and can be read a byte at a
+ * time from PNIC_REG_DATA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * PCI parameters
+ */
+#define PNIC_PCI_VENDOR 0xfefe /* Hopefully these won't clash with */
+#define PNIC_PCI_DEVICE 0xefef /* any real PCI device IDs. */
+
+/*
+ * 'Hardware' register addresses, offset from io_base
+ */
+#define PNIC_REG_CMD 0x00 /* Command register, 2 bytes, write only */
+#define PNIC_REG_STAT 0x00 /* Status register, 2 bytes, read only */
+#define PNIC_REG_LEN 0x02 /* Length register, 2 bytes, read-write */
+#define PNIC_REG_DATA 0x04 /* Data port, 1 byte, read-write */
+/*
+ * PNIC_MAX_REG used in Bochs to claim i/o space
+ */
+#define PNIC_MAX_REG 0x04
+
+/*
+ * Command code definitions: write these into PNIC_REG_CMD
+ */
+#define PNIC_CMD_NOOP 0x0000
+#define PNIC_CMD_API_VER 0x0001
+#define PNIC_CMD_READ_MAC 0x0002
+#define PNIC_CMD_RESET 0x0003
+#define PNIC_CMD_XMIT 0x0004
+#define PNIC_CMD_RECV 0x0005
+#define PNIC_CMD_RECV_QLEN 0x0006
+#define PNIC_CMD_MASK_IRQ 0x0007
+#define PNIC_CMD_FORCE_IRQ 0x0008
+
+/*
+ * Status code definitions: read these from PNIC_REG_STAT
+ *
+ * We avoid using status codes that might be confused with
+ * randomly-read data (e.g. 0x0000, 0xffff etc.)
+ */
+#define PNIC_STATUS_OK 0x4f4b /* 'OK' */
+#define PNIC_STATUS_UNKNOWN_CMD 0x3f3f /* '??' */
+
+/*
+ * Other miscellaneous information
+ */
+
+#define PNIC_API_VERSION 0x0101 /* 1.1 */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2.c
new file mode 100644
index 0000000..4c66592
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2.c
@@ -0,0 +1,857 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Prism2 NIC driver for Etherboot
+
+Written by Michael Brown of Fen Systems Ltd
+$Id$
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <etherboot.h>
+#include <nic.h>
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+
+/*
+ * Hard-coded SSID
+ * Leave blank in order to connect to any available SSID
+ */
+
+static const char hardcoded_ssid[] = "";
+
+/*
+ * Maximum number of info packets to wait for on a join attempt.
+ * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet
+ * before sending the "you are connected" packet, if the card has previously been
+ * attached to the AP.
+ *
+ * 2 is probably a sensible value, but YMMV.
+ */
+
+#define MAX_JOIN_INFO_COUNT 2
+
+/*
+ * Type of Prism2 interface to support
+ * If not already defined, select PLX
+ */
+#ifndef WLAN_HOSTIF
+#define WLAN_HOSTIF WLAN_PLX
+#endif
+
+/*
+ * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver
+ * We need to hack some defines in order to avoid compiling kernel-specific routines
+ */
+
+#define __LINUX_WLAN__
+#undef __KERNEL__
+#define __I386__
+#include "wlan_compat.h"
+#include "p80211hdr.h"
+#include "hfa384x.h"
+#define BAP_TIMEOUT ( 5000 )
+
+/*
+ * A few hacks to make the coding environment more Linux-like. This makes it somewhat
+ * quicker to convert code from the Linux Prism2 driver.
+ */
+#include <errno.h>
+#define __le16_to_cpu(x) (x)
+#define __le32_to_cpu(x) (x)
+#define __cpu_to_le16(x) (x)
+#define __cpu_to_le32(x) (x)
+
+#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n)))
+#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n)))
+#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n)))
+#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n)))
+
+/*
+ * PLX9052 PCI register offsets
+ * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
+ */
+
+#define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
+#define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
+#define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
+#define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
+#define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
+
+#define PRISM2_PLX_ATTR_MEM_BASE ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
+#define PRISM2_PLX_IO_BASE ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
+
+#define PRISM2_PCI_MEM_BASE ( PCI_BASE_ADDRESS_0 )
+
+/*
+ * PCMCIA CIS types
+ * Taken from cistpl.h in pcmcia-cs
+ */
+
+#define CISTPL_VERS_1 ( 0x15 )
+#define CISTPL_END ( 0xff )
+
+#define CIS_STEP ( 2 )
+#define CISTPL_HEADER_LEN ( 2 * CIS_STEP )
+#define CISTPL_LEN_OFF ( 1 * CIS_STEP )
+#define CISTPL_VERS_1_STR_OFF ( 4 * CIS_STEP )
+
+/*
+ * Prism2 constants
+ * Taken from prism2sta.c in linux-wlan-ng
+ */
+
+#define COR_OFFSET ( 0x3e0 ) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE ( 0x41 ) /* Enable PC card with irq in level trigger (but interrupts disabled) */
+
+/* NIC specific static variables */
+
+/* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
+ * This is a dummy version that contains only the fields we are interested in.
+ */
+
+typedef struct hfa384x
+{
+ UINT32 iobase;
+ void *membase;
+ UINT16 lastcmd;
+ UINT16 status; /* in host order */
+ UINT16 resp0; /* in host order */
+ UINT16 resp1; /* in host order */
+ UINT16 resp2; /* in host order */
+ UINT8 bssid[WLAN_BSSID_LEN];
+} hfa384x_t;
+
+/* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
+static hfa384x_t hw_global = {
+ 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
+};
+
+/*
+ * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
+ * Taken from p80211conv.h
+ */
+
+typedef struct wlan_llc
+{
+ UINT8 dsap;
+ UINT8 ssap;
+ UINT8 ctl;
+} wlan_llc_t;
+
+static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
+
+#define WLAN_IEEE_OUI_LEN 3
+typedef struct wlan_snap
+{
+ UINT8 oui[WLAN_IEEE_OUI_LEN];
+ UINT16 type;
+} wlan_snap_t;
+
+typedef struct wlan_80211hdr
+{
+ wlan_llc_t llc;
+ wlan_snap_t snap;
+} wlan_80211hdr_t;
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * Hardware-level hfa384x functions
+ * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
+ * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions.
+ */
+
+/* Retrieve the value of one of the MAC registers. */
+static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg )
+{
+#if (WLAN_HOSTIF == WLAN_PLX)
+ return inw ( hw->iobase + reg );
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ return readw ( hw->membase + reg );
+#endif
+}
+
+/* Set the value of one of the MAC registers. */
+static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg )
+{
+#if (WLAN_HOSTIF == WLAN_PLX)
+ outw ( val, hw->iobase + reg );
+#elif (WLAN_HOSTIF == WLAN_PCI)
+ writew ( val, hw->membase + reg );
+#endif
+ return;
+}
+
+/*
+ * Noswap versions
+ * Etherboot is i386 only, so swap and noswap are the same...
+ */
+static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg )
+{
+ return hfa384x_getreg ( hw, reg );
+}
+static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg )
+{
+ hfa384x_setreg ( hw, val, reg );
+}
+
+/*
+ * Low-level hfa384x functions
+ * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
+ */
+
+/*
+ * hfa384x_docmd_wait
+ *
+ * Waits for availability of the Command register, then
+ * issues the given command. Then polls the Evstat register
+ * waiting for command completion.
+ * Arguments:
+ * hw device structure
+ * cmd Command in host order
+ * parm0 Parameter0 in host order
+ * parm1 Parameter1 in host order
+ * parm2 Parameter2 in host order
+ * Returns:
+ * 0 success
+ * >0 command indicated error, Status and Resp0-2 are
+ * in hw structure.
+ */
+static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2)
+{
+ UINT16 reg = 0;
+ UINT16 counter = 0;
+
+ /* wait for the busy bit to clear */
+ counter = 0;
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
+ reg = hfa384x_getreg(hw, HFA384x_CMD);
+ counter++;
+ udelay(10);
+ }
+ if (HFA384x_CMD_ISBUSY(reg)) {
+ printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
+ return -ETIMEDOUT;
+ }
+
+ /* busy bit clear, write command */
+ hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
+ hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
+ hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
+ hw->lastcmd = cmd;
+ hfa384x_setreg(hw, cmd, HFA384x_CMD);
+
+ /* Now wait for completion */
+ counter = 0;
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ /* Initialization is the problem. It takes about
+ 100ms. "normal" commands are typically is about
+ 200-400 us (I've never seen less than 200). Longer
+ is better so that we're not hammering the bus. */
+ while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ counter++;
+ udelay(200);
+ }
+ if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
+ printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
+ return -ETIMEDOUT;
+ }
+
+ /* Read status and response */
+ hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
+ hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
+ hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
+ hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
+ hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
+ return HFA384x_STATUS_RESULT_GET(hw->status);
+}
+
+/*
+ * Prepare BAP for access. Assigns FID and RID, sets offset register
+ * and waits for BAP to become available.
+ *
+ * Arguments:
+ * hw device structure
+ * id FID or RID, destined for the select register (host order)
+ * offset An _even_ offset into the buffer for the given FID/RID.
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset)
+{
+ int result = 0;
+ UINT16 reg;
+ UINT16 i;
+
+ /* Validate offset, buf, and len */
+ if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
+ result = -EINVAL;
+ } else {
+ /* Write fid/rid and offset */
+ hfa384x_setreg(hw, id, HFA384x_SELECT0);
+ udelay(10);
+ hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
+ /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
+ i = 0;
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
+ if ( i > 0 ) udelay(2);
+ i++;
+ } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
+ if ( i >= BAP_TIMEOUT ) {
+ /* failure */
+ result = reg;
+ } else if ( HFA384x_OFFSET_ISERR(reg) ){
+ /* failure */
+ result = reg;
+ }
+ }
+ return result;
+}
+
+/*
+ * Copy data from BAP to memory.
+ *
+ * Arguments:
+ * hw device structure
+ * id FID or RID, destined for the select register (host order)
+ * offset An _even_ offset into the buffer for the given FID/RID.
+ * buf ptr to array of bytes
+ * len length of data to transfer in bytes
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
+ void *buf, UINT len)
+{
+ int result = 0;
+ UINT8 *d = (UINT8*)buf;
+ UINT16 i;
+ UINT16 reg = 0;
+
+ /* Prepare BAP */
+ result = hfa384x_prepare_bap ( hw, id, offset );
+ if ( result == 0 ) {
+ /* Read even(len) buf contents from data reg */
+ for ( i = 0; i < (len & 0xfffe); i+=2 ) {
+ *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
+ }
+ /* If len odd, handle last byte */
+ if ( len % 2 ){
+ reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
+ d[len-1] = ((UINT8*)(&reg))[0];
+ }
+ }
+ if (result) {
+ printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
+ }
+ return result;
+}
+
+/*
+ * Copy data from memory to BAP.
+ *
+ * Arguments:
+ * hw device structure
+ * id FID or RID, destined for the select register (host order)
+ * offset An _even_ offset into the buffer for the given FID/RID.
+ * buf ptr to array of bytes
+ * len length of data to transfer in bytes
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
+ void *buf, UINT len)
+{
+ int result = 0;
+ UINT8 *d = (UINT8*)buf;
+ UINT16 i;
+ UINT16 savereg;
+
+ /* Prepare BAP */
+ result = hfa384x_prepare_bap ( hw, id, offset );
+ if ( result == 0 ) {
+ /* Write even(len) buf contents to data reg */
+ for ( i = 0; i < (len & 0xfffe); i+=2 ) {
+ hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0);
+ }
+ /* If len odd, handle last byte */
+ if ( len % 2 ){
+ savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
+ result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
+ if ( result == 0 ) {
+ ((UINT8*)(&savereg))[0] = d[len-1];
+ hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
+ }
+ }
+ }
+ if (result) {
+ printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
+ }
+ return result;
+}
+
+/*
+ * Request a given record to be copied to/from the record buffer.
+ *
+ * Arguments:
+ * hw device structure
+ * write [0|1] copy the record buffer to the given
+ * configuration record. (host order)
+ * rid RID of the record to read/write. (host order)
+ *
+ * Returns:
+ * 0 success
+ */
+static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid)
+{
+ return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
+}
+
+/*
+ * Performs the sequence necessary to read a config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (host order)
+ * buf host side record buffer. Upon return it will
+ * contain the body portion of the record (minus the
+ * RID and len).
+ * len buffer length (in bytes, should match record length)
+ *
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result = 0;
+ hfa384x_rec_t rec;
+
+ /* Request read of RID */
+ result = hfa384x_cmd_access( hw, 0, rid);
+ if ( result ) {
+ printf("Call to hfa384x_cmd_access failed\n");
+ return -1;
+ }
+ /* Copy out record length */
+ result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
+ if ( result ) {
+ return -1;
+ }
+ /* Validate the record length */
+ if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */
+ printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
+ return -1;
+ }
+ /* Copy out record data */
+ result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
+ return result;
+}
+
+/*
+ * Performs the sequence necessary to read a 16/32 bit config/info item
+ * and convert it to host order.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * val ptr to 16/32 bit buffer to receive value (in host order)
+ *
+ * Returns:
+ * 0 success
+ */
+#if 0 /* Not actually used anywhere */
+static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
+ if ( result == 0 ) {
+ *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
+ }
+ return result;
+}
+#endif
+#if 0 /* Not actually used anywhere */
+static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
+{
+ int result = 0;
+ result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
+ if ( result == 0 ) {
+ *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
+ }
+ return result;
+}
+#endif
+
+/*
+ * Performs the sequence necessary to write a config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * buf host side record buffer
+ * len buffer length (in bytes)
+ *
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
+{
+ int result = 0;
+ hfa384x_rec_t rec;
+
+ rec.rid = host2hfa384x_16(rid);
+ rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
+ /* write the record header */
+ result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
+ if ( result ) {
+ printf("Failure writing record header\n");
+ return -1;
+ }
+ /* write the record data (if there is any) */
+ if ( len > 0 ) {
+ result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
+ if ( result ) {
+ printf("Failure writing record data\n");
+ return -1;
+ }
+ }
+ /* Trigger setting of record */
+ result = hfa384x_cmd_access( hw, 1, rid);
+ return result;
+}
+
+/*
+ * Performs the sequence necessary to write a 16/32 bit config/info item.
+ *
+ * Arguments:
+ * hw device structure
+ * rid config/info record id (in host order)
+ * val 16/32 bit value to store (in host order)
+ *
+ * Returns:
+ * 0 success
+ */
+static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
+{
+ UINT16 value;
+ value = host2hfa384x_16(*val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
+}
+#if 0 /* Not actually used anywhere */
+static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val)
+{
+ UINT32 value;
+ value = host2hfa384x_32(*val);
+ return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));
+}
+#endif
+
+/*
+ * Wait for an event, with specified checking interval and timeout.
+ * Automatically acknolwedges events.
+ *
+ * Arguments:
+ * hw device structure
+ * event_mask EVSTAT register mask of events to wait for
+ * event_ack EVACK register set of events to be acknowledged if they happen (can be
+ * used to acknowledge "ignorable" events in addition to the "main" event)
+ * wait Time (in us) to wait between each poll of the register
+ * timeout Maximum number of polls before timing out
+ * descr Descriptive text string of what is being waited for
+ * (will be printed out if a timeout happens)
+ *
+ * Returns:
+ * value of EVSTAT register, or 0 on failure
+ */
+static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr)
+{
+ UINT16 reg;
+ int count = 0;
+
+ do {
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ if ( count > 0 ) udelay(wait);
+ count++;
+ } while ( !(reg & event_mask) && count < timeout);
+ if ( count >= timeout ) {
+ printf("hfa384x: Timed out waiting for %s\n", descr);
+ return 0; /* Return failure */
+ }
+ /* Acknowledge all events that we were waiting on */
+ hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
+ return reg;
+}
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int prism2_poll(struct nic *nic, int retrieve)
+{
+ UINT16 reg;
+ UINT16 rxfid;
+ UINT16 result;
+ hfa384x_rx_frame_t rxdesc;
+ hfa384x_t *hw = &hw_global;
+
+ /* Check for received packet */
+ reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
+ if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
+ /* No packet received - return 0 */
+ return 0;
+ }
+
+ if ( ! retrieve ) return 1;
+
+ /* Acknowledge RX event */
+ hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
+ /* Get RX FID */
+ rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
+ /* Get the descriptor (including headers) */
+ result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
+ if ( result ) {
+ return 0; /* fail */
+ }
+ /* Byte order convert once up front. */
+ rxdesc.status = hfa384x2host_16(rxdesc.status);
+ rxdesc.time = hfa384x2host_32(rxdesc.time);
+ rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
+
+ /* Fill in nic->packetlen */
+ nic->packetlen = rxdesc.data_len;
+ if ( nic->packetlen > 0 ) {
+ /* Fill in nic->packet */
+ /*
+ * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
+ * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
+ * header), so we use a quick hack to achieve this.
+ */
+ result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
+ nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
+ if ( result ) {
+ return 0; /* fail */
+ }
+ }
+ return 1; /* Packet successfully received */
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void prism2_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ hfa384x_t *hw = &hw_global;
+ hfa384x_tx_frame_t txdesc;
+ wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
+ UINT16 fid;
+ UINT16 status;
+ int result;
+
+ // Request FID allocation
+ result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
+ if (result != 0) {
+ printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
+ return;
+ }
+ if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
+ fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
+
+ /* Build Tx frame structure */
+ memset(&txdesc, 0, sizeof(txdesc));
+ txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
+ HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
+ txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
+ WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
+ WLAN_SET_FC_TODS(1) );
+ memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
+ memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
+ memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
+ txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
+ /* Set up SNAP header */
+ /* Let OUI default to RFC1042 (0x000000) */
+ p80211hdr.snap.type = htons(t);
+
+ /* Copy txdesc, p80211hdr and payload parts to FID */
+ result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
+ if ( result ) return; /* fail */
+ result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
+ if ( result ) return; /* fail */
+ result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s );
+ if ( result ) return; /* fail */
+
+ /* Issue Tx command */
+ result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
+ if ( result != 0 ) {
+ printf("hfa384x: Transmit failed with result %#hx.\n", result);
+ return;
+ }
+
+ /* Wait for transmit completion (or exception) */
+ result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
+ 200, 500, "Tx to complete\n" );
+ if ( !result ) return; /* timeout failure */
+ if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
+ fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
+ printf ( "Tx exception occurred with fid %#hx\n", fid );
+ result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
+ if ( result ) return; /* fail */
+ printf("hfa384x: Tx error occurred (status %#hx):\n", status);
+ if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
+ if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
+ if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
+ if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
+ if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
+ return; /* fail */
+ }
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void prism2_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+/**************************************************************************
+Operations table
+***************************************************************************/
+static struct nic_operations prism2_operations = {
+ .connect = dummy_connect,
+ .poll = prism2_poll,
+ .transmit = prism2_transmit,
+ .irq = prism2_irq,
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+You should omit the last argument struct pci_device * for a non-PCI NIC
+***************************************************************************/
+static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) {
+ int result;
+ UINT16 tmp16 = 0;
+ UINT16 infofid;
+ hfa384x_InfFrame_t inf;
+ char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
+ int info_count = 0;
+
+ nic->irqno = 0;
+
+ /* Initialize card */
+ result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
+ if ( result ) printf ( "Initialize command returned %#hx\n", result );
+ hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
+ hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
+
+ DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) );
+
+ /* Retrieve MAC address (and fill out nic->node_addr) */
+ hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
+
+ /* Prepare card for autojoin */
+ /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
+ tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
+ if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
+ tmp16 = 0x000f; /* Set transmit rate(?) */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
+ if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
+ tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
+ if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
+ /* Set SSID */
+ memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
+ for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; }
+ ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */
+ result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
+ if ( result ) printf ( "Set SSID command returned %#hx\n", result );
+ tmp16 = 1; /* Set port type to ESS port */
+ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
+ if ( result ) printf ( "Set port type command returned %#hx\n", result );
+ /* Enable card */
+ result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
+ if ( result ) printf ( "Enable command returned %#hx\n", result );
+
+ do {
+ /* Increment info_count, abort if too many attempts.
+ * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
+ */
+ info_count++;
+ if ( info_count > MAX_JOIN_INFO_COUNT ) {
+ printf ( "Too many failed attempts - aborting\n" );
+ return 0;
+ }
+
+ /* Wait for info frame to indicate link status */
+ if ( sizeof(hardcoded_ssid) == 1 ) {
+ /* Empty SSID => join to any SSID */
+ printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count );
+ } else {
+ printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
+ }
+
+ if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
+ printf("done\n");
+ infofid = hfa384x_getreg(hw, HFA384x_INFOFID);
+ /* Retrieve the length */
+ result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(UINT16));
+ if ( result ) return 0; /* fail */
+ inf.framelen = hfa384x2host_16(inf.framelen);
+ /* Retrieve the rest */
+ result = hfa384x_copy_from_bap( hw, infofid, sizeof(UINT16),
+ &(inf.infotype), inf.framelen * sizeof(UINT16));
+ if ( result ) return 0; /* fail */
+ if ( inf.infotype != HFA384x_IT_LINKSTATUS ) {
+ /* Not a Link Status info frame: die */
+ printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype );
+ return 0;
+ }
+ inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
+ if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
+ /* Link not connected - retry */
+ printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
+ }
+ } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
+
+ /* Retrieve BSSID and print Connected message */
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
+
+ DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) );
+ DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) );
+
+ /* point to NIC specific routines */
+ nic->nic_op = &prism2_operations;
+ return 1;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_pci.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_pci.c
new file mode 100644
index 0000000..b7c1e6b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_pci.c
@@ -0,0 +1,58 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Prism2 NIC driver for Etherboot
+Wrapper for prism2_pci
+
+Written by Michael Brown of Fen Systems Ltd
+$Id$
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/pci.h>
+#include <nic.h>
+
+#define WLAN_HOSTIF WLAN_PCI
+#include "prism2.c"
+
+static int prism2_pci_probe ( struct nic *nic, struct pci_device *pci ) {
+ hfa384x_t *hw = &hw_global;
+
+ printf ( "Prism2.5 has registers at %#lx\n", pci->membase );
+ hw->membase = ioremap ( pci->membase, 0x100 );
+
+ nic->ioaddr = pci->membase;
+ nic->irqno = 0;
+
+ return prism2_probe ( nic, hw );
+}
+
+static void prism2_pci_disable ( struct nic *nic ) {
+ prism2_disable ( nic );
+}
+
+static struct pci_device_id prism2_pci_nics[] = {
+PCI_ROM(0x1260, 0x3873, "prism2_pci", "Harris Semiconductor Prism2.5 clone", 0),
+PCI_ROM(0x1260, 0x3873, "hwp01170", "ActionTec HWP01170", 0),
+PCI_ROM(0x1260, 0x3873, "dwl520", "DLink DWL-520", 0),
+};
+
+PCI_DRIVER ( prism2_pci_driver, prism2_pci_nics, PCI_NO_CLASS );
+
+DRIVER ( "Prism2/PCI", nic_driver, pci_driver, prism2_pci_driver,
+ prism2_pci_probe, prism2_pci_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_plx.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_plx.c
new file mode 100644
index 0000000..9fb5be2
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/prism2_plx.c
@@ -0,0 +1,122 @@
+/**************************************************************************
+Etherboot - BOOTP/TFTP Bootstrap Program
+Prism2 NIC driver for Etherboot
+Wrapper for prism2_plx
+
+Written by Michael Brown of Fen Systems Ltd
+$Id$
+***************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/pci.h>
+#include <nic.h>
+
+#define WLAN_HOSTIF WLAN_PLX
+#include "prism2.c"
+
+/*
+ * Find PLX card. Prints out information strings from PCMCIA CIS as visual
+ * confirmation of presence of card.
+ *
+ * Arguments:
+ * hw device structure to be filled in
+ * p PCI device structure
+ *
+ * Returns:
+ * 1 Success
+ */
+static int prism2_find_plx ( hfa384x_t *hw, struct pci_device *p )
+{
+ int found = 0;
+ uint32_t plx_lcr = 0; /* PLX9052 Local Configuration Register Base (I/O) */
+ uint32_t attr_mem = 0; /* Prism2 Attribute Memory Base */
+ uint32_t iobase = 0; /* Prism2 I/O Base */
+ unsigned char *cis_tpl = NULL;
+ unsigned char *cis_string;
+
+ /* Obtain all memory and IO base addresses */
+ pci_read_config_dword( p, PLX_LOCAL_CONFIG_REGISTER_BASE, &plx_lcr);
+ plx_lcr &= PCI_BASE_ADDRESS_IO_MASK;
+ pci_read_config_dword( p, PRISM2_PLX_ATTR_MEM_BASE, &attr_mem);
+ pci_read_config_dword( p, PRISM2_PLX_IO_BASE, &iobase);
+ iobase &= PCI_BASE_ADDRESS_IO_MASK;
+
+ /* Fill out hw structure */
+ hw->iobase = iobase;
+ printf ( "PLX9052 has local config registers at %#x\n", plx_lcr );
+ printf ( "Prism2 has attribute memory at %#x and I/O base at %#x\n", attr_mem, iobase );
+
+ /* Search for CIS strings */
+ printf ( "Searching for PCMCIA card...\n" );
+ cis_tpl = bus_to_virt(attr_mem);
+ while ( *cis_tpl != CISTPL_END ) {
+ if ( *cis_tpl == CISTPL_VERS_1 ) {
+ /* CISTPL_VERS_1 contains some nice text strings */
+ printf ( "...found " );
+ found = 1;
+ cis_string = cis_tpl + CISTPL_VERS_1_STR_OFF;
+ while ( ! ( ( *cis_string == 0 ) && ( *(cis_string+CIS_STEP) == 0 ) ) ) {
+ printf ( "%c", *cis_string == 0 ? ' ' : *cis_string );
+ cis_string += CIS_STEP;
+ }
+ printf ( "\n" );
+ }
+ /* printf ( "CIS tuple type %#hhx, length %#hhx\n", *cis_tpl, *(cis_tpl+CISTPL_LEN_OFF) ); */
+ cis_tpl += CISTPL_HEADER_LEN + CIS_STEP * ( *(cis_tpl+CISTPL_LEN_OFF) );
+ }
+ if ( found == 0 ) {
+ printf ( "...nothing found\n" );
+ }
+ ((unsigned char *)bus_to_virt(attr_mem))[COR_OFFSET] = COR_VALUE; /* Write COR to enable PC card */
+ return found;
+}
+
+static int prism2_plx_probe ( struct nic *nic, struct pci_device *pci ) {
+ hfa384x_t *hw = &hw_global;
+
+ /* Find and intialise PLX Prism2 card */
+ if ( ! prism2_find_plx ( hw, pci ) ) return 0;
+ nic->ioaddr = hw->iobase;
+ nic->irqno = 0;
+ return prism2_probe ( nic, hw );
+}
+
+static void prism2_plx_disable ( struct nic *nic ) {
+ prism2_disable ( nic );
+}
+
+static struct pci_device_id prism2_plx_nics[] = {
+PCI_ROM(0x1385, 0x4100, "ma301", "Netgear MA301", 0),
+PCI_ROM(0x10b7, 0x7770, "3c-airconnect", "3Com AirConnect", 0),
+PCI_ROM(0x111a, 0x1023, "ss1023", "Siemens SpeedStream SS1023", 0),
+PCI_ROM(0x15e8, 0x0130, "correga", "Correga", 0),
+PCI_ROM(0x1638, 0x1100, "smc2602w", "SMC EZConnect SMC2602W", 0), /* or Eumitcom PCI WL11000, Addtron AWA-100 */
+PCI_ROM(0x16ab, 0x1100, "gl24110p", "Global Sun Tech GL24110P", 0),
+PCI_ROM(0x16ab, 0x1101, "16ab-1101", "Unknown", 0),
+PCI_ROM(0x16ab, 0x1102, "wdt11", "Linksys WDT11", 0),
+PCI_ROM(0x16ec, 0x3685, "usr2415", "USR 2415", 0),
+PCI_ROM(0xec80, 0xec00, "f5d6000", "Belkin F5D6000", 0),
+PCI_ROM(0x126c, 0x8030, "emobility", "Nortel emobility", 0),
+};
+
+PCI_DRIVER ( prism2_plx_driver, prism2_plx_nics, PCI_NO_CLASS );
+
+
+DRIVER ( "Prism2/PLX", nic_driver, pci_driver, prism2_plx_driver,
+ prism2_plx_probe, prism2_plx_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.c
new file mode 100644
index 0000000..b468782
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.c
@@ -0,0 +1,2285 @@
+/*
+ * Copyright (c) 2008 Marty Connor <mdc@etherboot.org>
+ * Copyright (c) 2008 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is based on rtl8169 data sheets and work by:
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/io.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/malloc.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/pci.h>
+#include <gpxe/timer.h>
+#include <mii.h>
+
+#include "r8169.h"
+
+/*** Low level hardware routines ***/
+
+static void mdio_write(void *ioaddr, int reg_addr, int value)
+{
+ int i;
+
+ DBGP ( "mdio_write\n" );
+
+ RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff));
+
+ for (i = 20; i > 0; i--) {
+ /*
+ * Check if the RTL8169 has completed writing to the specified
+ * MII register.
+ */
+ if (!(RTL_R32(PHYAR) & 0x80000000))
+ break;
+ udelay(25);
+ }
+}
+
+static int mdio_read(void *ioaddr, int reg_addr)
+{
+ int i, value = -1;
+
+ DBGP ( "mdio_read\n" );
+
+ RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16);
+
+ for (i = 20; i > 0; i--) {
+ /*
+ * Check if the RTL8169 has completed retrieving data from
+ * the specified MII register.
+ */
+ if (RTL_R32(PHYAR) & 0x80000000) {
+ value = RTL_R32(PHYAR) & 0xffff;
+ break;
+ }
+ udelay(25);
+ }
+ return value;
+}
+
+static void mdio_patch(void *ioaddr, int reg_addr, int value)
+{
+ DBGP ( "mdio_patch\n" );
+
+ mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
+}
+
+static void rtl_ephy_write(void *ioaddr, int reg_addr, int value)
+{
+ unsigned int i;
+
+ DBGP ( "rtl_ephy_write\n" );
+
+ RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
+ (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG))
+ break;
+ udelay(10);
+ }
+}
+
+static u16 rtl_ephy_read(void *ioaddr, int reg_addr)
+{
+ u16 value = 0xffff;
+ unsigned int i;
+
+ DBGP ( "rtl_ephy_read\n" );
+
+ RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(EPHYAR) & EPHYAR_FLAG) {
+ value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK;
+ break;
+ }
+ udelay(10);
+ }
+
+ return value;
+}
+
+static void rtl_csi_write(void *ioaddr, int addr, int value)
+{
+ unsigned int i;
+
+ DBGP ( "rtl_csi_write\n" );
+
+ RTL_W32(CSIDR, value);
+ RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
+ break;
+ udelay(10);
+ }
+}
+
+static u32 rtl_csi_read(void *ioaddr, int addr)
+{
+ u32 value = ~0x00;
+ unsigned int i;
+
+ DBGP ( "rtl_csi_read\n" );
+
+ RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(CSIAR) & CSIAR_FLAG) {
+ value = RTL_R32(CSIDR);
+ break;
+ }
+ udelay(10);
+ }
+
+ return value;
+}
+
+static void rtl8169_irq_mask_and_ack(void *ioaddr)
+{
+ DBGP ( "rtl8169_irq_mask_and_ack\n" );
+
+ RTL_W16(IntrMask, 0x0000);
+
+ RTL_W16(IntrStatus, 0xffff);
+}
+
+static unsigned int rtl8169_tbi_reset_pending(void *ioaddr)
+{
+ DBGP ( "rtl8169_tbi_reset_pending\n" );
+
+ return RTL_R32(TBICSR) & TBIReset;
+}
+
+static unsigned int rtl8169_xmii_reset_pending(void *ioaddr)
+{
+ DBGP ( "rtl8169_xmii_reset_pending\n" );
+
+ return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET;
+}
+
+static unsigned int rtl8169_tbi_link_ok(void *ioaddr)
+{
+ DBGP ( "rtl8169_tbi_link_ok\n" );
+
+ return RTL_R32(TBICSR) & TBILinkOk;
+}
+
+static unsigned int rtl8169_xmii_link_ok(void *ioaddr)
+{
+ DBGP ( "rtl8169_xmii_link_ok\n" );
+
+ return RTL_R8(PHYstatus) & LinkStatus;
+}
+
+static void rtl8169_tbi_reset_enable(void *ioaddr)
+{
+ DBGP ( "rtl8169_tbi_reset_enable\n" );
+
+ RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
+}
+
+static void rtl8169_xmii_reset_enable(void *ioaddr)
+{
+ unsigned int val;
+
+ DBGP ( "rtl8169_xmii_reset_enable\n" );
+
+ val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET;
+ mdio_write(ioaddr, MII_BMCR, val & 0xffff);
+}
+
+static int rtl8169_set_speed_tbi(struct net_device *dev,
+ u8 autoneg, u16 speed, u8 duplex)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ int ret = 0;
+ u32 reg;
+
+ DBGP ( "rtl8169_set_speed_tbi\n" );
+
+ reg = RTL_R32(TBICSR);
+ if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
+ (duplex == DUPLEX_FULL)) {
+ RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
+ } else if (autoneg == AUTONEG_ENABLE)
+ RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
+ else {
+ DBG ( "incorrect speed setting refused in TBI mode\n" );
+ ret = -EOPNOTSUPP;
+ }
+ return ret;
+}
+
+static int rtl8169_set_speed_xmii(struct net_device *dev,
+ u8 autoneg, u16 speed, u8 duplex)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ int auto_nego, giga_ctrl;
+
+ DBGP ( "rtl8169_set_speed_xmii\n" );
+
+ auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
+ auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_100FULL);
+ giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
+ giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+
+ if (autoneg == AUTONEG_ENABLE) {
+ auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
+ ADVERTISE_100HALF | ADVERTISE_100FULL);
+ giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+ } else {
+ if (speed == SPEED_10)
+ auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;
+ else if (speed == SPEED_100)
+ auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;
+ else if (speed == SPEED_1000)
+ giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+
+ if (duplex == DUPLEX_HALF)
+ auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);
+
+ if (duplex == DUPLEX_FULL)
+ auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);
+
+ /* This tweak comes straight from Realtek's driver. */
+ if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&
+ ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16))) {
+ auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
+ }
+ }
+
+ /* The 8100e/8101e/8102e do Fast Ethernet only. */
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_07) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_08) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_09) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_10) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
+ if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF))) {
+ DBG ( "PHY does not support 1000Mbps.\n" );
+ }
+ giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ }
+
+ auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
+ (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
+ /*
+ * Wake up the PHY.
+ * Vendor specific (0x1f) and reserved (0x0e) MII registers.
+ */
+ mdio_write(ioaddr, 0x1f, 0x0000);
+ mdio_write(ioaddr, 0x0e, 0x0000);
+ }
+
+ tp->phy_auto_nego_reg = auto_nego;
+ tp->phy_1000_ctrl_reg = giga_ctrl;
+
+ mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
+ mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
+ mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+ return 0;
+}
+
+static int rtl8169_set_speed(struct net_device *dev,
+ u8 autoneg, u16 speed, u8 duplex)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int ret;
+
+ DBGP ( "rtl8169_set_speed\n" );
+
+ ret = tp->set_speed(dev, autoneg, speed, duplex);
+
+ return ret;
+}
+
+static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg,
+ int bitnum, int bitval)
+{
+ int val;
+
+ DBGP ( "rtl8169_write_gmii_reg_bit\n" );
+
+ val = mdio_read(ioaddr, reg);
+ val = (bitval == 1) ?
+ val | (bitval << bitnum) : val & ~(0x0001 << bitnum);
+ mdio_write(ioaddr, reg, val & 0xffff);
+}
+
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+ void *ioaddr)
+{
+ /*
+ * The driver currently handles the 8168Bf and the 8168Be identically
+ * but they can be identified more specifically through the test below
+ * if needed:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+ *
+ * Same thing for the 8101Eb and the 8101Ec:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+ */
+ const struct {
+ u32 mask;
+ u32 val;
+ int mac_version;
+ } mac_info[] = {
+ /* 8168D family. */
+ { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 },
+
+ /* 8168C family. */
+ { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 },
+ { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
+ { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
+ { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
+ { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
+ { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
+ { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
+ { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
+ { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
+
+ /* 8168B family. */
+ { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
+ { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
+
+ /* 8101 family. */
+ { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
+ { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
+ { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
+ { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
+ { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
+ { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
+ { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
+ { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
+ { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
+ { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
+ { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
+ { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
+ /* FIXME: where did these entries come from ? -- FR */
+ { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
+ { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
+
+ /* 8110 family. */
+ { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
+ { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
+ { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
+ { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
+ { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
+ { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
+
+ { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */
+ }, *p = mac_info;
+ u32 reg;
+
+ DBGP ( "rtl8169_get_mac_version\n" );
+
+ reg = RTL_R32(TxConfig);
+ while ((reg & p->mask) != p->val)
+ p++;
+ tp->mac_version = p->mac_version;
+
+ DBG ( "tp->mac_version = %d\n", tp->mac_version );
+
+ if (p->mask == 0x00000000) {
+ DBG ( "unknown MAC (%08x)\n", reg );
+ }
+}
+
+struct phy_reg {
+ u16 reg;
+ u16 val;
+};
+
+static void rtl_phy_write(void *ioaddr, struct phy_reg *regs, int len)
+{
+ DBGP ( "rtl_phy_write\n" );
+
+ while (len-- > 0) {
+ mdio_write(ioaddr, regs->reg, regs->val);
+ regs++;
+ }
+}
+
+static void rtl8169s_hw_phy_config(void *ioaddr)
+{
+ struct {
+ u16 regs[5]; /* Beware of bit-sign propagation */
+ } phy_magic[5] = { {
+ { 0x0000, //w 4 15 12 0
+ 0x00a1, //w 3 15 0 00a1
+ 0x0008, //w 2 15 0 0008
+ 0x1020, //w 1 15 0 1020
+ 0x1000 } },{ //w 0 15 0 1000
+ { 0x7000, //w 4 15 12 7
+ 0xff41, //w 3 15 0 ff41
+ 0xde60, //w 2 15 0 de60
+ 0x0140, //w 1 15 0 0140
+ 0x0077 } },{ //w 0 15 0 0077
+ { 0xa000, //w 4 15 12 a
+ 0xdf01, //w 3 15 0 df01
+ 0xdf20, //w 2 15 0 df20
+ 0xff95, //w 1 15 0 ff95
+ 0xfa00 } },{ //w 0 15 0 fa00
+ { 0xb000, //w 4 15 12 b
+ 0xff41, //w 3 15 0 ff41
+ 0xde20, //w 2 15 0 de20
+ 0x0140, //w 1 15 0 0140
+ 0x00bb } },{ //w 0 15 0 00bb
+ { 0xf000, //w 4 15 12 f
+ 0xdf01, //w 3 15 0 df01
+ 0xdf20, //w 2 15 0 df20
+ 0xff95, //w 1 15 0 ff95
+ 0xbf00 } //w 0 15 0 bf00
+ }
+ }, *p = phy_magic;
+ unsigned int i;
+
+ DBGP ( "rtl8169s_hw_phy_config\n" );
+
+ mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1
+ mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000
+ mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7
+ rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
+
+ for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
+ int val, pos = 4;
+
+ val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff);
+ mdio_write(ioaddr, pos, val);
+ while (--pos >= 0)
+ mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff);
+ rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
+ rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
+ }
+ mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0
+}
+
+static void rtl8169sb_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0002 },
+ { 0x01, 0x90d0 },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8169sb_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168bb_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x10, 0xf41b },
+ { 0x1f, 0x0000 }
+ };
+
+ mdio_write(ioaddr, 0x1f, 0x0001);
+ mdio_patch(ioaddr, 0x16, 1 << 0);
+
+ DBGP ( "rtl8168bb_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168bef_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x10, 0xf41b },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8168bef_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cp_1_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0000 },
+ { 0x1d, 0x0f00 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x1ec8 },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8168cp_1_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cp_2_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x1d, 0x3d98 },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8168cp_2_hw_phy_config\n" );
+
+ mdio_write(ioaddr, 0x1f, 0x0000);
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168c_1_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x12, 0x2300 },
+ { 0x1f, 0x0002 },
+ { 0x00, 0x88d4 },
+ { 0x01, 0x82b1 },
+ { 0x03, 0x7002 },
+ { 0x08, 0x9e30 },
+ { 0x09, 0x01f0 },
+ { 0x0a, 0x5500 },
+ { 0x0c, 0x00c8 },
+ { 0x1f, 0x0003 },
+ { 0x12, 0xc096 },
+ { 0x16, 0x000a },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x09, 0x2000 },
+ { 0x09, 0x0000 }
+ };
+
+ DBGP ( "rtl8168c_1_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8168c_2_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x12, 0x2300 },
+ { 0x03, 0x802f },
+ { 0x02, 0x4f02 },
+ { 0x01, 0x0409 },
+ { 0x00, 0xf099 },
+ { 0x04, 0x9800 },
+ { 0x04, 0x9000 },
+ { 0x1d, 0x3d98 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x7eb8 },
+ { 0x06, 0x0761 },
+ { 0x1f, 0x0003 },
+ { 0x16, 0x0f0a },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8168c_2_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ mdio_patch(ioaddr, 0x16, 1 << 0);
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8168c_3_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x12, 0x2300 },
+ { 0x1d, 0x3d98 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x7eb8 },
+ { 0x06, 0x5461 },
+ { 0x1f, 0x0003 },
+ { 0x16, 0x0f0a },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8168c_3_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ mdio_patch(ioaddr, 0x16, 1 << 0);
+ mdio_patch(ioaddr, 0x14, 1 << 5);
+ mdio_patch(ioaddr, 0x0d, 1 << 5);
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8168c_4_hw_phy_config(void *ioaddr)
+{
+ DBGP ( "rtl8168c_4_hw_phy_config\n" );
+
+ rtl8168c_3_hw_phy_config(ioaddr);
+}
+
+static void rtl8168d_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init_0[] = {
+ { 0x1f, 0x0001 },
+ { 0x09, 0x2770 },
+ { 0x08, 0x04d0 },
+ { 0x0b, 0xad15 },
+ { 0x0c, 0x5bf0 },
+ { 0x1c, 0xf101 },
+ { 0x1f, 0x0003 },
+ { 0x14, 0x94d7 },
+ { 0x12, 0xf4d6 },
+ { 0x09, 0xca0f },
+ { 0x1f, 0x0002 },
+ { 0x0b, 0x0b10 },
+ { 0x0c, 0xd1f7 },
+ { 0x1f, 0x0002 },
+ { 0x06, 0x5461 },
+ { 0x1f, 0x0002 },
+ { 0x05, 0x6662 },
+ { 0x1f, 0x0000 },
+ { 0x14, 0x0060 },
+ { 0x1f, 0x0000 },
+ { 0x0d, 0xf8a0 },
+ { 0x1f, 0x0005 },
+ { 0x05, 0xffc2 }
+ };
+
+ DBGP ( "rtl8168d_hw_phy_config\n" );
+
+ rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+ if (mdio_read(ioaddr, 0x06) == 0xc400) {
+ struct phy_reg phy_reg_init_1[] = {
+ { 0x1f, 0x0005 },
+ { 0x01, 0x0300 },
+ { 0x1f, 0x0000 },
+ { 0x11, 0x401c },
+ { 0x16, 0x4100 },
+ { 0x1f, 0x0005 },
+ { 0x07, 0x0010 },
+ { 0x05, 0x83dc },
+ { 0x06, 0x087d },
+ { 0x05, 0x8300 },
+ { 0x06, 0x0101 },
+ { 0x06, 0x05f8 },
+ { 0x06, 0xf9fa },
+ { 0x06, 0xfbef },
+ { 0x06, 0x79e2 },
+ { 0x06, 0x835f },
+ { 0x06, 0xe0f8 },
+ { 0x06, 0x9ae1 },
+ { 0x06, 0xf89b },
+ { 0x06, 0xef31 },
+ { 0x06, 0x3b65 },
+ { 0x06, 0xaa07 },
+ { 0x06, 0x81e4 },
+ { 0x06, 0xf89a },
+ { 0x06, 0xe5f8 },
+ { 0x06, 0x9baf },
+ { 0x06, 0x06ae },
+ { 0x05, 0x83dc },
+ { 0x06, 0x8300 },
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init_1,
+ ARRAY_SIZE(phy_reg_init_1));
+ }
+
+ mdio_write(ioaddr, 0x1f, 0x0000);
+}
+
+static void rtl8102e_hw_phy_config(void *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0003 },
+ { 0x08, 0x441d },
+ { 0x01, 0x9100 },
+ { 0x1f, 0x0000 }
+ };
+
+ DBGP ( "rtl8102e_hw_phy_config\n" );
+
+ mdio_write(ioaddr, 0x1f, 0x0000);
+ mdio_patch(ioaddr, 0x11, 1 << 12);
+ mdio_patch(ioaddr, 0x19, 1 << 13);
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl_hw_phy_config(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+
+ DBGP ( "rtl_hw_phy_config\n" );
+
+ DBG ( "mac_version = 0x%02x\n", tp->mac_version );
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01:
+ break;
+ case RTL_GIGA_MAC_VER_02:
+ case RTL_GIGA_MAC_VER_03:
+ rtl8169s_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_04:
+ rtl8169sb_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_07:
+ case RTL_GIGA_MAC_VER_08:
+ case RTL_GIGA_MAC_VER_09:
+ rtl8102e_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_11:
+ rtl8168bb_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_12:
+ rtl8168bef_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_17:
+ rtl8168bef_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_18:
+ rtl8168cp_1_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_19:
+ rtl8168c_1_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_20:
+ rtl8168c_2_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_21:
+ rtl8168c_3_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_22:
+ rtl8168c_4_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_23:
+ case RTL_GIGA_MAC_VER_24:
+ rtl8168cp_2_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_25:
+ rtl8168d_hw_phy_config(ioaddr);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void rtl8169_phy_reset(struct net_device *dev __unused,
+ struct rtl8169_private *tp)
+{
+ void *ioaddr = tp->mmio_addr;
+ unsigned int i;
+
+ DBGP ( "rtl8169_phy_reset\n" );
+
+ tp->phy_reset_enable(ioaddr);
+ for (i = 0; i < 100; i++) {
+ if (!tp->phy_reset_pending(ioaddr))
+ return;
+ mdelay ( 1 );
+ }
+ DBG ( "PHY reset failed.\n" );
+}
+
+static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
+{
+ void *ioaddr = tp->mmio_addr;
+
+ DBGP ( "rtl8169_init_phy\n" );
+
+ rtl_hw_phy_config(dev);
+
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+ DBG ( "Set MAC Reg C+CR Offset 0x82h = 0x01h\n" );
+ RTL_W8(0x82, 0x01);
+ }
+
+ pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+ pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
+ DBG ( "Set MAC Reg C+CR Offset 0x82h = 0x01h\n" );
+ RTL_W8(0x82, 0x01);
+ DBG ( "Set PHY Reg 0x0bh = 0x00h\n" );
+ mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
+ }
+
+ rtl8169_phy_reset(dev, tp);
+
+ /*
+ * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+ * only 8101. Don't panic.
+ */
+ rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
+
+ if ((RTL_R8(PHYstatus) & TBI_Enable))
+ DBG ( "TBI auto-negotiating\n" );
+}
+
+static const struct rtl_cfg_info {
+ void (*hw_start)(struct net_device *);
+ unsigned int region;
+ unsigned int align;
+ u16 intr_event;
+ u16 napi_event;
+ unsigned features;
+} rtl_cfg_infos [] = {
+ [RTL_CFG_0] = {
+ .hw_start = rtl_hw_start_8169,
+ .region = 1,
+ .align = 0,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .features = RTL_FEATURE_GMII
+ },
+ [RTL_CFG_1] = {
+ .hw_start = rtl_hw_start_8168,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ TxErr | TxOK | RxOK | RxErr,
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow,
+ .features = RTL_FEATURE_GMII
+ },
+ [RTL_CFG_2] = {
+ .hw_start = rtl_hw_start_8101,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ }
+};
+
+static void rtl8169_hw_reset(void *ioaddr)
+{
+ DBGP ( "rtl8169_hw_reset\n" );
+
+ /* Disable interrupts */
+ rtl8169_irq_mask_and_ack(ioaddr);
+
+ /* Reset the chipset */
+ RTL_W8(ChipCmd, CmdReset);
+
+ /* PCI commit */
+ RTL_R8(ChipCmd);
+}
+
+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
+{
+ void *ioaddr = tp->mmio_addr;
+ u32 cfg = rtl8169_rx_config;
+
+ DBGP ( "rtl_set_rx_tx_config_registers\n" );
+
+ cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
+ RTL_W32(RxConfig, cfg);
+
+ /* Set DMA burst size and Interframe Gap Time */
+ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
+ (InterFrameGap << TxInterFrameGapShift));
+}
+
+static void rtl_soft_reset ( struct net_device *dev )
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ unsigned int i;
+
+ DBGP ( "rtl_hw_soft_reset\n" );
+
+ /* Soft reset the chip. */
+ RTL_W8(ChipCmd, CmdReset);
+
+ /* Check that the chip has finished the reset. */
+ for (i = 0; i < 100; i++) {
+ if ((RTL_R8(ChipCmd) & CmdReset) == 0)
+ break;
+ mdelay ( 1 );
+ }
+
+ if ( i == 100 ) {
+ DBG ( "Reset Failed! (> 100 iterations)\n" );
+ }
+}
+
+static void rtl_hw_start ( struct net_device *dev )
+{
+ struct rtl8169_private *tp = netdev_priv ( dev );
+
+ DBGP ( "rtl_hw_start\n" );
+
+ /* Soft reset NIC */
+ rtl_soft_reset ( dev );
+
+ tp->hw_start ( dev );
+}
+
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
+ void *ioaddr)
+{
+ DBGP ( "rtl_set_rx_tx_desc_registers\n" );
+
+ /*
+ * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+ * register to be written before TxDescAddrLow to work.
+ * Switching from MMIO to I/O access fixes the issue as well.
+ */
+ RTL_W32 ( TxDescStartAddrHigh, 0 );
+ RTL_W32 ( TxDescStartAddrLow, virt_to_bus ( tp->tx_base ) );
+ RTL_W32 ( RxDescAddrHigh, 0 );
+ RTL_W32 ( RxDescAddrLow, virt_to_bus ( tp->rx_base ) );
+}
+
+static u16 rtl_rw_cpluscmd(void *ioaddr)
+{
+ u16 cmd;
+
+ DBGP ( "rtl_rw_cpluscmd\n" );
+
+ cmd = RTL_R16(CPlusCmd);
+ RTL_W16(CPlusCmd, cmd);
+ return cmd;
+}
+
+static void rtl_set_rx_max_size(void *ioaddr)
+{
+ DBGP ( "rtl_set_rx_max_size\n" );
+
+ RTL_W16 ( RxMaxSize, RX_BUF_SIZE );
+}
+
+static void rtl8169_set_magic_reg(void *ioaddr, unsigned mac_version)
+{
+ struct {
+ u32 mac_version;
+ u32 clk;
+ u32 val;
+ } cfg2_info [] = {
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
+ }, *p = cfg2_info;
+ unsigned int i;
+ u32 clk;
+
+ DBGP ( "rtl8169_set_magic_reg\n" );
+
+ clk = RTL_R8(Config2) & PCI_Clock_66MHz;
+ for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
+ if ((p->mac_version == mac_version) && (p->clk == clk)) {
+ RTL_W32(0x7c, p->val);
+ break;
+ }
+ }
+}
+
+static void rtl_set_rx_mode ( struct net_device *netdev )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ void *ioaddr = tp->mmio_addr;
+ u32 tmp;
+
+ DBGP ( "rtl_set_rx_mode\n" );
+
+ /* Accept all Multicast Packets */
+
+ RTL_W32 ( MAR0 + 0, 0xffffffff );
+ RTL_W32 ( MAR0 + 4, 0xffffffff );
+
+ tmp = rtl8169_rx_config | AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+ ( RTL_R32 ( RxConfig ) & rtl_chip_info[tp->chipset].RxConfigMask );
+
+ RTL_W32 ( RxConfig, tmp );
+}
+
+static void rtl_hw_start_8169(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ struct pci_device *pdev = tp->pci_dev;
+
+ DBGP ( "rtl_hw_start_8169\n" );
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_04))
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_04))
+ rtl_set_rx_tx_config_registers(tp);
+
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
+ DBG ( "Set MAC Reg C+CR Offset 0xE0. "
+ "Bit-3 and bit-14 MUST be 1\n" );
+ tp->cp_cmd |= (1 << 14);
+ }
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ rtl8169_set_magic_reg(ioaddr, tp->mac_version);
+
+ /*
+ * Undocumented corner. Supposedly:
+ * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
+ */
+ RTL_W16(IntrMitigate, 0x0000);
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
+ (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
+ (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
+ (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ rtl_set_rx_tx_config_registers(tp);
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ /* no early-rx interrupts */
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+ // RTL_W16(IntrMask, tp->intr_event);
+}
+
+static void rtl_tx_performance_tweak(struct pci_device *pdev, u16 force)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int cap = tp->pcie_cap;
+
+ DBGP ( "rtl_tx_performance_tweak\n" );
+
+ if (cap) {
+ u16 ctl;
+
+ pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+}
+
+static void rtl_csi_access_enable(void *ioaddr)
+{
+ u32 csi;
+
+ DBGP ( "rtl_csi_access_enable\n" );
+
+ csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff;
+ rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000);
+}
+
+struct ephy_info {
+ unsigned int offset;
+ u16 mask;
+ u16 bits;
+};
+
+static void rtl_ephy_init(void *ioaddr, struct ephy_info *e, int len)
+{
+ u16 w;
+
+ DBGP ( "rtl_ephy_init\n" );
+
+ while (len-- > 0) {
+ w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits;
+ rtl_ephy_write(ioaddr, e->offset, w);
+ e++;
+ }
+}
+
+static void rtl_disable_clock_request(struct pci_device *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int cap = tp->pcie_cap;
+
+ DBGP ( "rtl_disable_clock_request\n" );
+
+ if (cap) {
+ u16 ctl;
+
+ pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl);
+ ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl);
+ }
+}
+
+#define R8168_CPCMD_QUIRK_MASK (\
+ EnableBist | \
+ Mac_dbgo_oe | \
+ Force_half_dup | \
+ Force_rxflow_en | \
+ Force_txflow_en | \
+ Cxpl_dbg_sel | \
+ ASF | \
+ PktCntrDisable | \
+ Mac_dbgo_sel)
+
+static void rtl_hw_start_8168bb(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168bb\n" );
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+
+ rtl_tx_performance_tweak(pdev,
+ (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void rtl_hw_start_8168bef(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168bef\n" );
+
+ rtl_hw_start_8168bb(ioaddr, pdev);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+}
+
+static void __rtl_hw_start_8168cp(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "__rtl_hw_start_8168cp\n" );
+
+ RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ rtl_disable_clock_request(pdev);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168cp_1(void *ioaddr, struct pci_device *pdev)
+{
+ static struct ephy_info e_info_8168cp[] = {
+ { 0x01, 0, 0x0001 },
+ { 0x02, 0x0800, 0x1000 },
+ { 0x03, 0, 0x0042 },
+ { 0x06, 0x0080, 0x0000 },
+ { 0x07, 0, 0x2000 }
+ };
+
+ DBGP ( "rtl_hw_start_8168cp_1\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168cp_2(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168cp_2\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168cp_3(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168cp_3\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ /* Magic. */
+ RTL_W8(DBG_REG, 0x20);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168c_1(void *ioaddr, struct pci_device *pdev)
+{
+ static struct ephy_info e_info_8168c_1[] = {
+ { 0x02, 0x0800, 0x1000 },
+ { 0x03, 0, 0x0002 },
+ { 0x06, 0x0080, 0x0000 }
+ };
+
+ DBGP ( "rtl_hw_start_8168c_1\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
+
+ rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_2(void *ioaddr, struct pci_device *pdev)
+{
+ static struct ephy_info e_info_8168c_2[] = {
+ { 0x01, 0, 0x0001 },
+ { 0x03, 0x0400, 0x0220 }
+ };
+
+ DBGP ( "rtl_hw_start_8168c_2\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_3(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168c_3\n" );
+
+ rtl_hw_start_8168c_2(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168c_4(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168c_4\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ __rtl_hw_start_8168cp(ioaddr, pdev);
+}
+
+static void rtl_hw_start_8168d(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8168d\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_disable_clock_request(pdev);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8168(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ struct pci_device *pdev = tp->pci_dev;
+
+ DBGP ( "rtl_hw_start_8168\n" );
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ RTL_W16(IntrMitigate, 0x5151);
+
+ /* Work around for RxFIFO overflow. */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+ tp->intr_event |= RxFIFOOver | PCSTimeout;
+ tp->intr_event &= ~RxOverflow;
+ }
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
+ (InterFrameGap << TxInterFrameGapShift));
+
+ RTL_R8(IntrMask);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_11:
+ rtl_hw_start_8168bb(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_17:
+ rtl_hw_start_8168bef(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_18:
+ rtl_hw_start_8168cp_1(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_19:
+ rtl_hw_start_8168c_1(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_20:
+ rtl_hw_start_8168c_2(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_21:
+ rtl_hw_start_8168c_3(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_22:
+ rtl_hw_start_8168c_4(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_23:
+ rtl_hw_start_8168cp_2(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_24:
+ rtl_hw_start_8168cp_3(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_25:
+ rtl_hw_start_8168d(ioaddr, pdev);
+ break;
+
+ default:
+ DBG ( "Unknown chipset (mac_version = %d).\n",
+ tp->mac_version );
+ break;
+ }
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+ // RTL_W16(IntrMask, tp->intr_event);
+}
+
+#define R810X_CPCMD_QUIRK_MASK (\
+ EnableBist | \
+ Mac_dbgo_oe | \
+ Force_half_dup | \
+ Force_half_dup | \
+ Force_txflow_en | \
+ Cxpl_dbg_sel | \
+ ASF | \
+ PktCntrDisable | \
+ PCIDAC | \
+ PCIMulRW)
+
+static void rtl_hw_start_8102e_1(void *ioaddr, struct pci_device *pdev)
+{
+ static struct ephy_info e_info_8102e_1[] = {
+ { 0x01, 0, 0x6e65 },
+ { 0x02, 0, 0x091f },
+ { 0x03, 0, 0xc2f9 },
+ { 0x06, 0, 0xafb5 },
+ { 0x07, 0, 0x0e00 },
+ { 0x19, 0, 0xec80 },
+ { 0x01, 0, 0x2e65 },
+ { 0x01, 0, 0x6e65 }
+ };
+ u8 cfg1;
+
+ DBGP ( "rtl_hw_start_8102e_1\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ RTL_W8(DBG_REG, FIX_NAK_1);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W8(Config1,
+ LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ cfg1 = RTL_R8(Config1);
+ if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
+ RTL_W8(Config1, cfg1 & ~LEDS0);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
+
+ rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
+}
+
+static void rtl_hw_start_8102e_2(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8102e_2\n" );
+
+ rtl_csi_access_enable(ioaddr);
+
+ rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
+ RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK);
+}
+
+static void rtl_hw_start_8102e_3(void *ioaddr, struct pci_device *pdev)
+{
+ DBGP ( "rtl_hw_start_8102e_3\n" );
+
+ rtl_hw_start_8102e_2(ioaddr, pdev);
+
+ rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
+}
+
+static void rtl_hw_start_8101(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void *ioaddr = tp->mmio_addr;
+ struct pci_device *pdev = tp->pci_dev;
+
+ DBGP ( "rtl_hw_start_8101\n" );
+
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
+ int cap = tp->pcie_cap;
+
+ if (cap) {
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_NOSNOOP_EN);
+ }
+ }
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_07:
+ rtl_hw_start_8102e_1(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_08:
+ rtl_hw_start_8102e_3(ioaddr, pdev);
+ break;
+
+ case RTL_GIGA_MAC_VER_09:
+ rtl_hw_start_8102e_2(ioaddr, pdev);
+ break;
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ RTL_W16(IntrMitigate, 0x0000);
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ rtl_set_rx_tx_config_registers(tp);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
+
+ // RTL_W16(IntrMask, tp->intr_event);
+}
+
+/*** gPXE API Support Routines ***/
+
+/**
+ * setup_tx_resources - allocate tx resources (descriptors)
+ *
+ * @v tp Driver private storage
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ **/
+static int
+rtl8169_setup_tx_resources ( struct rtl8169_private *tp )
+{
+ DBGP ( "rtl8169_setup_tx_resources\n" );
+
+ tp->tx_base = malloc_dma ( R8169_TX_RING_BYTES, TX_RING_ALIGN );
+
+ if ( ! tp->tx_base ) {
+ return -ENOMEM;
+ }
+
+ memset ( tp->tx_base, 0, R8169_TX_RING_BYTES );
+
+ DBG ( "tp->tx_base = %#08lx\n", virt_to_bus ( tp->tx_base ) );
+
+ tp->tx_fill_ctr = 0;
+ tp->tx_curr = 0;
+ tp->tx_tail = 0;
+
+ return 0;
+}
+
+static void
+rtl8169_process_tx_packets ( struct net_device *netdev )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+
+ uint32_t tx_status;
+ struct TxDesc *tx_curr_desc;
+
+ DBGP ( "rtl8169_process_tx_packets\n" );
+
+ while ( tp->tx_tail != tp->tx_curr ) {
+
+ tx_curr_desc = tp->tx_base + tp->tx_tail;
+
+ tx_status = tx_curr_desc->opts1;
+
+ DBG2 ( "Before DescOwn check tx_status: %#08x\n", tx_status );
+
+ /* if the packet at tx_tail is not owned by hardware it is for us */
+ if ( tx_status & DescOwn )
+ break;
+
+ DBG ( "Transmitted packet.\n" );
+ DBG ( "tp->tx_fill_ctr = %d\n", tp->tx_fill_ctr );
+ DBG ( "tp->tx_tail = %d\n", tp->tx_tail );
+ DBG ( "tp->tx_curr = %d\n", tp->tx_curr );
+ DBG ( "tx_status = %d\n", tx_status );
+ DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
+
+ /* Pass packet to core for processing */
+ netdev_tx_complete ( netdev, tp->tx_iobuf[tp->tx_tail] );
+
+ memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
+
+ /* Decrement count of used descriptors */
+ tp->tx_fill_ctr--;
+
+ /* Increment sent packets index */
+ tp->tx_tail = ( tp->tx_tail + 1 ) % NUM_TX_DESC;
+ }
+}
+
+static void
+rtl8169_free_tx_resources ( struct rtl8169_private *tp )
+{
+ DBGP ( "rtl8169_free_tx_resources\n" );
+
+ free_dma ( tp->tx_base, R8169_TX_RING_BYTES );
+}
+
+static void
+rtl8169_populate_rx_descriptor ( struct rtl8169_private *tp, struct RxDesc *rx_desc, uint32_t index )
+{
+ DBGP ( "rtl8169_populate_rx_descriptor\n" );
+
+ DBG ( "Populating rx descriptor %d\n", index );
+
+ memset ( rx_desc, 0, sizeof ( *rx_desc ) );
+
+ rx_desc->addr_hi = 0;
+ rx_desc->addr_lo = virt_to_bus ( tp->rx_iobuf[index]->data );
+ rx_desc->opts2 = 0;
+ rx_desc->opts1 = ( index == ( NUM_RX_DESC - 1 ) ? RingEnd : 0 ) |
+ RX_BUF_SIZE;
+ rx_desc->opts1 |= DescOwn;
+}
+
+/**
+ * Refill descriptor ring
+ *
+ * @v netdev Net device
+ */
+static void rtl8169_refill_rx_ring ( struct rtl8169_private *tp )
+{
+ struct RxDesc *rx_curr_desc;
+ int i;
+
+ DBGP ( "rtl8169_refill_rx_ring\n" );
+
+ for ( i = 0; i < NUM_RX_DESC; i++ ) {
+
+ rx_curr_desc = ( tp->rx_base ) + i;
+
+ /* Don't touch descriptors owned by the NIC */
+ if ( rx_curr_desc->opts1 & DescOwn )
+ continue;
+
+ /* Don't touch descriptors with iobufs, they still need to be
+ processed by the poll routine */
+ if ( tp->rx_iobuf[tp->rx_curr] != NULL )
+ continue;
+
+ /** If we can't get an iobuf for this descriptor
+ try again later (next poll).
+ */
+ if ( ! ( tp->rx_iobuf[i] = alloc_iob ( RX_BUF_SIZE ) ) ) {
+ DBG ( "Refill rx ring failed!!\n" );
+ break;
+ }
+
+ rtl8169_populate_rx_descriptor ( tp, rx_curr_desc, i );
+ }
+}
+
+/**
+ * setup_rx_resources - allocate Rx resources (Descriptors)
+ *
+ * @v tp: Driver private structure
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ *
+ **/
+static int
+rtl8169_setup_rx_resources ( struct rtl8169_private *tp )
+{
+ DBGP ( "rtl8169_setup_rx_resources\n" );
+
+ tp->rx_base = malloc_dma ( R8169_RX_RING_BYTES, RX_RING_ALIGN );
+
+ DBG ( "tp->rx_base = %#08lx\n", virt_to_bus ( tp->rx_base ) );
+
+ if ( ! tp->rx_base ) {
+ return -ENOMEM;
+ }
+ memset ( tp->rx_base, 0, R8169_RX_RING_BYTES );
+
+ rtl8169_refill_rx_ring ( tp );
+
+ tp->rx_curr = 0;
+
+ return 0;
+}
+
+static void
+rtl8169_process_rx_packets ( struct net_device *netdev )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ uint32_t rx_status;
+ uint16_t rx_len;
+ struct RxDesc *rx_curr_desc;
+ int i;
+
+ DBGP ( "rtl8169_process_rx_packets\n" );
+
+ for ( i = 0; i < NUM_RX_DESC; i++ ) {
+
+ rx_curr_desc = tp->rx_base + tp->rx_curr;
+
+ rx_status = rx_curr_desc->opts1;
+
+ DBG2 ( "Before DescOwn check rx_status: %#08x\n", rx_status );
+
+ /* Hardware still owns the descriptor */
+ if ( rx_status & DescOwn )
+ break;
+
+ /* We own the descriptor, but it has not been refilled yet */
+ if ( tp->rx_iobuf[tp->rx_curr] == NULL )
+ break;
+
+ rx_len = rx_status & 0x3fff;
+
+ DBG ( "Received packet.\n" );
+ DBG ( "tp->rx_curr = %d\n", tp->rx_curr );
+ DBG ( "rx_len = %d\n", rx_len );
+ DBG ( "rx_status = %#08x\n", rx_status );
+ DBG ( "rx_curr_desc = %#08lx\n", virt_to_bus ( rx_curr_desc ) );
+
+ if ( rx_status & RxRES ) {
+
+ netdev_rx_err ( netdev, tp->rx_iobuf[tp->rx_curr], -EINVAL );
+
+ DBG ( "rtl8169_poll: Corrupted packet received!\n"
+ " rx_status: %#08x\n", rx_status );
+
+ } else {
+
+ /* Adjust size of the iobuf to reflect received data */
+ iob_put ( tp->rx_iobuf[tp->rx_curr], rx_len );
+
+ /* Add this packet to the receive queue. */
+ netdev_rx ( netdev, tp->rx_iobuf[tp->rx_curr] );
+ }
+
+ /* Invalidate this iobuf and descriptor */
+ tp->rx_iobuf[tp->rx_curr] = NULL;
+ memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
+
+ /* Update pointer to next available rx descriptor */
+ tp->rx_curr = ( tp->rx_curr + 1 ) % NUM_RX_DESC;
+ }
+ rtl8169_refill_rx_ring ( tp );
+}
+
+static void
+rtl8169_free_rx_resources ( struct rtl8169_private *tp )
+{
+ int i;
+
+ DBGP ( "rtl8169_free_rx_resources\n" );
+
+ free_dma ( tp->rx_base, R8169_RX_RING_BYTES );
+
+ for ( i = 0; i < NUM_RX_DESC; i++ ) {
+ free_iob ( tp->rx_iobuf[i] );
+ tp->rx_iobuf[i] = NULL;
+ }
+}
+
+/**
+ FIXME: Because gPXE's pci_device_id structure does not contain a
+ field to contain arbitrary data, we need the following table to
+ associate PCI IDs with nic variants, because a lot of driver
+ routines depend on knowing which kind of variant they are dealing
+ with. --mdc
+ **/
+
+#define _R(VENDOR,DEVICE,INDEX) \
+ { .vendor = VENDOR, .device = DEVICE, .index = INDEX }
+
+static const struct {
+ uint16_t vendor;
+ uint16_t device;
+ int index;
+} nic_variant_table[] = {
+ _R(0x10ec, 0x8129, RTL_CFG_0),
+ _R(0x10ec, 0x8136, RTL_CFG_2),
+ _R(0x10ec, 0x8167, RTL_CFG_0),
+ _R(0x10ec, 0x8168, RTL_CFG_1),
+ _R(0x10ec, 0x8169, RTL_CFG_0),
+ _R(0x1186, 0x4300, RTL_CFG_0),
+ _R(0x1259, 0xc107, RTL_CFG_0),
+ _R(0x16ec, 0x0116, RTL_CFG_0),
+ _R(0x1737, 0x1032, RTL_CFG_0),
+ _R(0x0001, 0x8168, RTL_CFG_2),
+};
+#undef _R
+
+static int
+rtl8169_get_nic_variant ( uint16_t vendor, uint16_t device )
+{
+ u32 i;
+
+ DBGP ( "rtl8169_get_nic_variant\n" );
+
+ for (i = 0; i < ARRAY_SIZE(nic_variant_table); i++) {
+ if ( ( nic_variant_table[i].vendor == vendor ) &&
+ ( nic_variant_table[i].device == device ) ) {
+ return ( nic_variant_table[i].index );
+ }
+ }
+ DBG ( "No matching NIC variant found!\n" );
+ return ( RTL_CFG_0 );
+}
+
+static void rtl8169_irq_enable ( struct rtl8169_private *tp )
+{
+ void *ioaddr = tp->mmio_addr;
+
+ DBGP ( "rtl8169_irq_enable\n" );
+
+ RTL_W16 ( IntrMask, tp->intr_event );
+}
+
+static void rtl8169_irq_disable ( struct rtl8169_private *tp )
+{
+ void *ioaddr = tp->mmio_addr;
+
+ DBGP ( "rtl8169_irq_disable\n" );
+
+ rtl8169_irq_mask_and_ack ( ioaddr );
+}
+
+/*** gPXE Core API Routines ***/
+
+/**
+ * open - Called when a network interface is made active
+ *
+ * @v netdev network interface device structure
+ * @ret rc Return status code, 0 on success, negative value on failure
+ *
+ **/
+static int
+rtl8169_open ( struct net_device *netdev )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ void *ioaddr = tp->mmio_addr;
+ int rc;
+
+ DBGP ( "rtl8169_open\n" );
+
+ /* allocate transmit descriptors */
+ rc = rtl8169_setup_tx_resources ( tp );
+ if ( rc ) {
+ DBG ( "Error setting up TX resources!\n" );
+ goto err_setup_tx;
+ }
+
+ /* allocate receive descriptors */
+ rc = rtl8169_setup_rx_resources ( tp );
+ if ( rc ) {
+ DBG ( "Error setting up RX resources!\n" );
+ goto err_setup_rx;
+ }
+
+ rtl_hw_start ( netdev );
+
+ DBG ( "TxDescStartAddrHigh = %#08lx\n", RTL_R32 ( TxDescStartAddrHigh ) );
+ DBG ( "TxDescStartAddrLow = %#08lx\n", RTL_R32 ( TxDescStartAddrLow ) );
+ DBG ( "RxDescAddrHigh = %#08lx\n", RTL_R32 ( RxDescAddrHigh ) );
+ DBG ( "RxDescAddrLow = %#08lx\n", RTL_R32 ( RxDescAddrLow ) );
+
+ return 0;
+
+err_setup_rx:
+ rtl8169_free_tx_resources ( tp );
+err_setup_tx:
+ rtl8169_hw_reset ( ioaddr );
+
+ return rc;
+}
+
+/**
+ * transmit - Transmit a packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * @ret rc Returns 0 on success, negative on failure
+ */
+static int
+rtl8169_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ void *ioaddr = tp->mmio_addr;
+ uint32_t tx_len = iob_len ( iobuf );
+
+ struct TxDesc *tx_curr_desc;
+
+ DBGP ("rtl8169_transmit\n");
+
+ if ( tp->tx_fill_ctr == NUM_TX_DESC ) {
+ DBG ("TX overflow\n");
+ return -ENOBUFS;
+ }
+
+ /**
+ * The rtl8169 family automatically pads short packets to a
+ * minimum size, but if it did not, like some older cards,
+ * we could do:
+ * iob_pad ( iobuf, ETH_ZLEN );
+ */
+
+ /* Save pointer to this iobuf we have been given to transmit so
+ we can pass it to netdev_tx_complete() later */
+ tp->tx_iobuf[tp->tx_curr] = iobuf;
+
+ tx_curr_desc = tp->tx_base + tp->tx_curr;
+
+ DBG ( "tp->tx_fill_ctr = %d\n", tp->tx_fill_ctr );
+ DBG ( "tp->tx_curr = %d\n", tp->tx_curr );
+ DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
+ DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) );
+ DBG ( "tx_len = %d\n", tx_len );
+
+ /* Configure current descriptor to transmit supplied packet */
+ tx_curr_desc->addr_hi = 0;
+ tx_curr_desc->addr_lo = virt_to_bus ( iobuf->data );
+ tx_curr_desc->opts2 = 0;
+ tx_curr_desc->opts1 = FirstFrag | LastFrag |
+ ( tp->tx_curr == ( NUM_TX_DESC - 1 ) ? RingEnd : 0 ) |
+ tx_len;
+
+ /* Mark descriptor as owned by NIC */
+ tx_curr_desc->opts1 |= DescOwn;
+
+ DBG ( "tx_curr_desc->opts1 = %#08x\n", tx_curr_desc->opts1 );
+ DBG ( "tx_curr_desc->opts2 = %#08x\n", tx_curr_desc->opts2 );
+ DBG ( "tx_curr_desc->addr_hi = %#08x\n", tx_curr_desc->addr_hi );
+ DBG ( "tx_curr_desc->addr_lo = %#08x\n", tx_curr_desc->addr_lo );
+
+ RTL_W8 ( TxPoll, NPQ ); /* set polling bit */
+
+ /* Point to next free descriptor */
+ tp->tx_curr = ( tp->tx_curr + 1 ) % NUM_TX_DESC;
+
+ /* Increment number of tx descriptors in use */
+ tp->tx_fill_ctr++;
+
+ return 0;
+}
+
+/**
+ * poll - Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void
+rtl8169_poll ( struct net_device *netdev )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ void *ioaddr = tp->mmio_addr;
+
+ uint16_t intr_status;
+ uint16_t intr_mask;
+
+ DBGP ( "rtl8169_poll\n" );
+
+ intr_status = RTL_R16 ( IntrStatus );
+ intr_mask = RTL_R16 ( IntrMask );
+
+ DBG2 ( "rtl8169_poll (before): intr_mask = %#04x intr_status = %#04x\n",
+ intr_mask, intr_status );
+
+ RTL_W16 ( IntrStatus, 0xffff );
+
+ /* hotplug / major error / no more work / shared irq */
+ if ( intr_status == 0xffff )
+ return;
+
+ /* Process transmitted packets */
+ rtl8169_process_tx_packets ( netdev );
+
+ /* Process received packets */
+ rtl8169_process_rx_packets ( netdev );
+}
+
+/**
+ * close - Disable network interface
+ *
+ * @v netdev network interface device structure
+ *
+ **/
+static void
+rtl8169_close ( struct net_device *netdev )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ void *ioaddr = tp->mmio_addr;
+
+ DBGP ( "r8169_close\n" );
+
+ rtl8169_hw_reset ( ioaddr );
+
+ rtl8169_free_tx_resources ( tp );
+ rtl8169_free_rx_resources ( tp );
+}
+
+/**
+ * irq - enable or Disable interrupts
+ *
+ * @v netdev network adapter
+ * @v action requested interrupt action
+ *
+ **/
+static void
+rtl8169_irq ( struct net_device *netdev, int action )
+{
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+
+ DBGP ( "rtl8169_irq\n" );
+
+ switch ( action ) {
+ case 0 :
+ rtl8169_irq_disable ( tp );
+ break;
+ default :
+ rtl8169_irq_enable ( tp );
+ break;
+ }
+}
+
+static struct net_device_operations rtl8169_operations = {
+ .open = rtl8169_open,
+ .transmit = rtl8169_transmit,
+ .poll = rtl8169_poll,
+ .close = rtl8169_close,
+ .irq = rtl8169_irq,
+};
+
+/**
+ * probe - Initial configuration of NIC
+ *
+ * @v pci PCI device
+ * @v id PCI IDs
+ *
+ * @ret rc Return status code
+ **/
+static int
+rtl8169_probe ( struct pci_device *pdev, const struct pci_device_id *ent )
+{
+ int i, rc;
+ struct net_device *netdev;
+ struct rtl8169_private *tp;
+ void *ioaddr;
+
+ /** FIXME: This lookup is necessary because gPXE does not have a "data"
+ element in the structure pci_device_id which can pass an arbitrary
+ piece of data to the driver. It might be useful to add it. Then we
+ could just use ent->data instead of having to look up cfg_index.
+ **/
+ int cfg_index = rtl8169_get_nic_variant ( ent->vendor, ent->device );
+ const struct rtl_cfg_info *cfg = rtl_cfg_infos + cfg_index;
+
+ DBGP ( "rtl8169_probe\n" );
+
+ DBG ( "ent->vendor = %#04x, ent->device = %#04x\n", ent->vendor, ent->device );
+
+ DBG ( "cfg_index = %d\n", cfg_index );
+ DBG ( "cfg->intr_event = %#04x\n", cfg->intr_event );
+
+ rc = -ENOMEM;
+
+ /* Allocate net device ( also allocates memory for netdev->priv
+ and makes netdev-priv point to it )
+ */
+ netdev = alloc_etherdev ( sizeof ( *tp ) );
+
+ if ( ! netdev )
+ goto err_alloc_etherdev;
+
+ /* Associate driver-specific network operations with
+ generic network device layer
+ */
+ netdev_init ( netdev, &rtl8169_operations );
+
+ /* Associate this network device with the given PCI device */
+ pci_set_drvdata ( pdev, netdev );
+ netdev->dev = &pdev->dev;
+
+ /* Initialize driver private storage */
+ tp = netdev_priv ( netdev );
+ memset ( tp, 0, ( sizeof ( *tp ) ) );
+
+ tp->pci_dev = pdev;
+ tp->irqno = pdev->irq;
+ tp->netdev = netdev;
+ tp->cfg_index = cfg_index;
+ tp->intr_event = cfg->intr_event;
+ tp->cp_cmd = PCIMulRW;
+
+ tp->hw_start = cfg->hw_start;
+
+ rc = -EIO;
+
+ adjust_pci_device ( pdev );
+
+ /* ioremap MMIO region */
+ ioaddr = ioremap ( pdev->membase, R8169_REGS_SIZE );
+
+ if ( ! ioaddr ) {
+ DBG ( "cannot remap MMIO\n" );
+ rc = -EIO;
+ goto err_ioremap;
+ }
+
+ tp->mmio_addr = ioaddr;
+
+ tp->pcie_cap = pci_find_capability ( pdev, PCI_CAP_ID_EXP );
+ if ( tp->pcie_cap ) {
+ DBG ( "PCI Express capability\n" );
+ } else {
+ DBG ( "No PCI Express capability\n" );
+ }
+
+ /* Mask interrupts just in case */
+ rtl8169_irq_mask_and_ack ( ioaddr );
+
+ /* Soft reset NIC */
+ rtl_soft_reset ( netdev );
+
+ /* Identify chip attached to board */
+ rtl8169_get_mac_version ( tp, ioaddr );
+
+ for ( i = 0; (u32) i < ARRAY_SIZE ( rtl_chip_info ); i++ ) {
+ if ( tp->mac_version == rtl_chip_info[i].mac_version )
+ break;
+ }
+ if ( i == ARRAY_SIZE(rtl_chip_info ) ) {
+ /* Unknown chip: assume array element #0, original RTL-8169 */
+ DBG ( "Unknown chip version, assuming %s\n", rtl_chip_info[0].name );
+ i = 0;
+ }
+ tp->chipset = i;
+
+ if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) &&
+ (RTL_R8(PHYstatus) & TBI_Enable)) {
+ tp->set_speed = rtl8169_set_speed_tbi;
+ tp->phy_reset_enable = rtl8169_tbi_reset_enable;
+ tp->phy_reset_pending = rtl8169_tbi_reset_pending;
+ tp->link_ok = rtl8169_tbi_link_ok;
+
+ tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */
+ } else {
+ tp->set_speed = rtl8169_set_speed_xmii;
+ tp->phy_reset_enable = rtl8169_xmii_reset_enable;
+ tp->phy_reset_pending = rtl8169_xmii_reset_pending;
+ tp->link_ok = rtl8169_xmii_link_ok;
+ }
+
+ /* Get MAC address */
+ for ( i = 0; i < MAC_ADDR_LEN; i++ )
+ netdev->hw_addr[i] = RTL_R8 ( MAC0 + i );
+
+ DBG ( "%s\n", eth_ntoa ( netdev->hw_addr ) );
+
+ rtl8169_init_phy ( netdev, tp );
+
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register;
+
+ /* Mark as link up; we don't yet handle link state */
+ netdev_link_up ( netdev );
+
+ DBG ( "rtl8169_probe succeeded!\n" );
+
+ /* No errors, return success */
+ return 0;
+
+/* Error return paths */
+err_register:
+err_ioremap:
+ netdev_put ( netdev );
+err_alloc_etherdev:
+ return rc;
+}
+
+/**
+ * remove - Device Removal Routine
+ *
+ * @v pdev PCI device information struct
+ *
+ **/
+static void
+rtl8169_remove ( struct pci_device *pdev )
+{
+ struct net_device *netdev = pci_get_drvdata ( pdev );
+ struct rtl8169_private *tp = netdev_priv ( netdev );
+ void *ioaddr = tp->mmio_addr;
+
+ DBGP ( "rtl8169_remove\n" );
+
+ rtl8169_hw_reset ( ioaddr );
+
+ unregister_netdev ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static struct pci_device_id rtl8169_nics[] = {
+ PCI_ROM(0x10ec, 0x8129, "rtl8169-0x8129", "rtl8169-0x8129", 0),
+ PCI_ROM(0x10ec, 0x8136, "rtl8169-0x8136", "rtl8169-0x8136", 0),
+ PCI_ROM(0x10ec, 0x8167, "rtl8169-0x8167", "rtl8169-0x8167", 0),
+ PCI_ROM(0x10ec, 0x8168, "rtl8169-0x8168", "rtl8169-0x8168", 0),
+ PCI_ROM(0x10ec, 0x8169, "rtl8169-0x8169", "rtl8169-0x8169", 0),
+ PCI_ROM(0x1186, 0x4300, "rtl8169-0x4300", "rtl8169-0x4300", 0),
+ PCI_ROM(0x1259, 0xc107, "rtl8169-0xc107", "rtl8169-0xc107", 0),
+ PCI_ROM(0x16ec, 0x0116, "rtl8169-0x0116", "rtl8169-0x0116", 0),
+ PCI_ROM(0x1737, 0x1032, "rtl8169-0x1032", "rtl8169-0x1032", 0),
+ PCI_ROM(0x0001, 0x8168, "rtl8169-0x8168", "rtl8169-0x8168", 0),
+};
+
+struct pci_driver rtl8169_driver __pci_driver = {
+ .ids = rtl8169_nics,
+ .id_count = ( sizeof ( rtl8169_nics ) / sizeof ( rtl8169_nics[0] ) ),
+ .probe = rtl8169_probe,
+ .remove = rtl8169_remove,
+};
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.h
new file mode 100644
index 0000000..89679b1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/r8169.h
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2008 Marty Connor <mdc@etherboot.org>
+ * Copyright (c) 2008 Entity Cyber, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is based on rtl8169 data sheets and work by:
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _R8169_H_
+#define _R8169_H_
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/** FIXME: include/linux/pci_regs.h has these PCI regs, maybe
+ we need such a file in gPXE?
+**/
+#define PCI_EXP_DEVCTL 8 /* Device Control */
+#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
+#define PCI_EXP_LNKCTL 16 /* Link Control */
+#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
+#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
+
+/** FIXME: update mii.h in src/include/mii.h from Linux sources
+ so we don't have to include these definitiions.
+**/
+/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define SPEED_2500 2500
+#define SPEED_10000 10000
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+/* MAC address length */
+#define MAC_ADDR_LEN 6
+
+#define MAX_READ_REQUEST_SHIFT 12
+#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
+#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
+#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
+#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
+#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */
+#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
+#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
+
+#define R8169_REGS_SIZE 256
+#define R8169_NAPI_WEIGHT 64
+#define NUM_TX_DESC 8 /* Number of Tx descriptor registers */
+#define NUM_RX_DESC 8 /* Number of Rx descriptor registers */
+#define RX_BUF_SIZE 1536 /* Rx Buffer size */
+#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
+#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
+
+#define TX_RING_ALIGN 256
+#define RX_RING_ALIGN 256
+
+#define RTL8169_TX_TIMEOUT (6*HZ)
+#define RTL8169_PHY_TIMEOUT (10*HZ)
+
+#define RTL_EEPROM_SIG cpu_to_le32(0x8129)
+#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff)
+#define RTL_EEPROM_SIG_ADDR 0x0000
+
+/* write/read MMIO register */
+#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
+#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
+#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
+#define RTL_R8(reg) readb (ioaddr + (reg))
+#define RTL_R16(reg) readw (ioaddr + (reg))
+#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
+
+enum mac_version {
+ RTL_GIGA_MAC_VER_01 = 0x01, // 8169
+ RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
+ RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
+ RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
+ RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
+ RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+ RTL_GIGA_MAC_VER_07 = 0x07, // 8102e
+ RTL_GIGA_MAC_VER_08 = 0x08, // 8102e
+ RTL_GIGA_MAC_VER_09 = 0x09, // 8102e
+ RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e
+ RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
+ RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be
+ RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb
+ RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ?
+ RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ?
+ RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec
+ RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf
+ RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP
+ RTL_GIGA_MAC_VER_19 = 0x13, // 8168C
+ RTL_GIGA_MAC_VER_20 = 0x14, // 8168C
+ RTL_GIGA_MAC_VER_21 = 0x15, // 8168C
+ RTL_GIGA_MAC_VER_22 = 0x16, // 8168C
+ RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP
+ RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
+ RTL_GIGA_MAC_VER_25 = 0x19, // 8168D
+};
+
+#define _R(NAME,MAC,MASK) \
+ { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
+
+static const struct {
+ const char *name;
+ u8 mac_version;
+ u32 RxConfigMask; /* Clears the bits supported by this chip */
+} rtl_chip_info[] = {
+ _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
+ _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
+ _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
+ _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
+ _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E
+ _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E
+ _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E
+ _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E
+ _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
+ _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
+ _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
+ _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139
+ _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139
+ _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E
+ _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
+ _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E
+};
+#undef _R
+
+enum cfg_version {
+ RTL_CFG_0 = 0x00,
+ RTL_CFG_1,
+ RTL_CFG_2
+};
+
+#if 0
+/** Device Table from Linux Driver **/
+static struct pci_device_id rtl8169_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032,
+ PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
+ { 0x0001, 0x8168,
+ PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
+ {0,},
+};
+#endif
+
+enum rtl_registers {
+ MAC0 = 0, /* Ethernet hardware address. */
+ MAC4 = 4,
+ MAR0 = 8, /* Multicast filter. */
+ CounterAddrLow = 0x10,
+ CounterAddrHigh = 0x14,
+ TxDescStartAddrLow = 0x20,
+ TxDescStartAddrHigh = 0x24,
+ TxHDescStartAddrLow = 0x28,
+ TxHDescStartAddrHigh = 0x2c,
+ FLASH = 0x30,
+ ERSR = 0x36,
+ ChipCmd = 0x37,
+ TxPoll = 0x38,
+ IntrMask = 0x3c,
+ IntrStatus = 0x3e,
+ TxConfig = 0x40,
+ RxConfig = 0x44,
+ RxMissed = 0x4c,
+ Cfg9346 = 0x50,
+ Config0 = 0x51,
+ Config1 = 0x52,
+ Config2 = 0x53,
+ Config3 = 0x54,
+ Config4 = 0x55,
+ Config5 = 0x56,
+ MultiIntr = 0x5c,
+ PHYAR = 0x60,
+ PHYstatus = 0x6c,
+ RxMaxSize = 0xda,
+ CPlusCmd = 0xe0,
+ IntrMitigate = 0xe2,
+ RxDescAddrLow = 0xe4,
+ RxDescAddrHigh = 0xe8,
+ EarlyTxThres = 0xec,
+ FuncEvent = 0xf0,
+ FuncEventMask = 0xf4,
+ FuncPresetState = 0xf8,
+ FuncForceEvent = 0xfc,
+};
+
+enum rtl8110_registers {
+ TBICSR = 0x64,
+ TBI_ANAR = 0x68,
+ TBI_LPAR = 0x6a,
+};
+
+enum rtl8168_8101_registers {
+ CSIDR = 0x64,
+ CSIAR = 0x68,
+#define CSIAR_FLAG 0x80000000
+#define CSIAR_WRITE_CMD 0x80000000
+#define CSIAR_BYTE_ENABLE 0x0f
+#define CSIAR_BYTE_ENABLE_SHIFT 12
+#define CSIAR_ADDR_MASK 0x0fff
+
+ EPHYAR = 0x80,
+#define EPHYAR_FLAG 0x80000000
+#define EPHYAR_WRITE_CMD 0x80000000
+#define EPHYAR_REG_MASK 0x1f
+#define EPHYAR_REG_SHIFT 16
+#define EPHYAR_DATA_MASK 0xffff
+ DBG_REG = 0xd1,
+#define FIX_NAK_1 (1 << 4)
+#define FIX_NAK_2 (1 << 3)
+};
+
+enum rtl_register_content {
+ /* InterruptStatusBits */
+ SYSErr = 0x8000,
+ PCSTimeout = 0x4000,
+ SWInt = 0x0100,
+ TxDescUnavail = 0x0080,
+ RxFIFOOver = 0x0040,
+ LinkChg = 0x0020,
+ RxOverflow = 0x0010,
+ TxErr = 0x0008,
+ TxOK = 0x0004,
+ RxErr = 0x0002,
+ RxOK = 0x0001,
+
+ /* RxStatusDesc */
+ RxFOVF = (1 << 23),
+ RxRWT = (1 << 22),
+ RxRES = (1 << 21),
+ RxRUNT = (1 << 20),
+ RxCRC = (1 << 19),
+
+ /* ChipCmdBits */
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08,
+ CmdTxEnb = 0x04,
+ RxBufEmpty = 0x01,
+
+ /* TXPoll register p.5 */
+ HPQ = 0x80, /* Poll cmd on the high prio queue */
+ NPQ = 0x40, /* Poll cmd on the low prio queue */
+ FSWInt = 0x01, /* Forced software interrupt */
+
+ /* Cfg9346Bits */
+ Cfg9346_Lock = 0x00,
+ Cfg9346_Unlock = 0xc0,
+
+ /* rx_mode_bits */
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0x08,
+ AcceptMulticast = 0x04,
+ AcceptMyPhys = 0x02,
+ AcceptAllPhys = 0x01,
+
+ /* RxConfigBits */
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8,
+
+ /* TxConfigBits */
+ TxInterFrameGapShift = 24,
+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
+
+ /* Config1 register p.24 */
+ LEDS1 = (1 << 7),
+ LEDS0 = (1 << 6),
+ MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */
+ Speed_down = (1 << 4),
+ MEMMAP = (1 << 3),
+ IOMAP = (1 << 2),
+ VPD = (1 << 1),
+ PMEnable = (1 << 0), /* Power Management Enable */
+
+ /* Config2 register p. 25 */
+ PCI_Clock_66MHz = 0x01,
+ PCI_Clock_33MHz = 0x00,
+
+ /* Config3 register p.25 */
+ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
+ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
+ Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
+
+ /* Config5 register p.27 */
+ BWF = (1 << 6), /* Accept Broadcast wakeup frame */
+ MWF = (1 << 5), /* Accept Multicast wakeup frame */
+ UWF = (1 << 4), /* Accept Unicast wakeup frame */
+ LanWake = (1 << 1), /* LanWake enable/disable */
+ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
+
+ /* TBICSR p.28 */
+ TBIReset = 0x80000000,
+ TBILoopback = 0x40000000,
+ TBINwEnable = 0x20000000,
+ TBINwRestart = 0x10000000,
+ TBILinkOk = 0x02000000,
+ TBINwComplete = 0x01000000,
+
+ /* CPlusCmd p.31 */
+ EnableBist = (1 << 15), // 8168 8101
+ Mac_dbgo_oe = (1 << 14), // 8168 8101
+ Normal_mode = (1 << 13), // unused
+ Force_half_dup = (1 << 12), // 8168 8101
+ Force_rxflow_en = (1 << 11), // 8168 8101
+ Force_txflow_en = (1 << 10), // 8168 8101
+ Cxpl_dbg_sel = (1 << 9), // 8168 8101
+ ASF = (1 << 8), // 8168 8101
+ PktCntrDisable = (1 << 7), // 8168 8101
+ Mac_dbgo_sel = 0x001c, // 8168
+ RxVlan = (1 << 6),
+ RxChkSum = (1 << 5),
+ PCIDAC = (1 << 4),
+ PCIMulRW = (1 << 3),
+ INTT_0 = 0x0000, // 8168
+ INTT_1 = 0x0001, // 8168
+ INTT_2 = 0x0002, // 8168
+ INTT_3 = 0x0003, // 8168
+
+ /* rtl8169_PHYstatus */
+ TBI_Enable = 0x80,
+ TxFlowCtrl = 0x40,
+ RxFlowCtrl = 0x20,
+ _1000bpsF = 0x10,
+ _100bps = 0x08,
+ _10bps = 0x04,
+ LinkStatus = 0x02,
+ FullDup = 0x01,
+
+ /* _TBICSRBit */
+ TBILinkOK = 0x02000000,
+
+ /* DumpCounterCommand */
+ CounterDump = 0x8,
+};
+
+enum desc_status_bit {
+ DescOwn = (1 << 31), /* Descriptor is owned by NIC */
+ RingEnd = (1 << 30), /* End of descriptor ring */
+ FirstFrag = (1 << 29), /* First segment of a packet */
+ LastFrag = (1 << 28), /* Final segment of a packet */
+
+ /* Tx private */
+ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
+ MSSShift = 16, /* MSS value position */
+ MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */
+ IPCS = (1 << 18), /* Calculate IP checksum */
+ UDPCS = (1 << 17), /* Calculate UDP/IP checksum */
+ TCPCS = (1 << 16), /* Calculate TCP/IP checksum */
+ TxVlanTag = (1 << 17), /* Add VLAN tag */
+
+ /* Rx private */
+ PID1 = (1 << 18), /* Protocol ID bit 1/2 */
+ PID0 = (1 << 17), /* Protocol ID bit 2/2 */
+
+#define RxProtoUDP (PID1)
+#define RxProtoTCP (PID0)
+#define RxProtoIP (PID1 | PID0)
+#define RxProtoMask RxProtoIP
+
+ IPFail = (1 << 16), /* IP checksum failed */
+ UDPFail = (1 << 15), /* UDP/IP checksum failed */
+ TCPFail = (1 << 14), /* TCP/IP checksum failed */
+ RxVlanTag = (1 << 16), /* VLAN tag available */
+};
+
+#define RsvdMask 0x3fffc000
+
+struct TxDesc {
+ volatile uint32_t opts1;
+ volatile uint32_t opts2;
+ volatile uint32_t addr_lo;
+ volatile uint32_t addr_hi;
+};
+
+struct RxDesc {
+ volatile uint32_t opts1;
+ volatile uint32_t opts2;
+ volatile uint32_t addr_lo;
+ volatile uint32_t addr_hi;
+};
+
+enum features {
+ RTL_FEATURE_WOL = (1 << 0),
+ RTL_FEATURE_MSI = (1 << 1),
+ RTL_FEATURE_GMII = (1 << 2),
+};
+
+static void rtl_hw_start_8169(struct net_device *);
+static void rtl_hw_start_8168(struct net_device *);
+static void rtl_hw_start_8101(struct net_device *);
+
+struct rtl8169_private {
+
+ struct pci_device *pci_dev;
+ struct net_device *netdev;
+ uint8_t *hw_addr;
+ void *mmio_addr;
+ uint32_t irqno;
+
+ int chipset;
+ int mac_version;
+ int cfg_index;
+ u16 intr_event;
+
+ struct io_buffer *tx_iobuf[NUM_TX_DESC];
+ struct io_buffer *rx_iobuf[NUM_RX_DESC];
+
+ struct TxDesc *tx_base;
+ struct RxDesc *rx_base;
+
+ uint32_t tx_curr;
+ uint32_t rx_curr;
+
+ uint32_t tx_tail;
+
+ uint32_t tx_fill_ctr;
+
+ u16 cp_cmd;
+
+ int phy_auto_nego_reg;
+ int phy_1000_ctrl_reg;
+
+ int ( *set_speed ) (struct net_device *, u8 autoneg, u16 speed, u8 duplex );
+ void ( *phy_reset_enable ) ( void *ioaddr );
+ void ( *hw_start ) ( struct net_device * );
+ unsigned int ( *phy_reset_pending ) ( void *ioaddr );
+ unsigned int ( *link_ok ) ( void *ioaddr );
+
+ int pcie_cap;
+
+ unsigned features;
+
+};
+
+static const unsigned int rtl8169_rx_config =
+ (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
+
+#endif /* _R8169_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/rtl8139.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/rtl8139.c
new file mode 100644
index 0000000..dd35f74
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/rtl8139.c
@@ -0,0 +1,606 @@
+/* rtl8139.c - etherboot driver for the Realtek 8139 chipset
+
+ ported from the linux driver written by Donald Becker
+ by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ changes to the original driver:
+ - removed support for interrupts, switching to polling mode (yuck!)
+ - removed support for the 8129 chip (external MII)
+
+*/
+
+FILE_LICENCE ( GPL_ANY );
+
+/*********************************************************************/
+/* Revision History */
+/*********************************************************************/
+
+/*
+ 27 May 2006 mcb30@users.sourceforge.net (Michael Brown)
+ Rewrote to use the new net driver API, the updated PCI API, and
+ the generic three-wire serial device support for EEPROM access.
+
+ 28 Dec 2002 ken_yap@users.sourceforge.net (Ken Yap)
+ Put in virt_to_bus calls to allow Etherboot relocation.
+
+ 06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap)
+ Following email from Hyun-Joon Cha, added a disable routine, otherwise
+ NIC remains live and can crash the kernel later.
+
+ 4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub)
+ Shuffled things around, removed the leftovers from the 8129 support
+ that was in the Linux driver and added a bit more 8139 definitions.
+ Moved the 8K receive buffer to a fixed, available address outside the
+ 0x98000-0x9ffff range. This is a bit of a hack, but currently the only
+ way to make room for the Etherboot features that need substantial amounts
+ of code like the ANSI console support. Currently the buffer is just below
+ 0x10000, so this even conforms to the tagged boot image specification,
+ which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My
+ interpretation of this "reserved" is that Etherboot may do whatever it
+ likes, as long as its environment is kept intact (like the BIOS
+ variables). Hopefully fixed rtl_poll() once and for all. The symptoms
+ were that if Etherboot was left at the boot menu for several minutes, the
+ first eth_poll failed. Seems like I am the only person who does this.
+ First of all I fixed the debugging code and then set out for a long bug
+ hunting session. It took me about a week full time work - poking around
+ various places in the driver, reading Don Becker's and Jeff Garzik's Linux
+ driver and even the FreeBSD driver (what a piece of crap!) - and
+ eventually spotted the nasty thing: the transmit routine was acknowledging
+ each and every interrupt pending, including the RxOverrun and RxFIFIOver
+ interrupts. This confused the RTL8139 thoroughly. It destroyed the
+ Rx ring contents by dumping the 2K FIFO contents right where we wanted to
+ get the next packet. Oh well, what fun.
+
+ 18 Jan 2000 mdc@etherboot.org (Marty Connor)
+ Drastically simplified error handling. Basically, if any error
+ in transmission or reception occurs, the card is reset.
+ Also, pointed all transmit descriptors to the same buffer to
+ save buffer space. This should decrease driver size and avoid
+ corruption because of exceeding 32K during runtime.
+
+ 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de)
+ rtl_poll was quite broken: it used the RxOK interrupt flag instead
+ of the RxBufferEmpty flag which often resulted in very bad
+ transmission performace - below 1kBytes/s.
+
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <gpxe/io.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <gpxe/pci.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/spi_bit.h>
+#include <gpxe/threewire.h>
+#include <gpxe/nvo.h>
+
+#define TX_RING_SIZE 4
+
+struct rtl8139_tx {
+ unsigned int next;
+ struct io_buffer *iobuf[TX_RING_SIZE];
+};
+
+struct rtl8139_rx {
+ void *ring;
+ unsigned int offset;
+};
+
+struct rtl8139_nic {
+ unsigned short ioaddr;
+ struct rtl8139_tx tx;
+ struct rtl8139_rx rx;
+ struct spi_bit_basher spibit;
+ struct spi_device eeprom;
+ struct nvo_block nvo;
+};
+
+/* Tuning Parameters */
+#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
+#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */
+#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */
+#define TX_DMA_BURST 4 /* Calculate as 16<<val. */
+#define TX_IPG 3 /* This is the only valid value */
+#define RX_BUF_LEN_IDX 0 /* 0, 1, 2 is allowed - 8,16,32K rx buffer */
+#define RX_BUF_LEN ( (8192 << RX_BUF_LEN_IDX) )
+#define RX_BUF_PAD 4
+
+/* Symbolic offsets to registers. */
+enum RTL8139_registers {
+ MAC0=0, /* Ethernet hardware address. */
+ MAR0=8, /* Multicast filter. */
+ TxStatus0=0x10, /* Transmit status (four 32bit registers). */
+ TxAddr0=0x20, /* Tx descriptors (also four 32bit). */
+ RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
+ ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
+ IntrMask=0x3C, IntrStatus=0x3E,
+ TxConfig=0x40, RxConfig=0x44,
+ Timer=0x48, /* general-purpose counter. */
+ RxMissed=0x4C, /* 24 bits valid, write clears. */
+ Cfg9346=0x50, Config0=0x51, Config1=0x52,
+ TimerIntrReg=0x54, /* intr if gp counter reaches this value */
+ MediaStatus=0x58,
+ Config3=0x59,
+ MultiIntr=0x5C,
+ RevisionID=0x5E, /* revision of the RTL8139 chip */
+ TxSummary=0x60,
+ MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68,
+ NWayExpansion=0x6A,
+ DisconnectCnt=0x6C, FalseCarrierCnt=0x6E,
+ NWayTestReg=0x70,
+ RxCnt=0x72, /* packet received counter */
+ CSCR=0x74, /* chip status and configuration register */
+ PhyParm1=0x78,TwisterParm=0x7c,PhyParm2=0x80, /* undocumented */
+ /* from 0x84 onwards are a number of power management/wakeup frame
+ * definitions we will probably never need to know about. */
+};
+
+enum RxEarlyStatusBits {
+ ERGood=0x08, ERBad=0x04, EROVW=0x02, EROK=0x01
+};
+
+enum ChipCmdBits {
+ CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, };
+
+enum IntrMaskBits {
+ SERR=0x8000, TimeOut=0x4000, LenChg=0x2000,
+ FOVW=0x40, PUN_LinkChg=0x20, RXOVW=0x10,
+ TER=0x08, TOK=0x04, RER=0x02, ROK=0x01
+};
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatusBits {
+ PCIErr=0x8000, PCSTimeout=0x4000, CableLenChange= 0x2000,
+ RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10,
+ TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01,
+};
+enum TxStatusBits {
+ TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000,
+ TxOutOfWindow=0x20000000, TxAborted=0x40000000,
+ TxCarrierLost=0x80000000,
+};
+enum RxStatusBits {
+ RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000,
+ RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004,
+ RxBadAlign=0x0002, RxStatusOK=0x0001,
+};
+
+enum MediaStatusBits {
+ MSRTxFlowEnable=0x80, MSRRxFlowEnable=0x40, MSRSpeed10=0x08,
+ MSRLinkFail=0x04, MSRRxPauseFlag=0x02, MSRTxPauseFlag=0x01,
+};
+
+enum MIIBMCRBits {
+ BMCRReset=0x8000, BMCRSpeed100=0x2000, BMCRNWayEnable=0x1000,
+ BMCRRestartNWay=0x0200, BMCRDuplex=0x0100,
+};
+
+enum CSCRBits {
+ CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
+ CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
+ CSCR_LinkDownCmd=0x0f3c0,
+};
+
+enum RxConfigBits {
+ RxCfgWrap=0x80,
+ Eeprom9356=0x40,
+ AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08,
+ AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
+};
+
+enum Config1Bits {
+ VPDEnable=0x02,
+};
+
+/* EEPROM access */
+#define EE_M1 0x80 /* Mode select bit 1 */
+#define EE_M0 0x40 /* Mode select bit 0 */
+#define EE_CS 0x08 /* EEPROM chip select */
+#define EE_SK 0x04 /* EEPROM shift clock */
+#define EE_DI 0x02 /* Data in */
+#define EE_DO 0x01 /* Data out */
+
+/* Offsets within EEPROM (these are word offsets) */
+#define EE_MAC 7
+
+static const uint8_t rtl_ee_bits[] = {
+ [SPI_BIT_SCLK] = EE_SK,
+ [SPI_BIT_MOSI] = EE_DI,
+ [SPI_BIT_MISO] = EE_DO,
+ [SPI_BIT_SS(0)] = ( EE_CS | EE_M1 ),
+};
+
+static int rtl_spi_read_bit ( struct bit_basher *basher,
+ unsigned int bit_id ) {
+ struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic,
+ spibit.basher );
+ uint8_t mask = rtl_ee_bits[bit_id];
+ uint8_t eereg;
+
+ eereg = inb ( rtl->ioaddr + Cfg9346 );
+ return ( eereg & mask );
+}
+
+static void rtl_spi_write_bit ( struct bit_basher *basher,
+ unsigned int bit_id, unsigned long data ) {
+ struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic,
+ spibit.basher );
+ uint8_t mask = rtl_ee_bits[bit_id];
+ uint8_t eereg;
+
+ eereg = inb ( rtl->ioaddr + Cfg9346 );
+ eereg &= ~mask;
+ eereg |= ( data & mask );
+ outb ( eereg, rtl->ioaddr + Cfg9346 );
+}
+
+static struct bit_basher_operations rtl_basher_ops = {
+ .read = rtl_spi_read_bit,
+ .write = rtl_spi_write_bit,
+};
+
+/** Portion of EEPROM available for non-volatile stored options
+ *
+ * We use offset 0x40 (i.e. address 0x20), length 0x40. This block is
+ * marked as VPD in the rtl8139 datasheets, so we use it only if we
+ * detect that the card is not supporting VPD.
+ */
+static struct nvo_fragment rtl_nvo_fragments[] = {
+ { 0x20, 0x40 },
+ { 0, 0 }
+};
+
+/**
+ * Set up for EEPROM access
+ *
+ * @v netdev Net device
+ */
+static void rtl_init_eeprom ( struct net_device *netdev ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+ int ee9356;
+ int vpd;
+
+ /* Initialise three-wire bus */
+ rtl->spibit.basher.op = &rtl_basher_ops;
+ rtl->spibit.bus.mode = SPI_MODE_THREEWIRE;
+ init_spi_bit_basher ( &rtl->spibit );
+
+ /* Detect EEPROM type and initialise three-wire device */
+ ee9356 = ( inw ( rtl->ioaddr + RxConfig ) & Eeprom9356 );
+ if ( ee9356 ) {
+ DBGC ( rtl, "rtl8139 %p EEPROM is an AT93C56\n", rtl );
+ init_at93c56 ( &rtl->eeprom, 16 );
+ } else {
+ DBGC ( rtl, "rtl8139 %p EEPROM is an AT93C46\n", rtl );
+ init_at93c46 ( &rtl->eeprom, 16 );
+ }
+ rtl->eeprom.bus = &rtl->spibit.bus;
+
+ /* Initialise space for non-volatile options, if available */
+ vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable );
+ if ( vpd ) {
+ DBGC ( rtl, "rtl8139 %p EEPROM in use for VPD; cannot use "
+ "for options\n", rtl );
+ } else {
+ nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, rtl_nvo_fragments,
+ &netdev->refcnt );
+ }
+}
+
+/**
+ * Reset NIC
+ *
+ * @v netdev Net device
+ *
+ * Issues a hardware reset and waits for the reset to complete.
+ */
+static void rtl_reset ( struct net_device *netdev ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+
+ /* Reset chip */
+ outb ( CmdReset, rtl->ioaddr + ChipCmd );
+ mdelay ( 10 );
+ memset ( &rtl->tx, 0, sizeof ( rtl->tx ) );
+ rtl->rx.offset = 0;
+}
+
+/**
+ * Open NIC
+ *
+ * @v netdev Net device
+ * @ret rc Return status code
+ */
+static int rtl_open ( struct net_device *netdev ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+ int i;
+
+ /* Program the MAC address */
+ for ( i = 0 ; i < ETH_ALEN ; i++ )
+ outb ( netdev->ll_addr[i], rtl->ioaddr + MAC0 + i );
+
+ /* Set up RX ring */
+ rtl->rx.ring = malloc ( RX_BUF_LEN + RX_BUF_PAD );
+ if ( ! rtl->rx.ring )
+ return -ENOMEM;
+ outl ( virt_to_bus ( rtl->rx.ring ), rtl->ioaddr + RxBuf );
+ DBGC ( rtl, "rtl8139 %p RX ring at %lx\n",
+ rtl, virt_to_bus ( rtl->rx.ring ) );
+
+ /* Enable TX and RX */
+ outb ( ( CmdRxEnb | CmdTxEnb ), rtl->ioaddr + ChipCmd );
+ outl ( ( ( RX_FIFO_THRESH << 13 ) | ( RX_BUF_LEN_IDX << 11 ) |
+ ( RX_DMA_BURST << 8 ) | AcceptBroadcast | AcceptMulticast |
+ AcceptMyPhys ), rtl->ioaddr + RxConfig );
+ outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 0 );
+ outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 4 );
+ outl ( ( ( TX_DMA_BURST << 8 ) | ( TX_IPG << 24 ) ),
+ rtl->ioaddr + TxConfig );
+
+ return 0;
+}
+
+/**
+ * Close NIC
+ *
+ * @v netdev Net device
+ */
+static void rtl_close ( struct net_device *netdev ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+
+ /* Reset the hardware to disable everything in one go */
+ rtl_reset ( netdev );
+
+ /* Free RX ring */
+ free ( rtl->rx.ring );
+ rtl->rx.ring = NULL;
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int rtl_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+
+ /* Check for space in TX ring */
+ if ( rtl->tx.iobuf[rtl->tx.next] != NULL ) {
+ DBGC ( rtl, "rtl8139 %p TX overflow\n", rtl );
+ return -ENOBUFS;
+ }
+
+ /* Pad and align packet */
+ iob_pad ( iobuf, ETH_ZLEN );
+
+ /* Add to TX ring */
+ DBGC2 ( rtl, "rtl8139 %p TX id %d at %lx+%zx\n", rtl, rtl->tx.next,
+ virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
+ rtl->tx.iobuf[rtl->tx.next] = iobuf;
+ outl ( virt_to_bus ( iobuf->data ),
+ rtl->ioaddr + TxAddr0 + 4 * rtl->tx.next );
+ outl ( ( ( ( TX_FIFO_THRESH & 0x7e0 ) << 11 ) | iob_len ( iobuf ) ),
+ rtl->ioaddr + TxStatus0 + 4 * rtl->tx.next );
+ rtl->tx.next = ( rtl->tx.next + 1 ) % TX_RING_SIZE;
+
+ return 0;
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void rtl_poll ( struct net_device *netdev ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+ unsigned int status;
+ unsigned int tsad;
+ unsigned int rx_status;
+ unsigned int rx_len;
+ struct io_buffer *rx_iob;
+ int wrapped_len;
+ int i;
+
+ /* Acknowledge interrupts */
+ status = inw ( rtl->ioaddr + IntrStatus );
+ if ( ! status )
+ return;
+ outw ( status, rtl->ioaddr + IntrStatus );
+
+ /* Handle TX completions */
+ tsad = inw ( rtl->ioaddr + TxSummary );
+ for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
+ if ( ( rtl->tx.iobuf[i] != NULL ) && ( tsad & ( 1 << i ) ) ) {
+ DBGC2 ( rtl, "rtl8139 %p TX id %d complete\n",
+ rtl, i );
+ netdev_tx_complete ( netdev, rtl->tx.iobuf[i] );
+ rtl->tx.iobuf[i] = NULL;
+ }
+ }
+
+ /* Handle received packets */
+ while ( ! ( inw ( rtl->ioaddr + ChipCmd ) & RxBufEmpty ) ) {
+ rx_status = * ( ( uint16_t * )
+ ( rtl->rx.ring + rtl->rx.offset ) );
+ rx_len = * ( ( uint16_t * )
+ ( rtl->rx.ring + rtl->rx.offset + 2 ) );
+ if ( rx_status & RxOK ) {
+ DBGC2 ( rtl, "rtl8139 %p RX packet at offset "
+ "%x+%x\n", rtl, rtl->rx.offset, rx_len );
+
+ rx_iob = alloc_iob ( rx_len );
+ if ( ! rx_iob ) {
+ netdev_rx_err ( netdev, NULL, -ENOMEM );
+ /* Leave packet for next call to poll() */
+ break;
+ }
+
+ wrapped_len = ( ( rtl->rx.offset + 4 + rx_len )
+ - RX_BUF_LEN );
+ if ( wrapped_len < 0 )
+ wrapped_len = 0;
+
+ memcpy ( iob_put ( rx_iob, rx_len - wrapped_len ),
+ rtl->rx.ring + rtl->rx.offset + 4,
+ rx_len - wrapped_len );
+ memcpy ( iob_put ( rx_iob, wrapped_len ),
+ rtl->rx.ring, wrapped_len );
+
+ netdev_rx ( netdev, rx_iob );
+ } else {
+ DBGC ( rtl, "rtl8139 %p RX bad packet (status %#04x "
+ "len %d)\n", rtl, rx_status, rx_len );
+ netdev_rx_err ( netdev, NULL, -EINVAL );
+ }
+ rtl->rx.offset = ( ( ( rtl->rx.offset + 4 + rx_len + 3 ) & ~3 )
+ % RX_BUF_LEN );
+ outw ( rtl->rx.offset - 16, rtl->ioaddr + RxBufPtr );
+ }
+}
+
+/**
+ * Enable/disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+static void rtl_irq ( struct net_device *netdev, int enable ) {
+ struct rtl8139_nic *rtl = netdev->priv;
+
+ DBGC ( rtl, "rtl8139 %p interrupts %s\n",
+ rtl, ( enable ? "enabled" : "disabled" ) );
+ outw ( ( enable ? ( ROK | RER | TOK | TER ) : 0 ),
+ rtl->ioaddr + IntrMask );
+}
+
+/** RTL8139 net device operations */
+static struct net_device_operations rtl_operations = {
+ .open = rtl_open,
+ .close = rtl_close,
+ .transmit = rtl_transmit,
+ .poll = rtl_poll,
+ .irq = rtl_irq,
+};
+
+/**
+ * Probe PCI device
+ *
+ * @v pci PCI device
+ * @v id PCI ID
+ * @ret rc Return status code
+ */
+static int rtl_probe ( struct pci_device *pci,
+ const struct pci_device_id *id __unused ) {
+ struct net_device *netdev;
+ struct rtl8139_nic *rtl;
+ int rc;
+
+ /* Allocate net device */
+ netdev = alloc_etherdev ( sizeof ( *rtl ) );
+ if ( ! netdev )
+ return -ENOMEM;
+ netdev_init ( netdev, &rtl_operations );
+ rtl = netdev->priv;
+ pci_set_drvdata ( pci, netdev );
+ netdev->dev = &pci->dev;
+ memset ( rtl, 0, sizeof ( *rtl ) );
+ rtl->ioaddr = pci->ioaddr;
+
+ /* Fix up PCI device */
+ adjust_pci_device ( pci );
+
+ /* Reset the NIC, set up EEPROM access and read MAC address */
+ rtl_reset ( netdev );
+ rtl_init_eeprom ( netdev );
+ nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->hw_addr, ETH_ALEN );
+
+ /* Mark as link up; we don't yet handle link state */
+ netdev_link_up ( netdev );
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+
+ /* Register non-volatile storage */
+ if ( rtl->nvo.nvs ) {
+ if ( ( rc = register_nvo ( &rtl->nvo,
+ netdev_settings ( netdev ) ) ) != 0)
+ goto err_register_nvo;
+ }
+
+ return 0;
+
+ err_register_nvo:
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ rtl_reset ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ return rc;
+}
+
+/**
+ * Remove PCI device
+ *
+ * @v pci PCI device
+ */
+static void rtl_remove ( struct pci_device *pci ) {
+ struct net_device *netdev = pci_get_drvdata ( pci );
+ struct rtl8139_nic *rtl = netdev->priv;
+
+ if ( rtl->nvo.nvs )
+ unregister_nvo ( &rtl->nvo );
+ unregister_netdev ( netdev );
+ rtl_reset ( netdev );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+static struct pci_device_id rtl8139_nics[] = {
+PCI_ROM(0x10ec, 0x8129, "rtl8129", "Realtek 8129", 0),
+PCI_ROM(0x10ec, 0x8139, "rtl8139", "Realtek 8139", 0),
+PCI_ROM(0x10ec, 0x8138, "rtl8139b", "Realtek 8139B", 0),
+PCI_ROM(0x1186, 0x1300, "dfe538", "DFE530TX+/DFE538TX", 0),
+PCI_ROM(0x1113, 0x1211, "smc1211-1", "SMC EZ10/100", 0),
+PCI_ROM(0x1112, 0x1211, "smc1211", "SMC EZ10/100", 0),
+PCI_ROM(0x1500, 0x1360, "delta8139", "Delta Electronics 8139", 0),
+PCI_ROM(0x4033, 0x1360, "addtron8139", "Addtron Technology 8139", 0),
+PCI_ROM(0x1186, 0x1340, "dfe690txd", "D-Link DFE690TXD", 0),
+PCI_ROM(0x13d1, 0xab06, "fe2000vx", "AboCom FE2000VX", 0),
+PCI_ROM(0x1259, 0xa117, "allied8139", "Allied Telesyn 8139", 0),
+PCI_ROM(0x14ea, 0xab06, "fnw3603tx", "Planex FNW-3603-TX", 0),
+PCI_ROM(0x14ea, 0xab07, "fnw3800tx", "Planex FNW-3800-TX", 0),
+PCI_ROM(0xffff, 0x8139, "clone-rtl8139", "Cloned 8139", 0),
+};
+
+struct pci_driver rtl8139_driver __pci_driver = {
+ .ids = rtl8139_nics,
+ .id_count = ( sizeof ( rtl8139_nics ) / sizeof ( rtl8139_nics[0] ) ),
+ .probe = rtl_probe,
+ .remove = rtl_remove,
+};
+
+GRUB_MOD_LICENSE("GPLv2+");
+
+GRUB_MOD_INIT(gpxe_rtl8139)
+{
+ grub_gpxe_register_pci_nic (&rtl8139_driver);
+}
+
+GRUB_MOD_FINI(gpxe_rtl8139)
+{
+ grub_gpxe_unregister_pci_nic (&rtl8139_driver);
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.c
new file mode 100644
index 0000000..da14a09
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.c
@@ -0,0 +1,1304 @@
+/* -*- Mode:C; c-basic-offset:4; -*- */
+
+/*
+ sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot
+ Copyright (C) 2001 Entity Cyber, Inc.
+
+ Revision: 1.0 March 1, 2001
+
+ Author: Marty Connor (mdc@etherboot.org)
+
+ Adapted from a Linux driver which was written by Donald Becker
+ and modified by Ollie Lho and Chin-Shan Li of SiS Corporation.
+ Rewritten for Etherboot by Marty Connor.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License (GPL), incorporated herein by reference.
+
+ References:
+ SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
+ preliminary Rev. 1.0 Jan. 14, 1998
+ SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
+ preliminary Rev. 1.0 Nov. 10, 1998
+ SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
+ preliminary Rev. 1.0 Jan. 18, 1998
+ http://www.sis.com.tw/support/databook.htm */
+
+FILE_LICENCE ( GPL_ANY );
+
+/* Revision History */
+
+/*
+ 07 Dec 2003 timlegge - Enabled Multicast Support
+ 06 Dec 2003 timlegge - Fixed relocation issue in 5.2
+ 04 Jan 2002 Chien-Yu Chen, Doug Ambrisko, Marty Connor Patch to Etherboot 5.0.5
+ Added support for the SiS 630ET plus various bug fixes from linux kernel
+ source 2.4.17.
+ 01 March 2001 mdc 1.0
+ Initial Release. Tested with PCI based sis900 card and ThinkNIC
+ computer.
+ 20 March 2001 P.Koegel
+ added support for sis630e and PHY ICS1893 and RTL8201
+ Testet with SIS730S chipset + ICS1893
+*/
+
+
+/* Includes */
+
+#include "etherboot.h"
+#include <gpxe/pci.h>
+#include "nic.h"
+
+#include "sis900.h"
+
+/* Globals */
+
+static struct nic_operations sis900_operations;
+
+static int sis900_debug = 0;
+
+static unsigned short vendor, dev_id;
+static unsigned long ioaddr;
+static u8 pci_revision;
+
+static unsigned int cur_phy;
+
+static unsigned int cur_rx;
+
+struct {
+ BufferDesc txd;
+ BufferDesc rxd[NUM_RX_DESC];
+ unsigned char txb[TX_BUF_SIZE];
+ unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
+} sis900_bufs __shared;
+#define txd sis900_bufs.txd
+#define rxd sis900_bufs.rxd
+#define txb sis900_bufs.txb
+#define rxb sis900_bufs.rxb
+
+#if 0
+static struct mac_chip_info {
+ const char *name;
+ u16 vendor_id, device_id, flags;
+ int io_size;
+} mac_chip_table[] = {
+ { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
+ PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
+ { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
+ PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
+ {0,0,0,0,0} /* 0 terminated list. */
+};
+#endif
+
+static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+static void vt6103_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
+
+static struct mii_chip_info {
+ const char * name;
+ u16 phy_id0;
+ u16 phy_id1;
+ void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
+} mii_chip_table[] = {
+ {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
+ {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
+ {"SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, sis900_read_mode},
+ {"AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, amd79c901_read_mode},
+ {"AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, amd79c901_read_mode},
+ {"ICS 1893 Integrated PHYceiver" , 0x0015, 0xf440,ics1893_read_mode},
+// {"NS 83851 PHY",0x2000, 0x5C20, MIX },
+ {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode},
+ {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode},
+ {0,0,0,0}
+};
+
+static struct mii_phy {
+ struct mii_phy * next;
+ struct mii_chip_info * chip_info;
+ int phy_addr;
+ u16 status;
+} mii;
+
+
+
+#if 0
+// PCI to ISA bridge for SIS640E access
+static struct pci_device_id pci_isa_bridge_list[] = {
+ { .vendor = 0x1039, .device = 0x0008,
+ .name = "SIS 85C503/5513 PCI to ISA bridge"},
+};
+
+PCI_DRIVER( sis_bridge_pci_driver, pci_isa_bridge_list, PCI_NO_CLASS );
+
+static struct device_driver sis_bridge_driver = {
+ .name = "SIS ISA bridge",
+ .bus_driver = &pci_driver,
+ .bus_driver_info = ( struct bus_driver_info * ) &sis_bridge_pci_driver,
+};
+#endif
+
+/* Function Prototypes */
+
+static int sis900_probe(struct nic *nic,struct pci_device *pci);
+
+static u16 sis900_read_eeprom(int location);
+static void sis900_mdio_reset(long mdio_addr);
+static void sis900_mdio_idle(long mdio_addr);
+static u16 sis900_mdio_read(int phy_id, int location);
+#if 0
+static void sis900_mdio_write(int phy_id, int location, int val);
+#endif
+static void sis900_init(struct nic *nic);
+
+static void sis900_reset(struct nic *nic);
+
+static void sis900_init_rxfilter(struct nic *nic);
+static void sis900_init_txd(struct nic *nic);
+static void sis900_init_rxd(struct nic *nic);
+static void sis900_set_rx_mode(struct nic *nic);
+static void sis900_check_mode(struct nic *nic);
+
+static void sis900_transmit(struct nic *nic, const char *d,
+ unsigned int t, unsigned int s, const char *p);
+static int sis900_poll(struct nic *nic, int retrieve);
+
+static void sis900_disable(struct nic *nic);
+
+static void sis900_irq(struct nic *nic, irq_action_t action);
+
+/**
+ * sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * Older SiS900 and friends, use EEPROM to store MAC address.
+ * MAC address is read from read_eeprom() into @net_dev->dev_addr.
+ */
+
+static int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+ u16 signature;
+ int i;
+
+ /* check to see if we have sane EEPROM */
+ signature = (u16) sis900_read_eeprom( EEPROMSignature);
+ if (signature == 0xffff || signature == 0x0000) {
+ printf ("sis900_probe: Error EERPOM read %hX\n", signature);
+ return 0;
+ }
+
+ /* get MAC address from EEPROM */
+ for (i = 0; i < 3; i++)
+ ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
+ return 1;
+}
+
+/**
+ * sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
+ * is shared by
+ * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
+ * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
+ * by LAN, otherwise is not. After MAC address is read from EEPROM, send
+ * EEDONE signal to refuse EEPROM access by LAN.
+ * The EEPROM map of SiS962 or SiS963 is different to SiS900.
+ * The signature field in SiS962 or SiS963 spec is meaningless.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+
+static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+/* long ioaddr = net_dev->base_addr; */
+ long ee_addr = ioaddr + mear;
+ u32 waittime = 0;
+ int i;
+
+ printf("Alternate function\n");
+
+ outl(EEREQ, ee_addr);
+ while(waittime < 2000) {
+ if(inl(ee_addr) & EEGNT) {
+
+ /* get MAC address from EEPROM */
+ for (i = 0; i < 3; i++)
+ ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
+
+ outl(EEDONE, ee_addr);
+ return 1;
+ } else {
+ udelay(1);
+ waittime ++;
+ }
+ }
+ outl(EEDONE, ee_addr);
+ return 0;
+}
+
+/**
+ * sis630e_get_mac_addr: - Get MAC address for SiS630E model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * SiS630E model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+
+static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+#if 0
+ u8 reg;
+ int i;
+ struct bus_loc bus_loc;
+ union {
+ struct bus_dev bus_dev;
+ struct pci_device isa_bridge;
+ } u;
+
+ /* find PCI to ISA bridge */
+ memset(&bus_loc, 0, sizeof(bus_loc));
+ if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
+ return 0;
+
+ pci_read_config_byte(&u.isa_bridge, 0x48, &reg);
+ pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ {
+ outb(0x09 + i, 0x70);
+ ((u8 *)(nic->node_addr))[i] = inb(0x71);
+ }
+ pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
+
+ return 1;
+#endif
+
+ /* Does not work with current bus/device model */
+ memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) );
+ return 0;
+}
+
+/**
+ * sis630e_get_mac_addr: - Get MAC address for SiS630E model
+ * @pci_dev: the sis900 pci device
+ * @net_dev: the net device to get address for
+ *
+ * SiS630E model, use APC CMOS RAM to store MAC address.
+ * APC CMOS RAM is accessed through ISA bridge.
+ * MAC address is read into @net_dev->dev_addr.
+ */
+
+static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
+{
+ u32 rfcrSave;
+ u32 i;
+
+
+ rfcrSave = inl(rfcr + ioaddr);
+
+ outl(rfcrSave | RELOAD, ioaddr + cr);
+ outl(0, ioaddr + cr);
+
+ /* disable packet filtering before setting filter */
+ outl(rfcrSave & ~RFEN, rfcr + ioaddr);
+
+ /* load MAC addr to filter data register */
+ for (i = 0 ; i < 3 ; i++) {
+ outl((i << RFADDR_shift), ioaddr + rfcr);
+ *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr);
+ }
+
+ /* enable packet filitering */
+ outl(rfcrSave | RFEN, rfcr + ioaddr);
+
+ return 1;
+}
+
+/*
+ * Function: sis900_probe
+ *
+ * Description: initializes initializes the NIC, retrieves the
+ * MAC address of the card, and sets up some globals required by
+ * other routines.
+ *
+ * Side effects:
+ * leaves the ioaddress of the sis900 chip in the variable ioaddr.
+ * leaves the sis900 initialized, and ready to recieve packets.
+ *
+ * Returns: struct nic *: pointer to NIC data structure
+ */
+
+static int sis900_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ int i;
+ int found=0;
+ int phy_addr;
+ u8 revision;
+ int ret;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ ioaddr = pci->ioaddr;
+ vendor = pci->vendor;
+ dev_id = pci->device;
+
+ /* wakeup chip */
+ pci_write_config_dword(pci, 0x40, 0x00000000);
+
+ adjust_pci_device(pci);
+
+ /* get MAC address */
+ ret = 0;
+ pci_read_config_byte(pci, PCI_REVISION, &revision);
+
+ /* save for use later in sis900_reset() */
+ pci_revision = revision;
+
+ if (revision == SIS630E_900_REV)
+ ret = sis630e_get_mac_addr(pci, nic);
+ else if ((revision > 0x81) && (revision <= 0x90))
+ ret = sis635_get_mac_addr(pci, nic);
+ else if (revision == SIS96x_900_REV)
+ ret = sis96x_get_mac_addr(pci, nic);
+ else
+ ret = sis900_get_mac_addr(pci, nic);
+
+ if (ret == 0)
+ {
+ printf ("sis900_probe: Error MAC address not found\n");
+ return 0;
+ }
+
+ /* 630ET : set the mii access mode as software-mode */
+ if (revision == SIS630ET_900_REV)
+ outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
+
+ DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id );
+
+ /* probe for mii transceiver */
+ /* search for total of 32 possible mii phy addresses */
+
+ found = 0;
+ for (phy_addr = 0; phy_addr < 32; phy_addr++) {
+ u16 mii_status;
+ u16 phy_id0, phy_id1;
+
+ mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
+ if (mii_status == 0xffff || mii_status == 0x0000)
+ /* the mii is not accessable, try next one */
+ continue;
+
+ phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
+ phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
+
+ /* search our mii table for the current mii */
+ for (i = 0; mii_chip_table[i].phy_id1; i++) {
+
+ if ((phy_id0 == mii_chip_table[i].phy_id0) &&
+ ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
+
+ printf("sis900_probe: %s transceiver found at address %d.\n",
+ mii_chip_table[i].name, phy_addr);
+
+ mii.chip_info = &mii_chip_table[i];
+ mii.phy_addr = phy_addr;
+ mii.status = sis900_mdio_read(phy_addr, MII_STATUS);
+ mii.next = NULL;
+
+ found=1;
+ break;
+ }
+ }
+ }
+
+ if (found == 0) {
+ printf("sis900_probe: No MII transceivers found!\n");
+ return 0;
+ }
+
+ /* Arbitrarily select the last PHY found as current PHY */
+ cur_phy = mii.phy_addr;
+ printf("sis900_probe: Using %s as default\n", mii.chip_info->name);
+
+ /* initialize device */
+ sis900_init(nic);
+ nic->nic_op = &sis900_operations;
+
+ return 1;
+}
+
+
+
+
+/*
+ * EEPROM Routines: These functions read and write to EEPROM for
+ * retrieving the MAC address and other configuration information about
+ * the card.
+ */
+
+/* Delay between EEPROM clock transitions. */
+#define eeprom_delay() inl(ee_addr)
+
+
+/* Function: sis900_read_eeprom
+ *
+ * Description: reads and returns a given location from EEPROM
+ *
+ * Arguments: int location: requested EEPROM location
+ *
+ * Returns: u16: contents of requested EEPROM location
+ *
+ */
+
+/* Read Serial EEPROM through EEPROM Access Register, Note that location is
+ in word (16 bits) unit */
+static u16 sis900_read_eeprom(int location)
+{
+ int i;
+ u16 retval = 0;
+ long ee_addr = ioaddr + mear;
+ u32 read_cmd = location | EEread;
+
+ outl(0, ee_addr);
+ eeprom_delay();
+ outl(EECS, ee_addr);
+ eeprom_delay();
+
+ /* Shift the read command (9) bits out. */
+ for (i = 8; i >= 0; i--) {
+ u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
+ outl(dataval, ee_addr);
+ eeprom_delay();
+ outl(dataval | EECLK, ee_addr);
+ eeprom_delay();
+ }
+ outl(EECS, ee_addr);
+ eeprom_delay();
+
+ /* read the 16-bits data in */
+ for (i = 16; i > 0; i--) {
+ outl(EECS, ee_addr);
+ eeprom_delay();
+ outl(EECS | EECLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(0, ee_addr);
+ eeprom_delay();
+// outl(EECLK, ee_addr);
+
+ return (retval);
+}
+
+#define sis900_mdio_delay() inl(mdio_addr)
+
+
+/*
+ Read and write the MII management registers using software-generated
+ serial MDIO protocol. Note that the command bits and data bits are
+ send out seperately
+*/
+
+static void sis900_mdio_idle(long mdio_addr)
+{
+ outl(MDIO | MDDIR, mdio_addr);
+ sis900_mdio_delay();
+ outl(MDIO | MDDIR | MDC, mdio_addr);
+}
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void sis900_mdio_reset(long mdio_addr)
+{
+ int i;
+
+ for (i = 31; i >= 0; i--) {
+ outl(MDDIR | MDIO, mdio_addr);
+ sis900_mdio_delay();
+ outl(MDDIR | MDIO | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ return;
+}
+
+static u16 sis900_mdio_read(int phy_id, int location)
+{
+ long mdio_addr = ioaddr + mear;
+ int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
+ u16 retval = 0;
+ int i;
+
+ sis900_mdio_reset(mdio_addr);
+ sis900_mdio_idle(mdio_addr);
+
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
+ outl(dataval, mdio_addr);
+ sis900_mdio_delay();
+ outl(dataval | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+
+ /* Read the 16 data bits. */
+ for (i = 16; i > 0; i--) {
+ outl(0, mdio_addr);
+ sis900_mdio_delay();
+ retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
+ outl(MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ outl(0x00, mdio_addr);
+ return retval;
+}
+
+#if 0
+static void sis900_mdio_write(int phy_id, int location, int value)
+{
+ long mdio_addr = ioaddr + mear;
+ int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
+ int i;
+
+ sis900_mdio_reset(mdio_addr);
+ sis900_mdio_idle(mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
+ outb(dataval, mdio_addr);
+ sis900_mdio_delay();
+ outb(dataval | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ sis900_mdio_delay();
+
+ /* Shift the value bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
+ outl(dataval, mdio_addr);
+ sis900_mdio_delay();
+ outl(dataval | MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ sis900_mdio_delay();
+
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ outb(0, mdio_addr);
+ sis900_mdio_delay();
+ outb(MDC, mdio_addr);
+ sis900_mdio_delay();
+ }
+ outl(0x00, mdio_addr);
+ return;
+}
+#endif
+
+
+/* Function: sis900_init
+ *
+ * Description: resets the ethernet controller chip and various
+ * data structures required for sending and receiving packets.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * returns: void.
+ */
+
+static void
+sis900_init(struct nic *nic)
+{
+ /* Soft reset the chip. */
+ sis900_reset(nic);
+
+ sis900_init_rxfilter(nic);
+
+ sis900_init_txd(nic);
+ sis900_init_rxd(nic);
+
+ sis900_set_rx_mode(nic);
+
+ sis900_check_mode(nic);
+
+ outl(RxENA| inl(ioaddr + cr), ioaddr + cr);
+}
+
+
+/*
+ * Function: sis900_reset
+ *
+ * Description: disables interrupts and soft resets the controller chip
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_reset(struct nic *nic __unused)
+{
+ int i = 0;
+ u32 status = TxRCMP | RxRCMP;
+
+ outl(0, ioaddr + ier);
+ outl(0, ioaddr + imr);
+ outl(0, ioaddr + rfcr);
+
+ outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
+
+ /* Check that the chip has finished the reset. */
+ while (status && (i++ < 1000)) {
+ status ^= (inl(isr + ioaddr) & status);
+ }
+
+ if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
+ outl(PESEL | RND_CNT, ioaddr + cfg);
+ else
+ outl(PESEL, ioaddr + cfg);
+}
+
+
+/* Function: sis_init_rxfilter
+ *
+ * Description: sets receive filter address to our MAC address
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * returns: void.
+ */
+
+static void
+sis900_init_rxfilter(struct nic *nic)
+{
+ u32 rfcrSave;
+ int i;
+
+ rfcrSave = inl(rfcr + ioaddr);
+
+ /* disable packet filtering before setting filter */
+ outl(rfcrSave & ~RFEN, rfcr + ioaddr);
+
+ /* load MAC addr to filter data register */
+ for (i = 0 ; i < 3 ; i++) {
+ u32 w;
+
+ w = (u32) *((u16 *)(nic->node_addr)+i);
+ outl((i << RFADDR_shift), ioaddr + rfcr);
+ outl(w, ioaddr + rfdr);
+
+ if (sis900_debug > 0)
+ printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
+ i, inl(ioaddr + rfdr));
+ }
+
+ /* enable packet filitering */
+ outl(rfcrSave | RFEN, rfcr + ioaddr);
+}
+
+
+/*
+ * Function: sis_init_txd
+ *
+ * Description: initializes the Tx descriptor
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * returns: void.
+ */
+
+static void
+sis900_init_txd(struct nic *nic __unused)
+{
+ txd.link = (u32) 0;
+ txd.cmdsts = (u32) 0;
+ txd.bufptr = virt_to_bus(&txb[0]);
+
+ /* load Transmit Descriptor Register */
+ outl(virt_to_bus(&txd), ioaddr + txdp);
+ if (sis900_debug > 0)
+ printf("sis900_init_txd: TX descriptor register loaded with: %X\n",
+ inl(ioaddr + txdp));
+}
+
+
+/* Function: sis_init_rxd
+ *
+ * Description: initializes the Rx descriptor ring
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_init_rxd(struct nic *nic __unused)
+{
+ int i;
+
+ cur_rx = 0;
+
+ /* init RX descriptor */
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ rxd[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
+ rxd[i].cmdsts = (u32) RX_BUF_SIZE;
+ rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
+ if (sis900_debug > 0)
+ printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n",
+ i, &rxd[i], (unsigned int) rxd[i].link, (unsigned int) rxd[i].cmdsts,
+ (unsigned int) rxd[i].bufptr);
+ }
+
+ /* load Receive Descriptor Register */
+ outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);
+
+ if (sis900_debug > 0)
+ printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
+ inl(ioaddr + rxdp));
+
+}
+
+
+/* Function: sis_init_rxd
+ *
+ * Description:
+ * sets the receive mode to accept all broadcast packets and packets
+ * with our MAC address, and reject all multicast packets.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void sis900_set_rx_mode(struct nic *nic __unused)
+{
+ int i, table_entries;
+ u32 rx_mode;
+ u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
+
+ if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
+ table_entries = 16;
+ else
+ table_entries = 8;
+
+ /* accept all multicast packet */
+ rx_mode = RFAAB | RFAAM;
+ for (i = 0; i < table_entries; i++)
+ mc_filter[i] = 0xffff;
+
+ /* update Multicast Hash Table in Receive Filter */
+ for (i = 0; i < table_entries; i++) {
+ /* why plus 0x04? That makes the correct value for hash table. */
+ outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
+ outl(mc_filter[i], ioaddr + rfdr);
+ }
+
+ /* Accept Broadcast and multicast packets, destination addresses that match
+ our MAC address */
+ outl(RFEN | rx_mode, ioaddr + rfcr);
+
+ return;
+}
+
+
+/* Function: sis900_check_mode
+ *
+ * Description: checks the state of transmit and receive
+ * parameters on the NIC, and updates NIC registers to match
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_check_mode(struct nic *nic)
+{
+ int speed, duplex;
+ u32 tx_flags = 0, rx_flags = 0;
+
+ mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
+
+ if( inl(ioaddr + cfg) & EDB_MASTER_EN ) {
+ tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
+ rx_flags = DMA_BURST_64 << RxMXDMA_shift;
+ }
+ else {
+ tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
+ rx_flags = DMA_BURST_512 << RxMXDMA_shift;
+ }
+
+ if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
+ rx_flags |= (RxDRNT_10 << RxDRNT_shift);
+ tx_flags |= (TxDRNT_10 << TxDRNT_shift);
+ }
+ else {
+ rx_flags |= (RxDRNT_100 << RxDRNT_shift);
+ tx_flags |= (TxDRNT_100 << TxDRNT_shift);
+ }
+
+ if (duplex == FDX_CAPABLE_FULL_SELECTED) {
+ tx_flags |= (TxCSI | TxHBI);
+ rx_flags |= RxATX;
+ }
+
+ outl (tx_flags, ioaddr + txcfg);
+ outl (rx_flags, ioaddr + rxcfg);
+}
+
+
+/* Function: sis900_read_mode
+ *
+ * Description: retrieves and displays speed and duplex
+ * parameters from the NIC
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ int i = 0;
+ u32 status;
+ u16 phy_id0, phy_id1;
+
+ /* STSOUT register is Latched on Transition, read operation updates it */
+ do {
+ status = sis900_mdio_read(phy_addr, MII_STSOUT);
+ } while (i++ < 2);
+
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+
+ if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
+ *speed = HW_SPEED_100_MBPS;
+ if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+
+ /* Workaround for Realtek RTL8201 PHY issue */
+ phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
+ phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
+ if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){
+ if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX)
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ if(sis900_mdio_read(phy_addr, 0x0019) & 0x01)
+ *speed = HW_SPEED_100_MBPS;
+ }
+
+ if (status & MII_STSOUT_LINK_FAIL)
+ printf("sis900_read_mode: Media Link Off\n");
+ else
+ printf("sis900_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+}
+
+
+/* Function: amd79c901_read_mode
+ *
+ * Description: retrieves and displays speed and duplex
+ * parameters from the NIC
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+amd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ int i;
+ u16 status;
+
+ for (i = 0; i < 2; i++)
+ status = sis900_mdio_read(phy_addr, MII_STATUS);
+
+ if (status & MII_STAT_CAN_AUTO) {
+ /* 10BASE-T PHY */
+ for (i = 0; i < 2; i++)
+ status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
+ if (status & MII_STSSUM_SPD)
+ *speed = HW_SPEED_100_MBPS;
+ else
+ *speed = HW_SPEED_10_MBPS;
+ if (status & MII_STSSUM_DPLX)
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ else
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+
+ if (status & MII_STSSUM_LINK)
+ printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("amd79c901_read_mode: Media Link Off\n");
+ }
+ else {
+ /* HomePNA */
+ *speed = HW_SPEED_HOME;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ if (status & MII_STAT_LINK)
+ printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
+ else
+ printf("amd79c901_read_mode: Media Link Off\n");
+ }
+}
+
+
+/**
+ * ics1893_read_mode: - read media mode for ICS1893 PHY
+ * @net_dev: the net device to read mode for
+ * @phy_addr: mii phy address
+ * @speed: the transmit speed to be determined
+ * @duplex: the duplex mode to be determined
+ *
+ * ICS1893 PHY use Quick Poll Detailed Status register
+ * to determine the speed and duplex mode for sis900
+ */
+
+static void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ int i = 0;
+ u32 status;
+
+ /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
+ for (i = 0; i < 2; i++)
+ status = sis900_mdio_read(phy_addr, MII_QPDSTS);
+
+ if (status & MII_STSICS_SPD)
+ *speed = HW_SPEED_100_MBPS;
+ else
+ *speed = HW_SPEED_10_MBPS;
+
+ if (status & MII_STSICS_DPLX)
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ else
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+
+ if (status & MII_STSICS_LINKSTS)
+ printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("ics1893_read_mode: Media Link Off\n");
+}
+
+/**
+ * rtl8201_read_mode: - read media mode for rtl8201 phy
+ * @nic: the net device to read mode for
+ * @phy_addr: mii phy address
+ * @speed: the transmit speed to be determined
+ * @duplex: the duplex mode to be determined
+ *
+ * read MII_STATUS register from rtl8201 phy
+ * to determine the speed and duplex mode for sis900
+ */
+
+static void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ u32 status;
+
+ status = sis900_mdio_read(phy_addr, MII_STATUS);
+
+ if (status & MII_STAT_CAN_TX_FDX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_TX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T_FDX) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+
+ if (status & MII_STAT_LINK)
+ printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("rtl8201_read_config_mode: Media Link Off\n");
+}
+
+/**
+ * vt6103_read_mode: - read media mode for vt6103 phy
+ * @nic: the net device to read mode for
+ * @phy_addr: mii phy address
+ * @speed: the transmit speed to be determined
+ * @duplex: the duplex mode to be determined
+ *
+ * read MII_STATUS register from rtl8201 phy
+ * to determine the speed and duplex mode for sis900
+ */
+
+static void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
+{
+ u32 status;
+
+ status = sis900_mdio_read(phy_addr, MII_STATUS);
+
+ if (status & MII_STAT_CAN_TX_FDX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_TX) {
+ *speed = HW_SPEED_100_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T_FDX) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_FULL_SELECTED;
+ }
+ else if (status & MII_STAT_CAN_T) {
+ *speed = HW_SPEED_10_MBPS;
+ *duplex = FDX_CAPABLE_HALF_SELECTED;
+ }
+
+ if (status & MII_STAT_LINK)
+ printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
+ *speed == HW_SPEED_100_MBPS ?
+ "100mbps" : "10mbps",
+ *duplex == FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ else
+ printf("vt6103_read_config_mode: Media Link Off\n");
+}
+
+/* Function: sis900_transmit
+ *
+ * Description: transmits a packet and waits for completion or timeout.
+ *
+ * Arguments: char d[6]: destination ethernet address.
+ * unsigned short t: ethernet protocol type.
+ * unsigned short s: size of the data-part of the packet.
+ * char *p: the data for the packet.
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_transmit(struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ u32 to, nstype;
+ volatile u32 tx_status;
+
+ /* Stop the transmitter */
+ outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);
+
+ /* load Transmit Descriptor Register */
+ outl(virt_to_bus(&txd), ioaddr + txdp);
+ if (sis900_debug > 1)
+ printf("sis900_transmit: TX descriptor register loaded with: %X\n",
+ inl(ioaddr + txdp));
+
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons(t);
+ memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= DSIZE;
+
+ if (sis900_debug > 1)
+ printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
+
+ /* pad to minimum packet size */
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+ /* set the transmit buffer descriptor and enable Transmit State Machine */
+ txd.bufptr = virt_to_bus(&txb[0]);
+ txd.cmdsts = (u32) OWN | s;
+
+ /* restart the transmitter */
+ outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
+
+ if (sis900_debug > 1)
+ printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
+
+ to = currticks() + TX_TIMEOUT;
+
+ while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ printf("sis900_transmit: TX Timeout! Tx status %X.\n",
+ (unsigned int) tx_status);
+ }
+
+ if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
+ /* packet unsuccessfully transmited */
+ printf("sis900_transmit: Transmit error, Tx status %X.\n",
+ (unsigned int) tx_status);
+ }
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0, ioaddr + imr);
+}
+
+
+/* Function: sis900_poll
+ *
+ * Description: checks for a received packet and returns it if found.
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: 1 if a packet was recieved.
+ * 0 if no pacet was recieved.
+ *
+ * Side effects:
+ * Returns (copies) the packet to the array nic->packet.
+ * Returns the length of the packet in nic->packetlen.
+ */
+
+static int
+sis900_poll(struct nic *nic, int retrieve)
+{
+ u32 rx_status = rxd[cur_rx].cmdsts;
+ u32 intr_status;
+ int retstat = 0;
+
+ /* acknowledge interrupts by reading interrupt status register */
+ intr_status = inl(ioaddr + isr);
+
+ if (sis900_debug > 2)
+ printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx,
+ (unsigned int) rx_status);
+
+ if (!(rx_status & OWN))
+ return retstat;
+
+ if (sis900_debug > 1)
+ printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
+ cur_rx, (unsigned int) rx_status);
+
+ if ( ! retrieve ) return 1;
+
+ nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
+
+ if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
+ /* corrupted packet received */
+ printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
+ (unsigned int) rx_status);
+ retstat = 0;
+ } else {
+ /* give packet to higher level routine */
+ memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
+ retstat = 1;
+ }
+
+ /* return the descriptor and buffer to receive ring */
+ rxd[cur_rx].cmdsts = RX_BUF_SIZE;
+ rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
+
+ if (++cur_rx == NUM_RX_DESC)
+ cur_rx = 0;
+
+ /* re-enable the potentially idle receive state machine */
+ outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
+
+ return retstat;
+
+}
+
+
+/* Function: sis900_disable
+ *
+ * Description: Turns off interrupts and stops Tx and Rx engines
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_disable ( struct nic *nic ) {
+
+ sis900_init(nic);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0, ioaddr + imr);
+ outl(0, ioaddr + ier);
+
+ /* Stop the chip's Tx and Rx Status Machine */
+ outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
+}
+
+
+/* Function: sis900_irq
+ *
+ * Description: Enable, Disable, or Force, interrupts
+ *
+ * Arguments: struct nic *nic: NIC data structure
+ * irq_action_t action: Requested action
+ *
+ * Returns: void.
+ */
+
+static void
+sis900_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ outl(0, ioaddr + imr);
+ break;
+ case ENABLE :
+ outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations sis900_operations = {
+ .connect = dummy_connect,
+ .poll = sis900_poll,
+ .transmit = sis900_transmit,
+ .irq = sis900_irq,
+};
+
+static struct pci_device_id sis900_nics[] = {
+PCI_ROM(0x1039, 0x0900, "sis900", "SIS900", 0),
+PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0),
+};
+
+PCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS );
+
+DRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver,
+ sis900_probe, sis900_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.h
new file mode 100644
index 0000000..7a5c6b5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/sis900.h
@@ -0,0 +1,375 @@
+/* -*- Mode:C; c-basic-offset:4; -*- */
+
+/* Definitions for SiS ethernet controllers including 7014/7016 and 900
+ * References:
+ * SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
+ * preliminary Rev. 1.0 Jan. 14, 1998
+ * SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
+ * preliminary Rev. 1.0 Nov. 10, 1998
+ * SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
+ * preliminary Rev. 1.0 Jan. 18, 1998
+ * http://www.sis.com.tw/support/databook.htm
+ */
+
+FILE_LICENCE ( GPL_ANY );
+
+/* MAC operationl registers of SiS 7016 and SiS 900 ethernet controller */
+/* The I/O extent, SiS 900 needs 256 bytes of io address */
+#define SIS900_TOTAL_SIZE 0x100
+
+/* Symbolic offsets to registers. */
+enum sis900_registers {
+ cr=0x0, /* Command Register */
+ cfg=0x4, /* Configuration Register */
+ mear=0x8, /* EEPROM Access Register */
+ ptscr=0xc, /* PCI Test Control Register */
+ isr=0x10, /* Interrupt Status Register */
+ imr=0x14, /* Interrupt Mask Register */
+ ier=0x18, /* Interrupt Enable Register */
+ epar=0x18, /* Enhanced PHY Access Register */
+ txdp=0x20, /* Transmit Descriptor Pointer Register */
+ txcfg=0x24, /* Transmit Configuration Register */
+ rxdp=0x30, /* Receive Descriptor Pointer Register */
+ rxcfg=0x34, /* Receive Configuration Register */
+ flctrl=0x38, /* Flow Control Register */
+ rxlen=0x3c, /* Receive Packet Length Register */
+ rfcr=0x48, /* Receive Filter Control Register */
+ rfdr=0x4C, /* Receive Filter Data Register */
+ pmctrl=0xB0, /* Power Management Control Register */
+ pmer=0xB4 /* Power Management Wake-up Event Register */
+};
+
+/* Symbolic names for bits in various registers */
+enum sis900_command_register_bits {
+ RELOAD = 0x00000400,
+ ACCESSMODE = 0x00000200,
+ RESET = 0x00000100,
+ SWI = 0x00000080,
+ RxRESET = 0x00000020,
+ TxRESET = 0x00000010,
+ RxDIS = 0x00000008,
+ RxENA = 0x00000004,
+ TxDIS = 0x00000002,
+ TxENA = 0x00000001
+};
+
+enum sis900_configuration_register_bits {
+ DESCRFMT = 0x00000100, /* 7016 specific */
+ REQALG = 0x00000080,
+ SB = 0x00000040,
+ POW = 0x00000020,
+ EXD = 0x00000010,
+ PESEL = 0x00000008,
+ LPM = 0x00000004,
+ BEM = 0x00000001,
+ RND_CNT = 0x00000400,
+ FAIR_BACKOFF = 0x00000200,
+ EDB_MASTER_EN = 0x00002000
+};
+
+enum sis900_eeprom_access_reigster_bits {
+ MDC = 0x00000040,
+ MDDIR = 0x00000020,
+ MDIO = 0x00000010, /* 7016 specific */
+ EECS = 0x00000008,
+ EECLK = 0x00000004,
+ EEDO = 0x00000002,
+ EEDI = 0x00000001
+};
+
+enum sis900_interrupt_register_bits {
+ WKEVT = 0x10000000,
+ TxPAUSEEND = 0x08000000,
+ TxPAUSE = 0x04000000,
+ TxRCMP = 0x02000000,
+ RxRCMP = 0x01000000,
+ DPERR = 0x00800000,
+ SSERR = 0x00400000,
+ RMABT = 0x00200000,
+ RTABT = 0x00100000,
+ RxSOVR = 0x00010000,
+ HIBERR = 0x00008000,
+ SWINT = 0x00001000,
+ MIBINT = 0x00000800,
+ TxURN = 0x00000400,
+ TxIDLE = 0x00000200,
+ TxERR = 0x00000100,
+ TxDESC = 0x00000080,
+ TxOK = 0x00000040,
+ RxORN = 0x00000020,
+ RxIDLE = 0x00000010,
+ RxEARLY = 0x00000008,
+ RxERR = 0x00000004,
+ RxDESC = 0x00000002,
+ RxOK = 0x00000001
+};
+
+enum sis900_interrupt_enable_reigster_bits {
+ IE = 0x00000001
+};
+
+/* maximum dma burst fro transmission and receive*/
+#define MAX_DMA_RANGE 7 /* actually 0 means MAXIMUM !! */
+#define TxMXDMA_shift 20
+#define RxMXDMA_shift 20
+#define TX_DMA_BURST 0
+#define RX_DMA_BURST 0
+
+enum sis900_tx_rx_dma{
+ DMA_BURST_512 = 0, DMA_BURST_64 = 5
+};
+
+/* transmit FIFO threshholds */
+#define TX_FILL_THRESH 16 /* 1/4 FIFO size */
+#define TxFILLT_shift 8
+#define TxDRNT_shift 0
+#define TxDRNT_100 48 /* 3/4 FIFO size */
+#define TxDRNT_10 16 /* 1/2 FIFO size */
+
+enum sis900_transmit_config_register_bits {
+ TxCSI = 0x80000000,
+ TxHBI = 0x40000000,
+ TxMLB = 0x20000000,
+ TxATP = 0x10000000,
+ TxIFG = 0x0C000000,
+ TxFILLT = 0x00003F00,
+ TxDRNT = 0x0000003F
+};
+
+/* recevie FIFO thresholds */
+#define RxDRNT_shift 1
+#define RxDRNT_100 16 /* 1/2 FIFO size */
+#define RxDRNT_10 24 /* 3/4 FIFO size */
+
+enum sis900_reveive_config_register_bits {
+ RxAEP = 0x80000000,
+ RxARP = 0x40000000,
+ RxATX = 0x10000000,
+ RxAJAB = 0x08000000,
+ RxDRNT = 0x0000007F
+};
+
+#define RFAA_shift 28
+#define RFADDR_shift 16
+
+enum sis900_receive_filter_control_register_bits {
+ RFEN = 0x80000000,
+ RFAAB = 0x40000000,
+ RFAAM = 0x20000000,
+ RFAAP = 0x10000000,
+ RFPromiscuous = (RFAAB|RFAAM|RFAAP)
+};
+
+enum sis900_reveive_filter_data_mask {
+ RFDAT = 0x0000FFFF
+};
+
+/* EEPROM Addresses */
+enum sis900_eeprom_address {
+ EEPROMSignature = 0x00,
+ EEPROMVendorID = 0x02,
+ EEPROMDeviceID = 0x03,
+ EEPROMMACAddr = 0x08,
+ EEPROMChecksum = 0x0b
+};
+
+/* The EEPROM commands include the alway-set leading bit. Refer to NM93Cxx datasheet */
+enum sis900_eeprom_command {
+ EEread = 0x0180,
+ EEwrite = 0x0140,
+ EEerase = 0x01C0,
+ EEwriteEnable = 0x0130,
+ EEwriteDisable = 0x0100,
+ EEeraseAll = 0x0120,
+ EEwriteAll = 0x0110,
+ EEaddrMask = 0x013F,
+ EEcmdShift = 16
+};
+/* For SiS962 or SiS963, request the eeprom software access */
+enum sis96x_eeprom_command {
+ EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
+};
+
+/* Manamgement Data I/O (mdio) frame */
+#define MIIread 0x6000
+#define MIIwrite 0x5002
+#define MIIpmdShift 7
+#define MIIregShift 2
+#define MIIcmdLen 16
+#define MIIcmdShift 16
+
+/* Buffer Descriptor Status*/
+enum sis900_buffer_status {
+ OWN = 0x80000000,
+ MORE = 0x40000000,
+ INTR = 0x20000000,
+ SUPCRC = 0x10000000,
+ INCCRC = 0x10000000,
+ OK = 0x08000000,
+ DSIZE = 0x00000FFF
+};
+
+/* Status for TX Buffers */
+enum sis900_tx_buffer_status {
+ ABORT = 0x04000000,
+ UNDERRUN = 0x02000000,
+ NOCARRIER = 0x01000000,
+ DEFERD = 0x00800000,
+ EXCDEFER = 0x00400000,
+ OWCOLL = 0x00200000,
+ EXCCOLL = 0x00100000,
+ COLCNT = 0x000F0000
+};
+
+enum sis900_rx_bufer_status {
+ OVERRUN = 0x02000000,
+ DEST = 0x00800000,
+ BCAST = 0x01800000,
+ MCAST = 0x01000000,
+ UNIMATCH = 0x00800000,
+ TOOLONG = 0x00400000,
+ RUNT = 0x00200000,
+ RXISERR = 0x00100000,
+ CRCERR = 0x00080000,
+ FAERR = 0x00040000,
+ LOOPBK = 0x00020000,
+ RXCOL = 0x00010000
+};
+
+/* MII register offsets */
+enum mii_registers {
+ MII_CONTROL = 0x0000,
+ MII_STATUS = 0x0001,
+ MII_PHY_ID0 = 0x0002,
+ MII_PHY_ID1 = 0x0003,
+ MII_ANADV = 0x0004,
+ MII_ANLPAR = 0x0005,
+ MII_ANEXT = 0x0006
+};
+
+/* mii registers specific to SiS 900 */
+enum sis_mii_registers {
+ MII_CONFIG1 = 0x0010,
+ MII_CONFIG2 = 0x0011,
+ MII_STSOUT = 0x0012,
+ MII_MASK = 0x0013,
+ MII_RESV = 0x0014
+};
+
+/* mii registers specific to AMD 79C901 */
+enum amd_mii_registers {
+ MII_STATUS_SUMMARY = 0x0018
+};
+
+/* mii registers specific to ICS 1893 */
+enum ics_mii_registers {
+ MII_EXTCTRL = 0x0010, MII_QPDSTS = 0x0011, MII_10BTOP = 0x0012,
+ MII_EXTCTRL2 = 0x0013
+};
+
+
+
+/* MII Control register bit definitions. */
+enum mii_control_register_bits {
+ MII_CNTL_FDX = 0x0100,
+ MII_CNTL_RST_AUTO = 0x0200,
+ MII_CNTL_ISOLATE = 0x0400,
+ MII_CNTL_PWRDWN = 0x0800,
+ MII_CNTL_AUTO = 0x1000,
+ MII_CNTL_SPEED = 0x2000,
+ MII_CNTL_LPBK = 0x4000,
+ MII_CNTL_RESET = 0x8000
+};
+
+/* MII Status register bit */
+enum mii_status_register_bits {
+ MII_STAT_EXT = 0x0001,
+ MII_STAT_JAB = 0x0002,
+ MII_STAT_LINK = 0x0004,
+ MII_STAT_CAN_AUTO = 0x0008,
+ MII_STAT_FAULT = 0x0010,
+ MII_STAT_AUTO_DONE = 0x0020,
+ MII_STAT_CAN_T = 0x0800,
+ MII_STAT_CAN_T_FDX = 0x1000,
+ MII_STAT_CAN_TX = 0x2000,
+ MII_STAT_CAN_TX_FDX = 0x4000,
+ MII_STAT_CAN_T4 = 0x8000
+};
+
+#define MII_ID1_OUI_LO 0xFC00 /* low bits of OUI mask */
+#define MII_ID1_MODEL 0x03F0 /* model number */
+#define MII_ID1_REV 0x000F /* model number */
+
+/* MII NWAY Register Bits ...
+ valid for the ANAR (Auto-Negotiation Advertisement) and
+ ANLPAR (Auto-Negotiation Link Partner) registers */
+enum mii_nway_register_bits {
+ MII_NWAY_NODE_SEL = 0x001f,
+ MII_NWAY_CSMA_CD = 0x0001,
+ MII_NWAY_T = 0x0020,
+ MII_NWAY_T_FDX = 0x0040,
+ MII_NWAY_TX = 0x0080,
+ MII_NWAY_TX_FDX = 0x0100,
+ MII_NWAY_T4 = 0x0200,
+ MII_NWAY_PAUSE = 0x0400,
+ MII_NWAY_RF = 0x2000,
+ MII_NWAY_ACK = 0x4000,
+ MII_NWAY_NP = 0x8000
+};
+
+enum mii_stsout_register_bits {
+ MII_STSOUT_LINK_FAIL = 0x4000,
+ MII_STSOUT_SPD = 0x0080,
+ MII_STSOUT_DPLX = 0x0040
+};
+
+enum mii_stsics_register_bits {
+ MII_STSICS_SPD = 0x8000, MII_STSICS_DPLX = 0x4000,
+ MII_STSICS_LINKSTS = 0x0001
+};
+
+enum mii_stssum_register_bits {
+ MII_STSSUM_LINK = 0x0008,
+ MII_STSSUM_DPLX = 0x0004,
+ MII_STSSUM_AUTO = 0x0002,
+ MII_STSSUM_SPD = 0x0001
+};
+
+enum sis900_revision_id {
+ SIS630A_900_REV = 0x80, SIS630E_900_REV = 0x81,
+ SIS630S_900_REV = 0x82, SIS630EA1_900_REV = 0x83,
+ SIS630ET_900_REV = 0x84, SIS635A_900_REV = 0x90,
+ SIS96x_900_REV = 0X91, SIS900B_900_REV = 0x03
+};
+
+enum sis630_revision_id {
+ SIS630A0 = 0x00, SIS630A1 = 0x01,
+ SIS630B0 = 0x10, SIS630B1 = 0x11
+};
+
+#define FDX_CAPABLE_DUPLEX_UNKNOWN 0
+#define FDX_CAPABLE_HALF_SELECTED 1
+#define FDX_CAPABLE_FULL_SELECTED 2
+
+#define HW_SPEED_UNCONFIG 0
+#define HW_SPEED_HOME 1
+#define HW_SPEED_10_MBPS 10
+#define HW_SPEED_100_MBPS 100
+#define HW_SPEED_DEFAULT (HW_SPEED_100_MBPS)
+
+#define CRC_SIZE 4
+#define MAC_HEADER_SIZE 14
+
+#define TX_BUF_SIZE 1536
+#define RX_BUF_SIZE 1536
+
+#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
+
+/* Time in ticks before concluding the transmitter is hung. */
+#define TX_TIMEOUT (4*TICKS_PER_SEC)
+
+typedef struct _BufferDesc {
+ u32 link;
+ volatile u32 cmdsts;
+ u32 bufptr;
+} BufferDesc;
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.c
new file mode 100644
index 0000000..cfbf104
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.c
@@ -0,0 +1,955 @@
+#ifdef ALLMULTI
+#error multicast support is not yet implemented
+#endif
+ /*------------------------------------------------------------------------
+ * smc9000.c
+ * This is a Etherboot driver for SMC's 9000 series of Ethernet cards.
+ *
+ * Copyright (C) 1998 Daniel Engström <daniel.engstrom@riksnett.no>
+ * Based on the Linux SMC9000 driver, smc9194.c by Eric Stahlman
+ * Copyright (C) 1996 by Erik Stahlman <eric@vt.edu>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * "Features" of the SMC chip:
+ * 4608 byte packet memory. ( for the 91C92/4. Others have more )
+ * EEPROM for configuration
+ * AUI/TP selection
+ *
+ * Authors
+ * Erik Stahlman <erik@vt.edu>
+ * Daniel Engström <daniel.engstrom@riksnett.no>
+ *
+ * History
+ * 98-09-25 Daniel Engström Etherboot driver crated from Eric's
+ * Linux driver.
+ *
+ *---------------------------------------------------------------------------*/
+
+FILE_LICENCE ( GPL_ANY );
+
+#define LINUX_OUT_MACROS 1
+#define SMC9000_DEBUG 0
+
+#if SMC9000_DEBUG > 1
+#define PRINTK2 printf
+#else
+#define PRINTK2(args...)
+#endif
+
+#include <gpxe/ethernet.h>
+#include <errno.h>
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/isa.h>
+#include "smc9000.h"
+
+# define _outb outb
+# define _outw outw
+
+static const char smc9000_version[] = "Version 0.99 98-09-30";
+static const char *interfaces[ 2 ] = { "TP", "AUI" };
+static const char *chip_ids[ 15 ] = {
+ NULL, NULL, NULL,
+ /* 3 */ "SMC91C90/91C92",
+ /* 4 */ "SMC91C94",
+ /* 5 */ "SMC91C95",
+ NULL,
+ /* 7 */ "SMC91C100",
+ /* 8 */ "SMC91C100FD",
+ /* 9 */ "SMC91C11xFD",
+ NULL, NULL,
+ NULL, NULL, NULL
+};
+static const char smc91c96_id[] = "SMC91C96";
+
+/*------------------------------------------------------------
+ . Reads a register from the MII Management serial interface
+ .-------------------------------------------------------------*/
+static word smc_read_phy_register(int ioaddr, byte phyaddr, byte phyreg)
+{
+ int oldBank;
+ unsigned int i;
+ byte mask;
+ word mii_reg;
+ byte bits[64];
+ int clk_idx = 0;
+ int input_idx;
+ word phydata;
+
+ // 32 consecutive ones on MDO to establish sync
+ for (i = 0; i < 32; ++i)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Start code <01>
+ bits[clk_idx++] = MII_MDOE;
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Read command <10>
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ bits[clk_idx++] = MII_MDOE;
+
+ // Output the PHY address, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyaddr & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Output the phy register number, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyreg & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Tristate and turnaround (2 bit times)
+ bits[clk_idx++] = 0;
+ //bits[clk_idx++] = 0;
+
+ // Input starts at this bit time
+ input_idx = clk_idx;
+
+ // Will input 16 bits
+ for (i = 0; i < 16; ++i)
+ bits[clk_idx++] = 0;
+
+ // Final clock bit
+ bits[clk_idx++] = 0;
+
+ // Save the current bank
+ oldBank = inw( ioaddr+BANK_SELECT );
+
+ // Select bank 3
+ SMC_SELECT_BANK(ioaddr, 3);
+
+ // Get the current MII register value
+ mii_reg = inw( ioaddr+MII_REG );
+
+ // Turn off all MII Interface bits
+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
+
+ // Clock all 64 cycles
+ for (i = 0; i < sizeof(bits); ++i)
+ {
+ // Clock Low - output data
+ outw( mii_reg | bits[i], ioaddr+MII_REG );
+ udelay(50);
+
+
+ // Clock Hi - input data
+ outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG );
+ udelay(50);
+ bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI;
+ }
+
+ // Return to idle state
+ // Set clock to low, data to low, and output tristated
+ outw( mii_reg, ioaddr+MII_REG );
+ udelay(50);
+
+ // Restore original bank select
+ SMC_SELECT_BANK(ioaddr, oldBank);
+
+ // Recover input data
+ phydata = 0;
+ for (i = 0; i < 16; ++i)
+ {
+ phydata <<= 1;
+
+ if (bits[input_idx++] & MII_MDI)
+ phydata |= 0x0001;
+ }
+
+#if (SMC_DEBUG > 2 )
+ printf("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
+ phyaddr, phyreg, phydata);
+#endif
+
+ return(phydata);
+}
+
+
+/*------------------------------------------------------------
+ . Writes a register to the MII Management serial interface
+ .-------------------------------------------------------------*/
+static void smc_write_phy_register(int ioaddr,
+ byte phyaddr, byte phyreg, word phydata)
+{
+ int oldBank;
+ unsigned int i;
+ word mask;
+ word mii_reg;
+ byte bits[65];
+ int clk_idx = 0;
+
+ // 32 consecutive ones on MDO to establish sync
+ for (i = 0; i < 32; ++i)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Start code <01>
+ bits[clk_idx++] = MII_MDOE;
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Write command <01>
+ bits[clk_idx++] = MII_MDOE;
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+
+ // Output the PHY address, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyaddr & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Output the phy register number, msb first
+ mask = (byte)0x10;
+ for (i = 0; i < 5; ++i)
+ {
+ if (phyreg & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Tristate and turnaround (2 bit times)
+ bits[clk_idx++] = 0;
+ bits[clk_idx++] = 0;
+
+ // Write out 16 bits of data, msb first
+ mask = 0x8000;
+ for (i = 0; i < 16; ++i)
+ {
+ if (phydata & mask)
+ bits[clk_idx++] = MII_MDOE | MII_MDO;
+ else
+ bits[clk_idx++] = MII_MDOE;
+
+ // Shift to next lowest bit
+ mask >>= 1;
+ }
+
+ // Final clock bit (tristate)
+ bits[clk_idx++] = 0;
+
+ // Save the current bank
+ oldBank = inw( ioaddr+BANK_SELECT );
+
+ // Select bank 3
+ SMC_SELECT_BANK(ioaddr, 3);
+
+ // Get the current MII register value
+ mii_reg = inw( ioaddr+MII_REG );
+
+ // Turn off all MII Interface bits
+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
+
+ // Clock all cycles
+ for (i = 0; i < sizeof(bits); ++i)
+ {
+ // Clock Low - output data
+ outw( mii_reg | bits[i], ioaddr+MII_REG );
+ udelay(50);
+
+
+ // Clock Hi - input data
+ outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG );
+ udelay(50);
+ bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI;
+ }
+
+ // Return to idle state
+ // Set clock to low, data to low, and output tristated
+ outw( mii_reg, ioaddr+MII_REG );
+ udelay(50);
+
+ // Restore original bank select
+ SMC_SELECT_BANK(ioaddr, oldBank);
+
+#if (SMC_DEBUG > 2 )
+ printf("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
+ phyaddr, phyreg, phydata);
+#endif
+}
+
+
+/*------------------------------------------------------------
+ . Finds and reports the PHY address
+ .-------------------------------------------------------------*/
+static int smc_detect_phy(int ioaddr, byte *pphyaddr)
+{
+ word phy_id1;
+ word phy_id2;
+ int phyaddr;
+ int found = 0;
+
+ // Scan all 32 PHY addresses if necessary
+ for (phyaddr = 0; phyaddr < 32; ++phyaddr)
+ {
+ // Read the PHY identifiers
+ phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
+ phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
+
+ // Make sure it is a valid identifier
+ if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
+ (phy_id1 > 0x0000) && (phy_id1 < 0xffff))
+ {
+ if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000))
+ {
+ // Save the PHY's address
+ *pphyaddr = phyaddr;
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ printf("No PHY found\n");
+ return(0);
+ }
+
+ // Set the PHY type
+ if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) )
+ {
+ printf("PHY=LAN83C183 (LAN91C111 Internal)\n");
+ }
+
+ if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) )
+ {
+ printf("PHY=LAN83C180\n");
+ }
+
+ return(1);
+}
+
+/*------------------------------------------------------------
+ . Configures the specified PHY using Autonegotiation. Calls
+ . smc_phy_fixed() if the user has requested a certain config.
+ .-------------------------------------------------------------*/
+static void smc_phy_configure(int ioaddr)
+{
+ int timeout;
+ byte phyaddr;
+ word my_phy_caps; // My PHY capabilities
+ word my_ad_caps; // My Advertised capabilities
+ word status;
+ int failed = 0;
+ int rpc_cur_mode = RPC_DEFAULT;
+ int lastPhy18;
+
+ // Find the address and type of our phy
+ if (!smc_detect_phy(ioaddr, &phyaddr))
+ {
+ return;
+ }
+
+ // Reset the PHY, setting all other bits to zero
+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
+
+ // Wait for the reset to complete, or time out
+ timeout = 6; // Wait up to 3 seconds
+ while (timeout--)
+ {
+ if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
+ & PHY_CNTL_RST))
+ {
+ // reset complete
+ break;
+ }
+
+ mdelay(500); // wait 500 millisecs
+ }
+
+ if (timeout < 1)
+ {
+ PRINTK2("PHY reset timed out\n");
+ return;
+ }
+
+ // Read PHY Register 18, Status Output
+ lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
+
+ // Enable PHY Interrupts (for register 18)
+ // Interrupts listed here are disabled
+ smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
+ PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
+ PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
+ PHY_INT_SPDDET | PHY_INT_DPLXDET);
+
+ /* Configure the Receive/Phy Control register */
+ SMC_SELECT_BANK(ioaddr, 0);
+ outw( rpc_cur_mode, ioaddr + RPC_REG );
+
+ // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
+ my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+ my_ad_caps = PHY_AD_CSMA; // I am CSMA capable
+
+ if (my_phy_caps & PHY_STAT_CAP_T4)
+ my_ad_caps |= PHY_AD_T4;
+
+ if (my_phy_caps & PHY_STAT_CAP_TXF)
+ my_ad_caps |= PHY_AD_TX_FDX;
+
+ if (my_phy_caps & PHY_STAT_CAP_TXH)
+ my_ad_caps |= PHY_AD_TX_HDX;
+
+ if (my_phy_caps & PHY_STAT_CAP_TF)
+ my_ad_caps |= PHY_AD_10_FDX;
+
+ if (my_phy_caps & PHY_STAT_CAP_TH)
+ my_ad_caps |= PHY_AD_10_HDX;
+
+ // Update our Auto-Neg Advertisement Register
+ smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
+
+ PRINTK2("phy caps=%x\n", my_phy_caps);
+ PRINTK2("phy advertised caps=%x\n", my_ad_caps);
+
+ // Restart auto-negotiation process in order to advertise my caps
+ smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
+ PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
+
+ // Wait for the auto-negotiation to complete. This may take from
+ // 2 to 3 seconds.
+ // Wait for the reset to complete, or time out
+ timeout = 20; // Wait up to 10 seconds
+ while (timeout--)
+ {
+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
+ if (status & PHY_STAT_ANEG_ACK)
+ {
+ // auto-negotiate complete
+ break;
+ }
+
+ mdelay(500); // wait 500 millisecs
+
+ // Restart auto-negotiation if remote fault
+ if (status & PHY_STAT_REM_FLT)
+ {
+ PRINTK2("PHY remote fault detected\n");
+
+ // Restart auto-negotiation
+ PRINTK2("PHY restarting auto-negotiation\n");
+ smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
+ PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |
+ PHY_CNTL_SPEED | PHY_CNTL_DPLX);
+ }
+ }
+
+ if (timeout < 1)
+ {
+ PRINTK2("PHY auto-negotiate timed out\n");
+ failed = 1;
+ }
+
+ // Fail if we detected an auto-negotiate remote fault
+ if (status & PHY_STAT_REM_FLT)
+ {
+ PRINTK2("PHY remote fault detected\n");
+ failed = 1;
+ }
+
+ // Set our sysctl parameters to match auto-negotiation results
+ if ( lastPhy18 & PHY_INT_SPDDET )
+ {
+ PRINTK2("PHY 100BaseT\n");
+ rpc_cur_mode |= RPC_SPEED;
+ }
+ else
+ {
+ PRINTK2("PHY 10BaseT\n");
+ rpc_cur_mode &= ~RPC_SPEED;
+ }
+
+ if ( lastPhy18 & PHY_INT_DPLXDET )
+ {
+ PRINTK2("PHY Full Duplex\n");
+ rpc_cur_mode |= RPC_DPLX;
+ }
+ else
+ {
+ PRINTK2("PHY Half Duplex\n");
+ rpc_cur_mode &= ~RPC_DPLX;
+ }
+
+ // Re-Configure the Receive/Phy Control register
+ outw( rpc_cur_mode, ioaddr + RPC_REG );
+}
+
+/*
+ * Function: smc_reset( int ioaddr )
+ * Purpose:
+ * This sets the SMC91xx chip to its normal state, hopefully from whatever
+ * mess that any other DOS driver has put it in.
+ *
+ * Maybe I should reset more registers to defaults in here? SOFTRESET should
+ * do that for me.
+ *
+ * Method:
+ * 1. send a SOFT RESET
+ * 2. wait for it to finish
+ * 3. reset the memory management unit
+ * 4. clear all interrupts
+ *
+*/
+static void smc_reset(int ioaddr)
+{
+ /* This resets the registers mostly to defaults, but doesn't
+ * affect EEPROM. That seems unnecessary */
+ SMC_SELECT_BANK(ioaddr, 0);
+ _outw( RCR_SOFTRESET, ioaddr + RCR );
+
+ /* this should pause enough for the chip to be happy */
+ SMC_DELAY(ioaddr);
+
+ /* Set the transmit and receive configuration registers to
+ * default values */
+ _outw(RCR_CLEAR, ioaddr + RCR);
+ _outw(TCR_CLEAR, ioaddr + TCR);
+
+ /* Reset the MMU */
+ SMC_SELECT_BANK(ioaddr, 2);
+ _outw( MC_RESET, ioaddr + MMU_CMD );
+
+ /* Note: It doesn't seem that waiting for the MMU busy is needed here,
+ * but this is a place where future chipsets _COULD_ break. Be wary
+ * of issuing another MMU command right after this */
+ _outb(0, ioaddr + INT_MASK);
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: smc9000_probe_addr( int ioaddr )
+ *
+ * Purpose:
+ * Tests to see if a given ioaddr points to an SMC9xxx chip.
+ * Returns a 1 on success
+ *
+ * Algorithm:
+ * (1) see if the high byte of BANK_SELECT is 0x33
+ * (2) compare the ioaddr with the base register's address
+ * (3) see if I recognize the chip ID in the appropriate register
+ *
+ * ---------------------------------------------------------------------
+ */
+static int smc9000_probe_addr( isa_probe_addr_t ioaddr )
+{
+ word bank;
+ word revision_register;
+ word base_address_register;
+
+ /* First, see if the high byte is 0x33 */
+ bank = inw(ioaddr + BANK_SELECT);
+ if ((bank & 0xFF00) != 0x3300) {
+ return 0;
+ }
+ /* The above MIGHT indicate a device, but I need to write to further
+ * test this. */
+ _outw(0x0, ioaddr + BANK_SELECT);
+ bank = inw(ioaddr + BANK_SELECT);
+ if ((bank & 0xFF00) != 0x3300) {
+ return 0;
+ }
+
+ /* well, we've already written once, so hopefully another time won't
+ * hurt. This time, I need to switch the bank register to bank 1,
+ * so I can access the base address register */
+ SMC_SELECT_BANK(ioaddr, 1);
+ base_address_register = inw(ioaddr + BASE);
+
+ if (ioaddr != (base_address_register >> 3 & 0x3E0)) {
+ DBG("SMC9000: IOADDR %hX doesn't match configuration (%hX)."
+ "Probably not a SMC chip\n",
+ ioaddr, base_address_register >> 3 & 0x3E0);
+ /* well, the base address register didn't match. Must not have
+ * been a SMC chip after all. */
+ return 0;
+ }
+
+
+ /* check if the revision register is something that I recognize.
+ * These might need to be added to later, as future revisions
+ * could be added. */
+ SMC_SELECT_BANK(ioaddr, 3);
+ revision_register = inw(ioaddr + REVISION);
+ if (!chip_ids[(revision_register >> 4) & 0xF]) {
+ /* I don't recognize this chip, so... */
+ DBG( "SMC9000: IO %hX: Unrecognized revision register:"
+ " %hX, Contact author.\n", ioaddr, revision_register );
+ return 0;
+ }
+
+ /* at this point I'll assume that the chip is an SMC9xxx.
+ * It might be prudent to check a listing of MAC addresses
+ * against the hardware address, or do some other tests. */
+ return 1;
+}
+
+
+/**************************************************************************
+ * ETH_TRANSMIT - Transmit a frame
+ ***************************************************************************/
+static void smc9000_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ word length; /* real, length incl. header */
+ word numPages;
+ unsigned long time_out;
+ byte packet_no;
+ word status;
+ int i;
+
+ /* We dont pad here since we can have the hardware doing it for us */
+ length = (s + ETH_HLEN + 1)&~1;
+
+ /* convert to MMU pages */
+ numPages = length / 256;
+
+ if (numPages > 7 ) {
+ DBG("SMC9000: Far too big packet error. \n");
+ return;
+ }
+
+ /* dont try more than, say 30 times */
+ for (i=0;i<30;i++) {
+ /* now, try to allocate the memory */
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ _outw(MC_ALLOC | numPages, nic->ioaddr + MMU_CMD);
+
+ status = 0;
+ /* wait for the memory allocation to finnish */
+ for (time_out = currticks() + 5*TICKS_PER_SEC; currticks() < time_out; ) {
+ status = inb(nic->ioaddr + INTERRUPT);
+ if ( status & IM_ALLOC_INT ) {
+ /* acknowledge the interrupt */
+ _outb(IM_ALLOC_INT, nic->ioaddr + INTERRUPT);
+ break;
+ }
+ }
+
+ if ((status & IM_ALLOC_INT) != 0 ) {
+ /* We've got the memory */
+ break;
+ } else {
+ printf("SMC9000: Memory allocation timed out, resetting MMU.\n");
+ _outw(MC_RESET, nic->ioaddr + MMU_CMD);
+ }
+ }
+
+ /* If I get here, I _know_ there is a packet slot waiting for me */
+ packet_no = inb(nic->ioaddr + PNR_ARR + 1);
+ if (packet_no & 0x80) {
+ /* or isn't there? BAD CHIP! */
+ printf("SMC9000: Memory allocation failed. \n");
+ return;
+ }
+
+ /* we have a packet address, so tell the card to use it */
+ _outb(packet_no, nic->ioaddr + PNR_ARR);
+
+ /* point to the beginning of the packet */
+ _outw(PTR_AUTOINC, nic->ioaddr + POINTER);
+
+#if SMC9000_DEBUG > 2
+ printf("Trying to xmit packet of length %hX\n", length );
+#endif
+
+ /* send the packet length ( +6 for status, length and ctl byte )
+ * and the status word ( set to zeros ) */
+ _outw(0, nic->ioaddr + DATA_1 );
+
+ /* send the packet length ( +6 for status words, length, and ctl) */
+ _outb((length+6) & 0xFF, nic->ioaddr + DATA_1);
+ _outb((length+6) >> 8 , nic->ioaddr + DATA_1);
+
+ /* Write the contents of the packet */
+
+ /* The ethernet header first... */
+ outsw(nic->ioaddr + DATA_1, d, ETH_ALEN >> 1);
+ outsw(nic->ioaddr + DATA_1, nic->node_addr, ETH_ALEN >> 1);
+ _outw(htons(t), nic->ioaddr + DATA_1);
+
+ /* ... the data ... */
+ outsw(nic->ioaddr + DATA_1 , p, s >> 1);
+
+ /* ... and the last byte, if there is one. */
+ if ((s & 1) == 0) {
+ _outw(0, nic->ioaddr + DATA_1);
+ } else {
+ _outb(p[s-1], nic->ioaddr + DATA_1);
+ _outb(0x20, nic->ioaddr + DATA_1);
+ }
+
+ /* and let the chipset deal with it */
+ _outw(MC_ENQUEUE , nic->ioaddr + MMU_CMD);
+
+ status = 0; time_out = currticks() + 5*TICKS_PER_SEC;
+ do {
+ status = inb(nic->ioaddr + INTERRUPT);
+
+ if ((status & IM_TX_INT ) != 0) {
+ word tx_status;
+
+ /* ack interrupt */
+ _outb(IM_TX_INT, nic->ioaddr + INTERRUPT);
+
+ packet_no = inw(nic->ioaddr + FIFO_PORTS);
+ packet_no &= 0x7F;
+
+ /* select this as the packet to read from */
+ _outb( packet_no, nic->ioaddr + PNR_ARR );
+
+ /* read the first word from this packet */
+ _outw( PTR_AUTOINC | PTR_READ, nic->ioaddr + POINTER );
+
+ tx_status = inw( nic->ioaddr + DATA_1 );
+
+ if (0 == (tx_status & TS_SUCCESS)) {
+ DBG("SMC9000: TX FAIL STATUS: %hX \n", tx_status);
+ /* re-enable transmit */
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+ _outw(inw(nic->ioaddr + TCR ) | TCR_ENABLE, nic->ioaddr + TCR );
+ }
+
+ /* kill the packet */
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ _outw(MC_FREEPKT, nic->ioaddr + MMU_CMD);
+
+ return;
+ }
+ }while(currticks() < time_out);
+
+ printf("SMC9000: TX timed out, resetting board\n");
+ smc_reset(nic->ioaddr);
+ return;
+}
+
+/**************************************************************************
+ * ETH_POLL - Wait for a frame
+ ***************************************************************************/
+static int smc9000_poll(struct nic *nic, int retrieve)
+{
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ if (inw(nic->ioaddr + FIFO_PORTS) & FP_RXEMPTY)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+ /* start reading from the start of the packet */
+ _outw(PTR_READ | PTR_RCV | PTR_AUTOINC, nic->ioaddr + POINTER);
+
+ /* First read the status and check that we're ok */
+ if (!(inw(nic->ioaddr + DATA_1) & RS_ERRORS)) {
+ /* Next: read the packet length and mask off the top bits */
+ nic->packetlen = (inw(nic->ioaddr + DATA_1) & 0x07ff);
+
+ /* the packet length includes the 3 extra words */
+ nic->packetlen -= 6;
+#if SMC9000_DEBUG > 2
+ printf(" Reading %d words (and %d byte(s))\n",
+ (nic->packetlen >> 1), nic->packetlen & 1);
+#endif
+ /* read the packet (and the last "extra" word) */
+ insw(nic->ioaddr + DATA_1, nic->packet, (nic->packetlen+2) >> 1);
+ /* is there an odd last byte ? */
+ if (nic->packet[nic->packetlen+1] & 0x20)
+ nic->packetlen++;
+
+ /* error or good, tell the card to get rid of this packet */
+ _outw(MC_RELEASE, nic->ioaddr + MMU_CMD);
+ return 1;
+ }
+
+ printf("SMC9000: RX error\n");
+ /* error or good, tell the card to get rid of this packet */
+ _outw(MC_RELEASE, nic->ioaddr + MMU_CMD);
+ return 0;
+}
+
+static void smc9000_disable ( struct nic *nic, struct isa_device *isa __unused ) {
+
+ smc_reset(nic->ioaddr);
+
+ /* no more interrupts for me */
+ SMC_SELECT_BANK(nic->ioaddr, 2);
+ _outb( 0, nic->ioaddr + INT_MASK);
+
+ /* and tell the card to stay away from that nasty outside world */
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+ _outb( RCR_CLEAR, nic->ioaddr + RCR );
+ _outb( TCR_CLEAR, nic->ioaddr + TCR );
+}
+
+static void smc9000_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations smc9000_operations = {
+ .connect = dummy_connect,
+ .poll = smc9000_poll,
+ .transmit = smc9000_transmit,
+ .irq = smc9000_irq,
+
+};
+
+/**************************************************************************
+ * ETH_PROBE - Look for an adapter
+ ***************************************************************************/
+
+static int smc9000_probe ( struct nic *nic, struct isa_device *isa ) {
+
+ unsigned short revision;
+ int memory;
+ int media;
+ const char * version_string;
+ const char * if_string;
+ int i;
+
+ nic->irqno = 0;
+ nic->ioaddr = isa->ioaddr;
+
+ /*
+ * Get the MAC address ( bank 1, regs 4 - 9 )
+ */
+ SMC_SELECT_BANK(nic->ioaddr, 1);
+ for ( i = 0; i < 6; i += 2 ) {
+ word address;
+
+ address = inw(nic->ioaddr + ADDR0 + i);
+ nic->node_addr[i+1] = address >> 8;
+ nic->node_addr[i] = address & 0xFF;
+ }
+
+ /* get the memory information */
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+ memory = ( inw(nic->ioaddr + MCR) >> 9 ) & 0x7; /* multiplier */
+ memory *= 256 * (inw(nic->ioaddr + MIR) & 0xFF);
+
+ /*
+ * Now, I want to find out more about the chip. This is sort of
+ * redundant, but it's cleaner to have it in both, rather than having
+ * one VERY long probe procedure.
+ */
+ SMC_SELECT_BANK(nic->ioaddr, 3);
+ revision = inw(nic->ioaddr + REVISION);
+ version_string = chip_ids[(revision >> 4) & 0xF];
+
+ if (((revision & 0xF0) >> 4 == CHIP_9196) &&
+ ((revision & 0x0F) >= REV_9196)) {
+ /* This is a 91c96. 'c96 has the same chip id as 'c94 (4) but
+ * a revision starting at 6 */
+ version_string = smc91c96_id;
+ }
+
+ if ( !version_string ) {
+ /* I shouldn't get here because this call was done before.... */
+ return 0;
+ }
+
+ /* is it using AUI or 10BaseT ? */
+ SMC_SELECT_BANK(nic->ioaddr, 1);
+ if (inw(nic->ioaddr + CONFIG) & CFG_AUI_SELECT)
+ media = 2;
+ else
+ media = 1;
+
+ if_string = interfaces[media - 1];
+
+ /* now, reset the chip, and put it into a known state */
+ smc_reset(nic->ioaddr);
+
+ printf("SMC9000 %s\n", smc9000_version);
+ DBG("Copyright (C) 1998 Daniel Engstr\x94m\n");
+ DBG("Copyright (C) 1996 Eric Stahlman\n");
+
+ printf("%s rev:%d I/O port:%hX Interface:%s RAM:%d bytes \n",
+ version_string, revision & 0xF,
+ nic->ioaddr, if_string, memory );
+
+ DBG ( "Ethernet MAC address: %s\n", eth_ntoa ( nic->node_addr ) );
+
+ SMC_SELECT_BANK(nic->ioaddr, 0);
+
+ /* see the header file for options in TCR/RCR NORMAL*/
+ _outw(TCR_NORMAL, nic->ioaddr + TCR);
+ _outw(RCR_NORMAL, nic->ioaddr + RCR);
+
+ /* Select which interface to use */
+ SMC_SELECT_BANK(nic->ioaddr, 1);
+ if ( media == 1 ) {
+ _outw( inw( nic->ioaddr + CONFIG ) & ~CFG_AUI_SELECT,
+ nic->ioaddr + CONFIG );
+ }
+ else if ( media == 2 ) {
+ _outw( inw( nic->ioaddr + CONFIG ) | CFG_AUI_SELECT,
+ nic->ioaddr + CONFIG );
+ }
+
+ smc_phy_configure(nic->ioaddr);
+
+ nic->nic_op = &smc9000_operations;
+ return 1;
+}
+
+/*
+ * The SMC9000 can be at any of the following port addresses. To
+ * change for a slightly different card, you can add it to the array.
+ *
+ */
+static isa_probe_addr_t smc9000_probe_addrs[] = {
+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0,
+};
+
+ISA_DRIVER ( smc9000_driver, smc9000_probe_addrs, smc9000_probe_addr,
+ GENERIC_ISAPNP_VENDOR, 0x8228 );
+
+DRIVER ( "SMC9000", nic_driver, isa_driver, smc9000_driver,
+ smc9000_probe, smc9000_disable );
+
+ISA_ROM ( "smc9000", "SMC9000" );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.h
new file mode 100644
index 0000000..22b0e18
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/smc9000.h
@@ -0,0 +1,428 @@
+/*------------------------------------------------------------------------
+ * smc9000.h
+ *
+ * Copyright (C) 1998 by Daniel Engström
+ * Copyright (C) 1996 by Erik Stahlman
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * This file contains register information and access macros for
+ * the SMC91xxx chipset.
+ *
+ * Information contained in this file was obtained from the SMC91C94
+ * manual from SMC. To get a copy, if you really want one, you can find
+ * information under www.smsc.com in the components division.
+ * ( this thanks to advice from Donald Becker ).
+ *
+ * Authors
+ * Daniel Engström <daniel.engstrom@riksnett.no>
+ * Erik Stahlman <erik@vt.edu>
+ *
+ * History
+ * 96-01-06 Erik Stahlman moved definitions here from main .c
+ * file
+ * 96-01-19 Erik Stahlman polished this up some, and added
+ * better error handling
+ * 98-09-25 Daniel Engström adjusted for Etherboot
+ * 98-09-27 Daniel Engström moved some static strings back to the
+ * main .c file
+ * --------------------------------------------------------------------------*/
+
+FILE_LICENCE ( GPL_ANY );
+
+#ifndef _SMC9000_H_
+# define _SMC9000_H_
+
+/* I want some simple types */
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long int dword;
+
+/*---------------------------------------------------------------
+ *
+ * A description of the SMC registers is probably in order here,
+ * although for details, the SMC datasheet is invaluable.
+ *
+ * Basically, the chip has 4 banks of registers ( 0 to 3 ), which
+ * are accessed by writing a number into the BANK_SELECT register
+ * ( I also use a SMC_SELECT_BANK macro for this ).
+ *
+ * The banks are configured so that for most purposes, bank 2 is all
+ * that is needed for simple run time tasks.
+ * ----------------------------------------------------------------------*/
+
+/*
+ * Bank Select Register:
+ *
+ * yyyy yyyy 0000 00xx
+ * xx = bank number
+ * yyyy yyyy = 0x33, for identification purposes.
+ */
+#define BANK_SELECT 14
+
+/* BANK 0 */
+
+#define TCR 0 /* transmit control register */
+#define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
+#define TCR_FDUPLX 0x0800 /* receive packets sent out */
+#define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
+#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
+#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
+
+#define TCR_CLEAR 0 /* do NOTHING */
+/* the normal settings for the TCR register : */
+#define TCR_NORMAL (TCR_ENABLE | TCR_PAD_ENABLE)
+
+
+#define EPH_STATUS 2
+#define ES_LINK_OK 0x4000 /* is the link integrity ok ? */
+
+#define RCR 4
+#define RCR_SOFTRESET 0x8000 /* resets the chip */
+#define RCR_STRIP_CRC 0x200 /* strips CRC */
+#define RCR_ENABLE 0x100 /* IFF this is set, we can receive packets */
+#define RCR_ALMUL 0x4 /* receive all multicast packets */
+#define RCR_PROMISC 0x2 /* enable promiscuous mode */
+
+/* the normal settings for the RCR register : */
+#define RCR_NORMAL (RCR_STRIP_CRC | RCR_ENABLE)
+#define RCR_CLEAR 0x0 /* set it to a base state */
+
+#define COUNTER 6
+#define MIR 8
+#define MCR 10
+/* 12 is reserved */
+
+// Receive/Phy Control Register
+/* BANK 0 */
+#define RPC_REG 0x000A
+#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
+#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
+#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
+#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
+#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
+#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
+#define RPC_LED_RES (0x01) // LED = Reserved
+#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
+#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
+#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
+#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
+#define RPC_LED_TX (0x06) // LED = TX packet occurred
+#define RPC_LED_RX (0x07) // LED = RX packet occurred
+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+
+// Receive/Phy Control Register
+/* BANK 0 */
+#define RPC_REG 0x000A
+#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
+#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
+#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
+#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
+#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
+#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
+#define RPC_LED_RES (0x01) // LED = Reserved
+#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
+#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
+#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
+#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
+#define RPC_LED_TX (0x06) // LED = TX packet occurred
+#define RPC_LED_RX (0x07) // LED = RX packet occurred
+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
+
+/* BANK 1 */
+#define CONFIG 0
+#define CFG_AUI_SELECT 0x100
+#define BASE 2
+#define ADDR0 4
+#define ADDR1 6
+#define ADDR2 8
+#define GENERAL 10
+#define CONTROL 12
+#define CTL_POWERDOWN 0x2000
+#define CTL_LE_ENABLE 0x80
+#define CTL_CR_ENABLE 0x40
+#define CTL_TE_ENABLE 0x0020
+#define CTL_AUTO_RELEASE 0x0800
+#define CTL_EPROM_ACCESS 0x0003 /* high if Eprom is being read */
+
+/* BANK 2 */
+#define MMU_CMD 0
+#define MC_BUSY 1 /* only readable bit in the register */
+#define MC_NOP 0
+#define MC_ALLOC 0x20 /* or with number of 256 byte packets */
+#define MC_RESET 0x40
+#define MC_REMOVE 0x60 /* remove the current rx packet */
+#define MC_RELEASE 0x80 /* remove and release the current rx packet */
+#define MC_FREEPKT 0xA0 /* Release packet in PNR register */
+#define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */
+
+#define PNR_ARR 2
+#define FIFO_PORTS 4
+
+#define FP_RXEMPTY 0x8000
+#define FP_TXEMPTY 0x80
+
+#define POINTER 6
+#define PTR_READ 0x2000
+#define PTR_RCV 0x8000
+#define PTR_AUTOINC 0x4000
+#define PTR_AUTO_INC 0x0040
+
+#define DATA_1 8
+#define DATA_2 10
+#define INTERRUPT 12
+
+#define INT_MASK 13
+#define IM_RCV_INT 0x1
+#define IM_TX_INT 0x2
+#define IM_TX_EMPTY_INT 0x4
+#define IM_ALLOC_INT 0x8
+#define IM_RX_OVRN_INT 0x10
+#define IM_EPH_INT 0x20
+#define IM_ERCV_INT 0x40 /* not on SMC9192 */
+
+/* BANK 3 */
+#define MULTICAST1 0
+#define MULTICAST2 2
+#define MULTICAST3 4
+#define MULTICAST4 6
+#define MGMT 8
+#define REVISION 10 /* ( hi: chip id low: rev # ) */
+
+// Management Interface Register (MII)
+#define MII_REG 0x0008
+#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup
+#define MII_MDOE 0x0008 // MII Output Enable
+#define MII_MCLK 0x0004 // MII Clock, pin MDCLK
+#define MII_MDI 0x0002 // MII Input, pin MDI
+#define MII_MDO 0x0001 // MII Output, pin MDO
+
+/* this is NOT on SMC9192 */
+#define ERCV 12
+
+/* Note that 9194 and 9196 have the smame chip id,
+ * the 9196 will have revisions starting at 6 */
+#define CHIP_9190 3
+#define CHIP_9194 4
+#define CHIP_9195 5
+#define CHIP_9196 4
+#define CHIP_91100 7
+#define CHIP_91100FD 8
+
+#define REV_9196 6
+
+/*
+ * Transmit status bits
+ */
+#define TS_SUCCESS 0x0001
+#define TS_LOSTCAR 0x0400
+#define TS_LATCOL 0x0200
+#define TS_16COL 0x0010
+
+/*
+ * Receive status bits
+ */
+#define RS_ALGNERR 0x8000
+#define RS_BADCRC 0x2000
+#define RS_ODDFRAME 0x1000
+#define RS_TOOLONG 0x0800
+#define RS_TOOSHORT 0x0400
+#define RS_MULTICAST 0x0001
+#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
+
+// PHY Register Addresses (LAN91C111 Internal PHY)
+
+// PHY Control Register
+#define PHY_CNTL_REG 0x00
+#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
+#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
+#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
+#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
+#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
+#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
+#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
+#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
+#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
+
+// PHY Status Register
+#define PHY_STAT_REG 0x01
+#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
+#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
+#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
+#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
+#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
+#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
+#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
+#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
+#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
+#define PHY_STAT_LINK 0x0004 // 1=valid link
+#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
+#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
+
+// PHY Identifier Registers
+#define PHY_ID1_REG 0x02 // PHY Identifier 1
+#define PHY_ID2_REG 0x03 // PHY Identifier 2
+
+// PHY Auto-Negotiation Advertisement Register
+#define PHY_AD_REG 0x04
+#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
+#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
+#define PHY_AD_RF 0x2000 // 1=advertise remote fault
+#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
+#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
+#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
+#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
+#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
+#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
+
+// PHY Auto-negotiation Remote End Capability Register
+#define PHY_RMT_REG 0x05
+// Uses same bit definitions as PHY_AD_REG
+
+// PHY Configuration Register 1
+#define PHY_CFG1_REG 0x10
+#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK 0x003C
+#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
+
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG 0x11
+#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
+#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
+#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
+#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
+#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
+#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
+#define PHY_INT_JAB 0x0100 // 1=Jabber detected
+#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG 0x13 // Interrupt Mask
+// Uses the same bit definitions as PHY_INT_REG
+
+
+// PHY Register Addresses (LAN91C111 Internal PHY)
+
+// PHY Control Register
+#define PHY_CNTL_REG 0x00
+#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
+#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
+#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
+#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
+#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
+#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
+#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
+#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
+#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
+
+// PHY Status Register
+#define PHY_STAT_REG 0x01
+#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
+#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
+#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
+#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
+#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
+#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
+#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
+#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
+#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
+#define PHY_STAT_LINK 0x0004 // 1=valid link
+#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
+#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
+
+// PHY Identifier Registers
+#define PHY_ID1_REG 0x02 // PHY Identifier 1
+#define PHY_ID2_REG 0x03 // PHY Identifier 2
+
+// PHY Auto-Negotiation Advertisement Register
+#define PHY_AD_REG 0x04
+#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
+#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
+#define PHY_AD_RF 0x2000 // 1=advertise remote fault
+#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
+#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
+#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
+#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
+#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
+#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
+
+// PHY Auto-negotiation Remote End Capability Register
+#define PHY_RMT_REG 0x05
+// Uses same bit definitions as PHY_AD_REG
+
+// PHY Configuration Register 1
+#define PHY_CFG1_REG 0x10
+#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
+#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
+#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
+#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
+#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
+#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
+#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
+#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
+#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
+#define PHY_CFG1_TLVL_MASK 0x003C
+#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
+
+
+// PHY Configuration Register 2
+#define PHY_CFG2_REG 0x11
+#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
+#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
+#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
+#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
+
+// PHY Status Output (and Interrupt status) Register
+#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
+#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
+#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
+#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
+#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
+#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
+#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
+#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
+#define PHY_INT_JAB 0x0100 // 1=Jabber detected
+#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
+#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
+
+// PHY Interrupt/Status Mask Register
+#define PHY_MASK_REG 0x13 // Interrupt Mask
+// Uses the same bit definitions as PHY_INT_REG
+
+
+/*-------------------------------------------------------------------------
+ * I define some macros to make it easier to do somewhat common
+ * or slightly complicated, repeated tasks.
+ --------------------------------------------------------------------------*/
+
+/* select a register bank, 0 to 3 */
+
+#define SMC_SELECT_BANK(x, y) { _outw( y, x + BANK_SELECT ); }
+
+/* define a small delay for the reset */
+#define SMC_DELAY(x) { inw( x + RCR );\
+ inw( x + RCR );\
+ inw( x + RCR ); }
+
+
+#endif /* _SMC_9000_H_ */
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/sundance.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/sundance.c
new file mode 100644
index 0000000..c446ac0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/sundance.c
@@ -0,0 +1,897 @@
+/**************************************************************************
+*
+* sundance.c -- Etherboot device driver for the Sundance ST201 "Alta".
+* Written 2002-2002 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* sundance.c: A Linux device driver for the Sundance ST201 "Alta"
+* Written 1999-2002 by Donald Becker
+*
+* tulip.c: Tulip and Clone Etherboot Driver
+* By Marty Conner
+* Copyright (C) 2001 Entity Cyber, Inc.
+*
+* Linux Driver Version LK1.09a, 10-Jul-2003 (2.4.25)
+*
+* REVISION HISTORY:
+* ================
+* v1.1 01-01-2003 timlegge Initial implementation
+* v1.7 04-10-2003 timlegge Transfers Linux Kernel (30 sec)
+* v1.8 04-13-2003 timlegge Fix multiple transmission bug
+* v1.9 08-19-2003 timlegge Support Multicast
+* v1.10 01-17-2004 timlegge Initial driver output cleanup
+* v1.11 03-21-2004 timlegge Remove unused variables
+* v1.12 03-21-2004 timlegge Remove excess MII defines
+* v1.13 03-24-2004 timlegge Update to Linux 2.4.25 driver
+*
+****************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* to get some global routines like printf */
+#include "etherboot.h"
+/* to get the interface to the body of the program */
+#include "nic.h"
+/* to get the PCI support functions, if this is a PCI NIC */
+#include <gpxe/pci.h>
+#include "mii.h"
+
+#define drv_version "v1.12"
+#define drv_date "2004-03-21"
+
+#define HZ 100
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* Set the mtu */
+static int mtu = 1514;
+
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
+ The sundance uses a 64 element hash table based on the Ethernet CRC. */
+// static int multicast_filter_limit = 32;
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ Setting to > 1518 effectively disables this feature.
+ This chip can receive into any byte alignment buffers, so word-oriented
+ archs do not need a copy-align of the IP header. */
+static int rx_copybreak = 0;
+static int flowctrl = 1;
+
+/* Allow forcing the media type */
+/* media[] specifies the media type the NIC operates at.
+ autosense Autosensing active media.
+ 10mbps_hd 10Mbps half duplex.
+ 10mbps_fd 10Mbps full duplex.
+ 100mbps_hd 100Mbps half duplex.
+ 100mbps_fd 100Mbps full duplex.
+*/
+static char media[] = "autosense";
+
+/* Operational parameters that are set at compile time. */
+
+/* As Etherboot uses a Polling driver we can keep the number of rings
+to the minimum number required. In general that is 1 transmit and 4 receive receive rings. However some cards require that
+there be a minimum of 2 rings */
+#define TX_RING_SIZE 2
+#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
+#define RX_RING_SIZE 4
+
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIME_OUT (4*HZ)
+#define PKT_BUF_SZ 1536
+
+/* Offsets to the device registers.
+ Unlike software-only systems, device drivers interact with complex hardware.
+ It's not useful to define symbolic names for every register bit in the
+ device. The name can only partially document the semantics and make
+ the driver longer and more difficult to read.
+ In general, only the important configuration values or bits changed
+ multiple times should be defined symbolically.
+*/
+enum alta_offsets {
+ DMACtrl = 0x00,
+ TxListPtr = 0x04,
+ TxDMABurstThresh = 0x08,
+ TxDMAUrgentThresh = 0x09,
+ TxDMAPollPeriod = 0x0a,
+ RxDMAStatus = 0x0c,
+ RxListPtr = 0x10,
+ DebugCtrl0 = 0x1a,
+ DebugCtrl1 = 0x1c,
+ RxDMABurstThresh = 0x14,
+ RxDMAUrgentThresh = 0x15,
+ RxDMAPollPeriod = 0x16,
+ LEDCtrl = 0x1a,
+ ASICCtrl = 0x30,
+ EEData = 0x34,
+ EECtrl = 0x36,
+ TxStartThresh = 0x3c,
+ RxEarlyThresh = 0x3e,
+ FlashAddr = 0x40,
+ FlashData = 0x44,
+ TxStatus = 0x46,
+ TxFrameId = 0x47,
+ DownCounter = 0x18,
+ IntrClear = 0x4a,
+ IntrEnable = 0x4c,
+ IntrStatus = 0x4e,
+ MACCtrl0 = 0x50,
+ MACCtrl1 = 0x52,
+ StationAddr = 0x54,
+ MaxFrameSize = 0x5A,
+ RxMode = 0x5c,
+ MIICtrl = 0x5e,
+ MulticastFilter0 = 0x60,
+ MulticastFilter1 = 0x64,
+ RxOctetsLow = 0x68,
+ RxOctetsHigh = 0x6a,
+ TxOctetsLow = 0x6c,
+ TxOctetsHigh = 0x6e,
+ TxFramesOK = 0x70,
+ RxFramesOK = 0x72,
+ StatsCarrierError = 0x74,
+ StatsLateColl = 0x75,
+ StatsMultiColl = 0x76,
+ StatsOneColl = 0x77,
+ StatsTxDefer = 0x78,
+ RxMissed = 0x79,
+ StatsTxXSDefer = 0x7a,
+ StatsTxAbort = 0x7b,
+ StatsBcastTx = 0x7c,
+ StatsBcastRx = 0x7d,
+ StatsMcastTx = 0x7e,
+ StatsMcastRx = 0x7f,
+ /* Aliased and bogus values! */
+ RxStatus = 0x0c,
+};
+enum ASICCtrl_HiWord_bit {
+ GlobalReset = 0x0001,
+ RxReset = 0x0002,
+ TxReset = 0x0004,
+ DMAReset = 0x0008,
+ FIFOReset = 0x0010,
+ NetworkReset = 0x0020,
+ HostReset = 0x0040,
+ ResetBusy = 0x0400,
+};
+
+/* Bits in the interrupt status/mask registers. */
+enum intr_status_bits {
+ IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008,
+ IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020,
+ IntrDrvRqst = 0x0040,
+ StatsMax = 0x0080, LinkChange = 0x0100,
+ IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400,
+};
+
+/* Bits in the RxMode register. */
+enum rx_mode_bits {
+ AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08,
+ AcceptBroadcast = 0x04, AcceptMulticast = 0x02, AcceptMyPhys =
+ 0x01,
+};
+/* Bits in MACCtrl. */
+enum mac_ctrl0_bits {
+ EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40,
+ EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200,
+};
+enum mac_ctrl1_bits {
+ StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080,
+ TxEnable = 0x0100, TxDisable = 0x0200, TxEnabled = 0x0400,
+ RxEnable = 0x0800, RxDisable = 0x1000, RxEnabled = 0x2000,
+};
+
+/* The Rx and Tx buffer descriptors.
+ Using only 32 bit fields simplifies software endian correction.
+ This structure must be aligned, and should avoid spanning cache lines.
+*/
+struct netdev_desc {
+ u32 next_desc;
+ u32 status;
+ u32 addr;
+ u32 length;
+};
+
+/* Bits in netdev_desc.status */
+enum desc_status_bits {
+ DescOwn = 0x8000,
+ DescEndPacket = 0x4000,
+ DescEndRing = 0x2000,
+ LastFrag = 0x80000000,
+ DescIntrOnTx = 0x8000,
+ DescIntrOnDMADone = 0x80000000,
+ DisableAlign = 0x00000001,
+};
+
+/**********************************************
+* Descriptor Ring and Buffer defination
+***********************************************/
+/* Define the TX Descriptor */
+static struct netdev_desc tx_ring[TX_RING_SIZE];
+
+/* Define the RX Descriptor */
+static struct netdev_desc rx_ring[RX_RING_SIZE];
+
+/* Create a static buffer of size PKT_BUF_SZ for each RX and TX descriptor.
+ All descriptors point to a part of this buffer */
+struct {
+ unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE];
+ unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ];
+} rx_tx_buf __shared;
+#define rxb rx_tx_buf.rxb
+#define txb rx_tx_buf.txb
+
+/* FIXME: Move BASE to the private structure */
+static u32 BASE;
+#define EEPROM_SIZE 128
+
+enum pci_id_flags_bits {
+ PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
+ PCI_ADDR0 = 0 << 4, PCI_ADDR1 = 1 << 4, PCI_ADDR2 =
+ 2 << 4, PCI_ADDR3 = 3 << 4,
+};
+
+enum chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, };
+#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0)
+
+#define MII_CNT 4
+static struct sundance_private {
+ const char *nic_name;
+ /* Frequently used values */
+
+ unsigned int cur_rx; /* Producer/consumer ring indicies */
+ unsigned int mtu;
+
+ /* These values keep track of the tranceiver/media in use */
+ unsigned int flowctrl:1;
+ unsigned int an_enable:1;
+
+ unsigned int speed;
+
+ /* MII tranceiver section */
+ struct mii_if_info mii_if;
+ int mii_preamble_required;
+ unsigned char phys[MII_CNT];
+ unsigned char pci_rev_id;
+} sdx;
+
+static struct sundance_private *sdc;
+
+/* Station Address location within the EEPROM */
+#define EEPROM_SA_OFFSET 0x10
+#define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \
+ IntrDrvRqst | IntrTxDone | StatsMax | \
+ LinkChange)
+
+static int eeprom_read(long ioaddr, int location);
+static int mdio_read(struct nic *nic, int phy_id, unsigned int location);
+static void mdio_write(struct nic *nic, int phy_id, unsigned int location,
+ int value);
+static void set_rx_mode(struct nic *nic);
+
+static void check_duplex(struct nic *nic)
+{
+ int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
+ int negotiated = mii_lpa & sdc->mii_if.advertising;
+ int duplex;
+
+ /* Force media */
+ if (!sdc->an_enable || mii_lpa == 0xffff) {
+ if (sdc->mii_if.full_duplex)
+ outw(inw(BASE + MACCtrl0) | EnbFullDuplex,
+ BASE + MACCtrl0);
+ return;
+ }
+
+ /* Autonegotiation */
+ duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
+ if (sdc->mii_if.full_duplex != duplex) {
+ sdc->mii_if.full_duplex = duplex;
+ DBG ("%s: Setting %s-duplex based on MII #%d "
+ "negotiated capability %4.4x.\n", sdc->nic_name,
+ duplex ? "full" : "half", sdc->phys[0],
+ negotiated );
+ outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0,
+ BASE + MACCtrl0);
+ }
+}
+
+
+/**************************************************************************
+ * init_ring - setup the tx and rx descriptors
+ *************************************************************************/
+static void init_ring(struct nic *nic __unused)
+{
+ int i;
+
+ sdc->cur_rx = 0;
+
+ /* Initialize all the Rx descriptors */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].next_desc = virt_to_le32desc(&rx_ring[i + 1]);
+ rx_ring[i].status = 0;
+ rx_ring[i].length = 0;
+ rx_ring[i].addr = 0;
+ }
+
+ /* Mark the last entry as wrapping the ring */
+ rx_ring[i - 1].next_desc = virt_to_le32desc(&rx_ring[0]);
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].addr = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
+ rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
+ }
+
+ /* We only use one transmit buffer, but two
+ * descriptors so transmit engines have somewhere
+ * to point should they feel the need */
+ tx_ring[0].status = 0x00000000;
+ tx_ring[0].addr = virt_to_bus(&txb[0]);
+ tx_ring[0].next_desc = 0; /* virt_to_bus(&tx_ring[1]); */
+
+ /* This descriptor is never used */
+ tx_ring[1].status = 0x00000000;
+ tx_ring[1].addr = 0; /*virt_to_bus(&txb[0]); */
+ tx_ring[1].next_desc = 0;
+
+ /* Mark the last entry as wrapping the ring,
+ * though this should never happen */
+ tx_ring[1].length = cpu_to_le32(LastFrag | PKT_BUF_SZ);
+}
+
+/**************************************************************************
+ * RESET - Reset Adapter
+ * ***********************************************************************/
+static void sundance_reset(struct nic *nic)
+{
+ int i;
+
+ init_ring(nic);
+
+ outl(virt_to_le32desc(&rx_ring[0]), BASE + RxListPtr);
+ /* The Tx List Pointer is written as packets are queued */
+
+ /* Initialize other registers. */
+ /* __set_mac_addr(dev); */
+ {
+ u16 addr16;
+
+ addr16 = (nic->node_addr[0] | (nic->node_addr[1] << 8));
+ outw(addr16, BASE + StationAddr);
+ addr16 = (nic->node_addr[2] | (nic->node_addr[3] << 8));
+ outw(addr16, BASE + StationAddr + 2);
+ addr16 = (nic->node_addr[4] | (nic->node_addr[5] << 8));
+ outw(addr16, BASE + StationAddr + 4);
+ }
+
+ outw(sdc->mtu + 14, BASE + MaxFrameSize);
+ if (sdc->mtu > 2047) /* this will never happen with default options */
+ outl(inl(BASE + ASICCtrl) | 0x0c, BASE + ASICCtrl);
+
+ set_rx_mode(nic);
+
+ outw(0, BASE + DownCounter);
+ /* Set the chip to poll every N*30nsec */
+ outb(100, BASE + RxDMAPollPeriod);
+
+ /* Fix DFE-580TX packet drop issue */
+ if (sdc->pci_rev_id >= 0x14)
+ writeb(0x01, BASE + DebugCtrl1);
+
+ outw(RxEnable | TxEnable, BASE + MACCtrl1);
+
+ /* Construct a perfect filter frame with the mac address as first match
+ * and broadcast for all others */
+ for (i = 0; i < 192; i++)
+ txb[i] = 0xFF;
+
+ txb[0] = nic->node_addr[0];
+ txb[1] = nic->node_addr[1];
+ txb[2] = nic->node_addr[2];
+ txb[3] = nic->node_addr[3];
+ txb[4] = nic->node_addr[4];
+ txb[5] = nic->node_addr[5];
+
+ DBG ( "%s: Done sundance_reset, status: Rx %hX Tx %hX "
+ "MAC Control %hX, %hX %hX\n",
+ sdc->nic_name, (int) inl(BASE + RxStatus),
+ (int) inw(BASE + TxStatus), (int) inl(BASE + MACCtrl0),
+ (int) inw(BASE + MACCtrl1), (int) inw(BASE + MACCtrl0) );
+}
+
+/**************************************************************************
+IRQ - Wait for a frame
+***************************************************************************/
+static void sundance_irq ( struct nic *nic, irq_action_t action ) {
+ unsigned int intr_status;
+
+ switch ( action ) {
+ case DISABLE :
+ case ENABLE :
+ intr_status = inw(nic->ioaddr + IntrStatus);
+ intr_status = intr_status & ~DEFAULT_INTR;
+ if ( action == ENABLE )
+ intr_status = intr_status | DEFAULT_INTR;
+ outw(intr_status, nic->ioaddr + IntrEnable);
+ break;
+ case FORCE :
+ outw(0x0200, BASE + ASICCtrl);
+ break;
+ }
+}
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int sundance_poll(struct nic *nic, int retreive)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ int entry = sdc->cur_rx % RX_RING_SIZE;
+ u32 frame_status = le32_to_cpu(rx_ring[entry].status);
+ int intr_status;
+ int pkt_len = 0;
+
+ if (!(frame_status & DescOwn))
+ return 0;
+
+ /* There is a packet ready */
+ if(!retreive)
+ return 1;
+
+ intr_status = inw(nic->ioaddr + IntrStatus);
+ outw(intr_status, nic->ioaddr + IntrStatus);
+
+ pkt_len = frame_status & 0x1fff;
+
+ if (frame_status & 0x001f4000) {
+ DBG ( "Polling frame_status error\n" ); /* Do we really care about this */
+ } else {
+ if (pkt_len < rx_copybreak) {
+ /* FIXME: What should happen Will this ever occur */
+ printf("Poll Error: pkt_len < rx_copybreak");
+ } else {
+ nic->packetlen = pkt_len;
+ memcpy(nic->packet, rxb +
+ (sdc->cur_rx * PKT_BUF_SZ), nic->packetlen);
+
+ }
+ }
+ rx_ring[entry].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
+ rx_ring[entry].status = 0;
+ entry++;
+ sdc->cur_rx = entry % RX_RING_SIZE;
+ outw(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
+ nic->ioaddr + IntrStatus);
+ return 1;
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void sundance_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ u16 nstype;
+ u32 to;
+
+ /* Disable the Tx */
+ outw(TxDisable, BASE + MACCtrl1);
+
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+ /* Setup the transmit descriptor */
+ tx_ring[0].length = cpu_to_le32(s | LastFrag);
+ tx_ring[0].status = cpu_to_le32(0x00000001);
+
+ /* Point to transmit descriptor */
+ outl(virt_to_le32desc(&tx_ring[0]), BASE + TxListPtr);
+
+ /* Enable Tx */
+ outw(TxEnable, BASE + MACCtrl1);
+ /* Trigger an immediate send */
+ outw(0, BASE + TxStatus);
+
+ to = currticks() + TX_TIME_OUT;
+ while (!(tx_ring[0].status & 0x00010000) && (currticks() < to)); /* wait */
+
+ if (currticks() >= to) {
+ printf("TX Time Out");
+ }
+ /* Disable Tx */
+ outw(TxDisable, BASE + MACCtrl1);
+
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void sundance_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ */
+ outw(0x0000, BASE + IntrEnable);
+ /* Stop the Chipchips Tx and Rx Status */
+ outw(TxDisable | RxDisable | StatsDisable, BASE + MACCtrl1);
+}
+
+static struct nic_operations sundance_operations = {
+ .connect = dummy_connect,
+ .poll = sundance_poll,
+ .transmit = sundance_transmit,
+ .irq = sundance_irq,
+
+};
+
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int sundance_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ u8 ee_data[EEPROM_SIZE];
+ u16 mii_ctl;
+ int i;
+ int speed;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ /* BASE is used throughout to address the card */
+ BASE = pci->ioaddr;
+ printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n",
+ pci->driver_name, pci->vendor, pci->device);
+
+ /* Get the MAC Address by reading the EEPROM */
+ for (i = 0; i < 3; i++) {
+ ((u16 *) ee_data)[i] =
+ le16_to_cpu(eeprom_read(BASE, i + EEPROM_SA_OFFSET));
+ }
+ /* Update the nic structure with the MAC Address */
+ for (i = 0; i < ETH_ALEN; i++) {
+ nic->node_addr[i] = ee_data[i];
+ }
+
+ /* Set the card as PCI Bus Master */
+ adjust_pci_device(pci);
+
+// sdc->mii_if.dev = pci;
+// sdc->mii_if.phy_id_mask = 0x1f;
+// sdc->mii_if.reg_num_mask = 0x1f;
+
+ /* point to private storage */
+ sdc = &sdx;
+
+ sdc->nic_name = pci->driver_name;
+ sdc->mtu = mtu;
+
+ pci_read_config_byte(pci, PCI_REVISION_ID, &sdc->pci_rev_id);
+
+ DBG ( "Device revision id: %hx\n", sdc->pci_rev_id );
+
+ /* Print out some hardware info */
+ DBG ( "%s: %s at ioaddr %hX, ", pci->driver_name, nic->node_addr, (unsigned int) BASE);
+
+ sdc->mii_preamble_required = 0;
+ if (1) {
+ int phy, phy_idx = 0;
+ sdc->phys[0] = 1; /* Default Setting */
+ sdc->mii_preamble_required++;
+ for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
+ int mii_status = mdio_read(nic, phy, MII_BMSR);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ sdc->phys[phy_idx++] = phy;
+ sdc->mii_if.advertising =
+ mdio_read(nic, phy, MII_ADVERTISE);
+ if ((mii_status & 0x0040) == 0)
+ sdc->mii_preamble_required++;
+ DBG
+ ( "%s: MII PHY found at address %d, status " "%hX advertising %hX\n", sdc->nic_name, phy, mii_status, sdc->mii_if.advertising );
+ }
+ }
+ sdc->mii_preamble_required--;
+ if (phy_idx == 0)
+ printf("%s: No MII transceiver found!\n",
+ sdc->nic_name);
+ sdc->mii_if.phy_id = sdc->phys[0];
+ }
+
+ /* Parse override configuration */
+ sdc->an_enable = 1;
+ if (strcasecmp(media, "autosense") != 0) {
+ sdc->an_enable = 0;
+ if (strcasecmp(media, "100mbps_fd") == 0 ||
+ strcasecmp(media, "4") == 0) {
+ sdc->speed = 100;
+ sdc->mii_if.full_duplex = 1;
+ } else if (strcasecmp(media, "100mbps_hd") == 0
+ || strcasecmp(media, "3") == 0) {
+ sdc->speed = 100;
+ sdc->mii_if.full_duplex = 0;
+ } else if (strcasecmp(media, "10mbps_fd") == 0 ||
+ strcasecmp(media, "2") == 0) {
+ sdc->speed = 10;
+ sdc->mii_if.full_duplex = 1;
+ } else if (strcasecmp(media, "10mbps_hd") == 0 ||
+ strcasecmp(media, "1") == 0) {
+ sdc->speed = 10;
+ sdc->mii_if.full_duplex = 0;
+ } else {
+ sdc->an_enable = 1;
+ }
+ }
+ if (flowctrl == 1)
+ sdc->flowctrl = 1;
+
+ /* Fibre PHY? */
+ if (inl(BASE + ASICCtrl) & 0x80) {
+ /* Default 100Mbps Full */
+ if (sdc->an_enable) {
+ sdc->speed = 100;
+ sdc->mii_if.full_duplex = 1;
+ sdc->an_enable = 0;
+ }
+ }
+
+ /* The Linux driver uses flow control and resets the link here. This means the
+ mii section from above would need to be re done I believe. Since it serves
+ no real purpose leave it out. */
+
+ /* Force media type */
+ if (!sdc->an_enable) {
+ mii_ctl = 0;
+ mii_ctl |= (sdc->speed == 100) ? BMCR_SPEED100 : 0;
+ mii_ctl |= (sdc->mii_if.full_duplex) ? BMCR_FULLDPLX : 0;
+ mdio_write(nic, sdc->phys[0], MII_BMCR, mii_ctl);
+ printf("Override speed=%d, %s duplex\n",
+ sdc->speed,
+ sdc->mii_if.full_duplex ? "Full" : "Half");
+ }
+
+ /* Reset the chip to erase previous misconfiguration */
+ DBG ( "ASIC Control is %#x\n", inl(BASE + ASICCtrl) );
+ outw(0x007f, BASE + ASICCtrl + 2);
+
+ /*
+ * wait for reset to complete
+ * this is heavily inspired by the linux sundance driver
+ * according to the linux driver it can take up to 1ms for the reset
+ * to complete
+ */
+ i = 0;
+ while(inl(BASE + ASICCtrl) & (ResetBusy << 16)) {
+ if(i++ >= 10) {
+ DBG("sundance: NIC reset did not complete.\n");
+ break;
+ }
+ udelay(100);
+ }
+
+ DBG ( "ASIC Control is now %#x.\n", inl(BASE + ASICCtrl) );
+
+ sundance_reset(nic);
+ if (sdc->an_enable) {
+ u16 mii_advertise, mii_lpa;
+ mii_advertise =
+ mdio_read(nic, sdc->phys[0], MII_ADVERTISE);
+ mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
+ mii_advertise &= mii_lpa;
+ if (mii_advertise & ADVERTISE_100FULL)
+ sdc->speed = 100;
+ else if (mii_advertise & ADVERTISE_100HALF)
+ sdc->speed = 100;
+ else if (mii_advertise & ADVERTISE_10FULL)
+ sdc->speed = 10;
+ else if (mii_advertise & ADVERTISE_10HALF)
+ sdc->speed = 10;
+ } else {
+ mii_ctl = mdio_read(nic, sdc->phys[0], MII_BMCR);
+ speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
+ sdc->speed = speed;
+ printf("%s: Link changed: %dMbps ,", sdc->nic_name, speed);
+ printf("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
+ "full" : "half");
+ }
+ check_duplex(nic);
+ if (sdc->flowctrl && sdc->mii_if.full_duplex) {
+ outw(inw(BASE + MulticastFilter1 + 2) | 0x0200,
+ BASE + MulticastFilter1 + 2);
+ outw(inw(BASE + MACCtrl0) | EnbFlowCtrl, BASE + MACCtrl0);
+ }
+ printf("%dMbps, %s-Duplex\n", sdc->speed,
+ sdc->mii_if.full_duplex ? "Full" : "Half");
+
+ /* point to NIC specific routines */
+ nic->nic_op = &sundance_operations;
+
+ nic->irqno = pci->irq;
+ nic->ioaddr = BASE;
+
+ return 1;
+}
+
+
+/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
+static int eeprom_read(long ioaddr, int location)
+{
+ int boguscnt = 10000; /* Typical 1900 ticks */
+ outw(0x0200 | (location & 0xff), ioaddr + EECtrl);
+ do {
+ if (!(inw(ioaddr + EECtrl) & 0x8000)) {
+ return inw(ioaddr + EEData);
+ }
+ }
+ while (--boguscnt > 0);
+ return 0;
+}
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details.
+
+ The maximum data clock rate is 2.5 Mhz.
+ The timing is decoupled from the processor clock by flushing the write
+ from the CPU write buffer with a following read, and using PCI
+ transaction time. */
+
+#define mdio_in(mdio_addr) inb(mdio_addr)
+#define mdio_out(value, mdio_addr) outb(value, mdio_addr)
+#define mdio_delay(mdio_addr) inb(mdio_addr)
+
+enum mii_reg_bits {
+ MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput =
+ 0x0004,
+};
+#define MDIO_EnbIn (0)
+#define MDIO_WRITE0 (MDIO_EnbOutput)
+#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput)
+
+/* Generate the preamble required for initial synchronization and
+ a few older transceivers. */
+static void mdio_sync(long mdio_addr)
+{
+ int bits = 32;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ while (--bits >= 0) {
+ mdio_out(MDIO_WRITE1, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+}
+
+static int
+mdio_read(struct nic *nic __unused, int phy_id, unsigned int location)
+{
+ long mdio_addr = BASE + MIICtrl;
+ int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int i, retval = 0;
+
+ if (sdc->mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval =
+ (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+
+ mdio_out(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ mdio_out(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ retval = (retval << 1) | ((mdio_in(mdio_addr) & MDIO_Data)
+ ? 1 : 0);
+ mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return (retval >> 1) & 0xffff;
+}
+
+static void
+mdio_write(struct nic *nic __unused, int phy_id,
+ unsigned int location, int value)
+{
+ long mdio_addr = BASE + MIICtrl;
+ int mii_cmd =
+ (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+ int i;
+
+ if (sdc->mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval =
+ (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+ mdio_out(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ mdio_out(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return;
+}
+
+static void set_rx_mode(struct nic *nic __unused)
+{
+ int i;
+ u16 mc_filter[4]; /* Multicast hash filter */
+ u32 rx_mode;
+
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+
+ if (sdc->mii_if.full_duplex && sdc->flowctrl)
+ mc_filter[3] |= 0x0200;
+ for (i = 0; i < 4; i++)
+ outw(mc_filter[i], BASE + MulticastFilter0 + i * 2);
+ outb(rx_mode, BASE + RxMode);
+ return;
+}
+
+static struct pci_device_id sundance_nics[] = {
+ PCI_ROM(0x13f0, 0x0201, "sundance", "ST201 Sundance 'Alta' based Adaptor", 0),
+ PCI_ROM(0x1186, 0x1002, "dfe530txs", "D-Link DFE530TXS (Sundance ST201 Alta)", 0),
+ PCI_ROM(0x13f0, 0x0200, "ip100a", "IC+ IP100A", 0),
+};
+
+PCI_DRIVER ( sundance_driver, sundance_nics, PCI_NO_CLASS );
+
+DRIVER ( "SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver,
+ sundance_probe, sundance_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.c
new file mode 100644
index 0000000..e5f04fa
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.c
@@ -0,0 +1,1723 @@
+/**************************************************************************
+*
+* tlan.c -- Etherboot device driver for the Texas Instruments ThunderLAN
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code based on:
+* lan.c: Linux ThunderLan Driver:
+*
+* by James Banks
+*
+* (C) 1997-1998 Caldera, Inc.
+* (C) 1998 James Banks
+* (C) 1999-2001 Torben Mathiasen
+* (C) 2002 Samuel Chessman
+*
+* REVISION HISTORY:
+* ================
+* v1.0 07-08-2003 timlegge Initial not quite working version
+* v1.1 07-27-2003 timlegge Sync 5.0 and 5.1 versions
+* v1.2 08-19-2003 timlegge Implement Multicast Support
+* v1.3 08-23-2003 timlegge Fix the transmit Function
+* v1.4 01-17-2004 timlegge Initial driver output cleanup
+*
+* Indent Options: indent -kr -i8
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+#include <mii.h>
+#include "tlan.h"
+
+#define drv_version "v1.4"
+#define drv_date "01-17-2004"
+
+/* NIC specific static variables go here */
+#define HZ 100
+#define TX_TIME_OUT (6*HZ)
+
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+static void TLan_ResetLists(struct nic *nic __unused);
+static void TLan_ResetAdapter(struct nic *nic __unused);
+static void TLan_FinishReset(struct nic *nic __unused);
+
+static void TLan_EeSendStart(u16);
+static int TLan_EeSendByte(u16, u8, int);
+static void TLan_EeReceiveByte(u16, u8 *, int);
+static int TLan_EeReadByte(u16 io_base, u8, u8 *);
+
+static void TLan_PhyDetect(struct nic *nic);
+static void TLan_PhyPowerDown(struct nic *nic);
+static void TLan_PhyPowerUp(struct nic *nic);
+
+
+static void TLan_SetMac(struct nic *nic __unused, int areg, unsigned char *mac);
+
+static void TLan_PhyReset(struct nic *nic);
+static void TLan_PhyStartLink(struct nic *nic);
+static void TLan_PhyFinishAutoNeg(struct nic *nic);
+
+#ifdef MONITOR
+static void TLan_PhyMonitor(struct nic *nic);
+#endif
+
+
+static void refill_rx(struct nic *nic __unused);
+
+static int TLan_MiiReadReg(struct nic *nic __unused, u16, u16, u16 *);
+static void TLan_MiiSendData(u16, u32, unsigned);
+static void TLan_MiiSync(u16);
+static void TLan_MiiWriteReg(struct nic *nic __unused, u16, u16, u16);
+
+
+static const char *media[] = {
+ "10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ",
+ "100baseTx-FD", "100baseT4", 0
+};
+
+/* This much match tlan_pci_tbl[]! */
+enum tlan_nics {
+ NETEL10 = 0, NETEL100 = 1, NETFLEX3I = 2, THUNDER = 3, NETFLEX3B =
+ 4, NETEL100PI = 5,
+ NETEL100D = 6, NETEL100I = 7, OC2183 = 8, OC2325 = 9, OC2326 =
+ 10, NETELLIGENT_10_100_WS_5100 = 11,
+ NETELLIGENT_10_T2 = 12
+};
+
+struct pci_id_info {
+ const char *name;
+ int nic_id;
+ struct match_info {
+ u32 pci, pci_mask, subsystem, subsystem_mask;
+ u32 revision, revision_mask; /* Only 8 bits. */
+ } id;
+ u32 flags;
+ u16 addrOfs; /* Address Offset */
+};
+
+static const struct pci_id_info tlan_pci_tbl[] = {
+ {"Compaq Netelligent 10 T PCI UTP", NETEL10,
+ {0xae340e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Netelligent 10/100 TX PCI UTP", NETEL100,
+ {0xae320e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Integrated NetFlex-3/P", NETFLEX3I,
+ {0xae350e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq NetFlex-3/P", THUNDER,
+ {0xf1300e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83},
+ {"Compaq NetFlex-3/P", NETFLEX3B,
+ {0xf1500e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq Netelligent Integrated 10/100 TX UTP", NETEL100PI,
+ {0xae430e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Netelligent Dual 10/100 TX PCI UTP", NETEL100D,
+ {0xae400e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq Netelligent 10/100 TX Embedded UTP", NETEL100I,
+ {0xb0110e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Olicom OC-2183/2185", OC2183,
+ {0x0013108d, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_USE_INTERN_10, 0x83},
+ {"Olicom OC-2325", OC2325,
+ {0x0012108d, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_UNMANAGED_PHY, 0xF8},
+ {"Olicom OC-2326", OC2326,
+ {0x0014108d, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_USE_INTERN_10, 0xF8},
+ {"Compaq Netelligent 10/100 TX UTP", NETELLIGENT_10_100_WS_5100,
+ {0xb0300e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {"Compaq Netelligent 10 T/2 PCI UTP/Coax", NETELLIGENT_10_T2,
+ {0xb0120e11, 0xffffffff, 0, 0, 0, 0},
+ TLAN_ADAPTER_NONE, 0x83},
+ {"Compaq NetFlex-3/E", 0, /* EISA card */
+ {0, 0, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED | TLAN_ADAPTER_UNMANAGED_PHY |
+ TLAN_ADAPTER_BIT_RATE_PHY, 0x83},
+ {"Compaq NetFlex-3/E", 0, /* EISA card */
+ {0, 0, 0, 0, 0, 0},
+ TLAN_ADAPTER_ACTIVITY_LED, 0x83},
+ {0, 0,
+ {0, 0, 0, 0, 0, 0},
+ 0, 0},
+};
+
+struct TLanList {
+ u32 forward;
+ u16 cStat;
+ u16 frameSize;
+ struct {
+ u32 count;
+ u32 address;
+ } buffer[TLAN_BUFFERS_PER_LIST];
+};
+
+struct {
+ struct TLanList tx_ring[TLAN_NUM_TX_LISTS];
+ unsigned char txb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_TX_LISTS];
+ struct TLanList rx_ring[TLAN_NUM_RX_LISTS];
+ unsigned char rxb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_RX_LISTS];
+} tlan_buffers __shared;
+#define tx_ring tlan_buffers.tx_ring
+#define txb tlan_buffers.txb
+#define rx_ring tlan_buffers.rx_ring
+#define rxb tlan_buffers.rxb
+
+typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
+
+static int chip_idx;
+
+/*****************************************************************
+* TLAN Private Information Structure
+*
+****************************************************************/
+static struct tlan_private {
+ unsigned short vendor_id; /* PCI Vendor code */
+ unsigned short dev_id; /* PCI Device code */
+ const char *nic_name;
+ unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indicies */
+ unsigned rx_buf_sz; /* Based on mtu + Slack */
+ struct TLanList *txList;
+ u32 txHead;
+ u32 txInProgress;
+ u32 txTail;
+ int eoc;
+ u32 phyOnline;
+ u32 aui;
+ u32 duplex;
+ u32 phy[2];
+ u32 phyNum;
+ u32 speed;
+ u8 tlanRev;
+ u8 tlanFullDuplex;
+ u8 link;
+ u8 neg_be_verbose;
+} TLanPrivateInfo;
+
+static struct tlan_private *priv;
+
+static u32 BASE;
+
+/***************************************************************
+* TLan_ResetLists
+*
+* Returns:
+* Nothing
+* Parms:
+* dev The device structure with the list
+* stuctures to be reset.
+*
+* This routine sets the variables associated with managing
+* the TLAN lists to their initial values.
+*
+**************************************************************/
+
+static void TLan_ResetLists(struct nic *nic __unused)
+{
+
+ int i;
+ struct TLanList *list;
+ priv->txHead = 0;
+ priv->txTail = 0;
+
+ for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
+ list = &tx_ring[i];
+ list->cStat = TLAN_CSTAT_UNUSED;
+ list->buffer[0].address = virt_to_bus(txb +
+ (i * TLAN_MAX_FRAME_SIZE));
+ list->buffer[2].count = 0;
+ list->buffer[2].address = 0;
+ list->buffer[9].address = 0;
+ }
+
+ priv->cur_rx = 0;
+ priv->rx_buf_sz = (TLAN_MAX_FRAME_SIZE);
+// priv->rx_head_desc = &rx_ring[0];
+
+ /* Initialize all the Rx descriptors */
+ for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
+ rx_ring[i].forward = virt_to_le32desc(&rx_ring[i + 1]);
+ rx_ring[i].cStat = TLAN_CSTAT_READY;
+ rx_ring[i].frameSize = TLAN_MAX_FRAME_SIZE;
+ rx_ring[i].buffer[0].count =
+ TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
+ rx_ring[i].buffer[0].address =
+ virt_to_le32desc(&rxb[i * TLAN_MAX_FRAME_SIZE]);
+ rx_ring[i].buffer[1].count = 0;
+ rx_ring[i].buffer[1].address = 0;
+ }
+
+ /* Mark the last entry as wrapping the ring */
+ rx_ring[i - 1].forward = virt_to_le32desc(&rx_ring[0]);
+ priv->dirty_rx = (unsigned int) (i - TLAN_NUM_RX_LISTS);
+
+} /* TLan_ResetLists */
+
+/***************************************************************
+* TLan_Reset
+*
+* Returns:
+* 0
+* Parms:
+* dev Pointer to device structure of adapter
+* to be reset.
+*
+* This function resets the adapter and it's physical
+* device. See Chap. 3, pp. 9-10 of the "ThunderLAN
+* Programmer's Guide" for details. The routine tries to
+* implement what is detailed there, though adjustments
+* have been made.
+*
+**************************************************************/
+
+void TLan_ResetAdapter(struct nic *nic __unused)
+{
+ int i;
+ u32 addr;
+ u32 data;
+ u8 data8;
+
+ priv->tlanFullDuplex = FALSE;
+ priv->phyOnline = 0;
+/* 1. Assert reset bit. */
+
+ data = inl(BASE + TLAN_HOST_CMD);
+ data |= TLAN_HC_AD_RST;
+ outl(data, BASE + TLAN_HOST_CMD);
+
+ udelay(1000);
+
+/* 2. Turn off interrupts. ( Probably isn't necessary ) */
+
+ data = inl(BASE + TLAN_HOST_CMD);
+ data |= TLAN_HC_INT_OFF;
+ outl(data, BASE + TLAN_HOST_CMD);
+/* 3. Clear AREGs and HASHs. */
+
+ for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4) {
+ TLan_DioWrite32(BASE, (u16) i, 0);
+ }
+
+/* 4. Setup NetConfig register. */
+
+ data =
+ TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);
+
+/* 5. Load Ld_Tmr and Ld_Thr in HOST_CMD. */
+
+ outl(TLAN_HC_LD_TMR | 0x3f, BASE + TLAN_HOST_CMD);
+ outl(TLAN_HC_LD_THR | 0x0, BASE + TLAN_HOST_CMD);
+
+/* 6. Unreset the MII by setting NMRST (in NetSio) to 1. */
+
+ outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
+ addr = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
+ TLan_SetBit(TLAN_NET_SIO_NMRST, addr);
+
+/* 7. Setup the remaining registers. */
+
+ if (priv->tlanRev >= 0x30) {
+ data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
+ TLan_DioWrite8(BASE, TLAN_INT_DIS, data8);
+ }
+ TLan_PhyDetect(nic);
+ data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
+
+ if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_BIT_RATE_PHY) {
+ data |= TLAN_NET_CFG_BIT;
+ if (priv->aui == 1) {
+ TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x0a);
+ } else if (priv->duplex == TLAN_DUPLEX_FULL) {
+ TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x00);
+ priv->tlanFullDuplex = TRUE;
+ } else {
+ TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x08);
+ }
+ }
+
+ if (priv->phyNum == 0) {
+ data |= TLAN_NET_CFG_PHY_EN;
+ }
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);
+
+ if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+ TLan_FinishReset(nic);
+ } else {
+ TLan_PhyPowerDown(nic);
+ }
+
+} /* TLan_ResetAdapter */
+
+void TLan_FinishReset(struct nic *nic)
+{
+
+ u8 data;
+ u32 phy;
+ u8 sio;
+ u16 status;
+ u16 partner;
+ u16 tlphy_ctl;
+ u16 tlphy_par;
+ u16 tlphy_id1, tlphy_id2;
+ int i;
+
+ phy = priv->phy[priv->phyNum];
+
+ data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
+ if (priv->tlanFullDuplex) {
+ data |= TLAN_NET_CMD_DUPLEX;
+ }
+ TLan_DioWrite8(BASE, TLAN_NET_CMD, data);
+ data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
+ if (priv->phyNum == 0) {
+ data |= TLAN_NET_MASK_MASK7;
+ }
+ TLan_DioWrite8(BASE, TLAN_NET_MASK, data);
+ TLan_DioWrite16(BASE, TLAN_MAX_RX, ((1536) + 7) & ~7);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID1, &tlphy_id1);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID2, &tlphy_id2);
+
+ if ((tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY)
+ || (priv->aui)) {
+ status = BMSR_LSTATUS;
+ DBG ( "TLAN: %s: Link forced.\n", priv->nic_name );
+ } else {
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ udelay(1000);
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ if ((status & BMSR_LSTATUS) && /* We only support link info on Nat.Sem. PHY's */
+ (tlphy_id1 == NAT_SEM_ID1)
+ && (tlphy_id2 == NAT_SEM_ID2)) {
+ TLan_MiiReadReg(nic, phy, MII_LPA, &partner);
+ TLan_MiiReadReg(nic, phy, TLAN_TLPHY_PAR,
+ &tlphy_par);
+
+ DBG ( "TLAN: %s: Link active with ",
+ priv->nic_name );
+ if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
+ DBG ( "forced 10%sMbps %s-Duplex\n",
+ tlphy_par & TLAN_PHY_SPEED_100 ? ""
+ : "0",
+ tlphy_par & TLAN_PHY_DUPLEX_FULL ?
+ "Full" : "Half" );
+ } else {
+ DBG
+ ( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
+ tlphy_par & TLAN_PHY_SPEED_100 ? "" :
+ "0",
+ tlphy_par & TLAN_PHY_DUPLEX_FULL ?
+ "Full" : "Half" );
+ DBG ( "TLAN: Partner capability: " );
+ for (i = 5; i <= 10; i++)
+ if (partner & (1 << i)) {
+ DBG ( "%s", media[i - 5] );
+ }
+ DBG ( "\n" );
+ }
+
+ TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
+#ifdef MONITOR
+ /* We have link beat..for now anyway */
+ priv->link = 1;
+ /*Enabling link beat monitoring */
+ /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_LINK_BEAT ); */
+ mdelay(10000);
+ TLan_PhyMonitor(nic);
+#endif
+ } else if (status & BMSR_LSTATUS) {
+ DBG ( "TLAN: %s: Link active\n", priv->nic_name );
+ TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
+ }
+ }
+
+ if (priv->phyNum == 0) {
+ TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
+ tlphy_ctl |= TLAN_TC_INTEN;
+ TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tlphy_ctl);
+ sio = TLan_DioRead8(BASE, TLAN_NET_SIO);
+ sio |= TLAN_NET_SIO_MINTEN;
+ TLan_DioWrite8(BASE, TLAN_NET_SIO, sio);
+ }
+
+ if (status & BMSR_LSTATUS) {
+ TLan_SetMac(nic, 0, nic->node_addr);
+ priv->phyOnline = 1;
+ outb((TLAN_HC_INT_ON >> 8), BASE + TLAN_HOST_CMD + 1);
+ outl(virt_to_bus(&rx_ring), BASE + TLAN_CH_PARM);
+ outl(TLAN_HC_GO | TLAN_HC_RT, BASE + TLAN_HOST_CMD);
+ } else {
+ DBG
+ ( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
+ priv->nic_name );
+ /* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_FINISH_RESET ); */
+ mdelay(10000);
+ TLan_FinishReset(nic);
+ return;
+
+ }
+
+} /* TLan_FinishReset */
+
+/**************************************************************************
+POLL - Wait for a frame
+***************************************************************************/
+static int tlan_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ u32 framesize;
+ u32 host_cmd = 0;
+ u32 ack = 1;
+ int eoc = 0;
+ int entry = priv->cur_rx % TLAN_NUM_RX_LISTS;
+ u16 tmpCStat = le32_to_cpu(rx_ring[entry].cStat);
+ u16 host_int = inw(BASE + TLAN_HOST_INT);
+
+ if ((tmpCStat & TLAN_CSTAT_FRM_CMP) && !retrieve)
+ return 1;
+
+ outw(host_int, BASE + TLAN_HOST_INT);
+
+ if (!(tmpCStat & TLAN_CSTAT_FRM_CMP))
+ return 0;
+
+ /* printf("PI-1: 0x%hX\n", host_int); */
+ if (tmpCStat & TLAN_CSTAT_EOC)
+ eoc = 1;
+
+ framesize = rx_ring[entry].frameSize;
+
+ nic->packetlen = framesize;
+
+ DBG ( ".%d.", (unsigned int) framesize );
+
+ memcpy(nic->packet, rxb +
+ (priv->cur_rx * TLAN_MAX_FRAME_SIZE), nic->packetlen);
+
+ rx_ring[entry].cStat = 0;
+
+ DBG ( "%d", entry );
+
+ entry = (entry + 1) % TLAN_NUM_RX_LISTS;
+ priv->cur_rx = entry;
+ if (eoc) {
+ if ((rx_ring[entry].cStat & TLAN_CSTAT_READY) ==
+ TLAN_CSTAT_READY) {
+ ack |= TLAN_HC_GO | TLAN_HC_RT;
+ host_cmd = TLAN_HC_ACK | ack | 0x001C0000;
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+ }
+ } else {
+ host_cmd = TLAN_HC_ACK | ack | (0x000C0000);
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+
+ DBG ( "AC: 0x%hX\n", inw(BASE + TLAN_CH_PARM) );
+ DBG ( "PI-2: 0x%hX\n", inw(BASE + TLAN_HOST_INT) );
+ }
+ refill_rx(nic);
+ return (1); /* initially as this is called to flush the input */
+}
+
+static void refill_rx(struct nic *nic __unused)
+{
+ int entry = 0;
+
+ for (;
+ (priv->cur_rx - priv->dirty_rx +
+ TLAN_NUM_RX_LISTS) % TLAN_NUM_RX_LISTS > 0;
+ priv->dirty_rx = (priv->dirty_rx + 1) % TLAN_NUM_RX_LISTS) {
+ entry = priv->dirty_rx % TLAN_NUM_TX_LISTS;
+ rx_ring[entry].frameSize = TLAN_MAX_FRAME_SIZE;
+ rx_ring[entry].cStat = TLAN_CSTAT_READY;
+ }
+
+}
+
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static void tlan_transmit(struct nic *nic, const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p)
+{ /* Packet */
+ u16 nstype;
+ u32 to;
+ struct TLanList *tail_list;
+ struct TLanList *head_list;
+ u8 *tail_buffer;
+ u32 ack = 0;
+ u32 host_cmd;
+ int eoc = 0;
+ u16 tmpCStat;
+ u16 host_int = inw(BASE + TLAN_HOST_INT);
+
+ int entry = 0;
+
+ DBG ( "INT0-0x%hX\n", host_int );
+
+ if (!priv->phyOnline) {
+ printf("TRANSMIT: %s PHY is not ready\n", priv->nic_name);
+ return;
+ }
+
+ tail_list = priv->txList + priv->txTail;
+
+ if (tail_list->cStat != TLAN_CSTAT_UNUSED) {
+ printf("TRANSMIT: %s is busy (Head=%p Tail=%x)\n",
+ priv->nic_name, priv->txList, (unsigned int) priv->txTail);
+ tx_ring[entry].cStat = TLAN_CSTAT_UNUSED;
+// priv->txBusyCount++;
+ return;
+ }
+
+ tail_list->forward = 0;
+
+ tail_buffer = txb + (priv->txTail * TLAN_MAX_FRAME_SIZE);
+
+ /* send the packet to destination */
+ memcpy(tail_buffer, d, ETH_ALEN);
+ memcpy(tail_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(tail_buffer + 2 * ETH_ALEN, (u8 *) & nstype, 2);
+ memcpy(tail_buffer + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+ while (s < ETH_ZLEN)
+ tail_buffer[s++] = '\0';
+
+ /*=====================================================*/
+ /* Receive
+ * 0000 0000 0001 1100
+ * 0000 0000 0000 1100
+ * 0000 0000 0000 0011 = 0x0003
+ *
+ * 0000 0000 0000 0000 0000 0000 0000 0011
+ * 0000 0000 0000 1100 0000 0000 0000 0000 = 0x000C0000
+ *
+ * Transmit
+ * 0000 0000 0001 1100
+ * 0000 0000 0000 0100
+ * 0000 0000 0000 0001 = 0x0001
+ *
+ * 0000 0000 0000 0000 0000 0000 0000 0001
+ * 0000 0000 0000 0100 0000 0000 0000 0000 = 0x00040000
+ * */
+
+ /* Setup the transmit descriptor */
+ tail_list->frameSize = (u16) s;
+ tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) s;
+ tail_list->buffer[1].count = 0;
+ tail_list->buffer[1].address = 0;
+
+ tail_list->cStat = TLAN_CSTAT_READY;
+
+ DBG ( "INT1-0x%hX\n", inw(BASE + TLAN_HOST_INT) );
+
+ if (!priv->txInProgress) {
+ priv->txInProgress = 1;
+ outl(virt_to_le32desc(tail_list), BASE + TLAN_CH_PARM);
+ outl(TLAN_HC_GO, BASE + TLAN_HOST_CMD);
+ } else {
+ if (priv->txTail == 0) {
+ DBG ( "Out buffer\n" );
+ (priv->txList + (TLAN_NUM_TX_LISTS - 1))->forward =
+ virt_to_le32desc(tail_list);
+ } else {
+ DBG ( "Fix this \n" );
+ (priv->txList + (priv->txTail - 1))->forward =
+ virt_to_le32desc(tail_list);
+ }
+ }
+
+ CIRC_INC(priv->txTail, TLAN_NUM_TX_LISTS);
+
+ DBG ( "INT2-0x%hX\n", inw(BASE + TLAN_HOST_INT) );
+
+ to = currticks() + TX_TIME_OUT;
+ while ((tail_list->cStat == TLAN_CSTAT_READY) && currticks() < to);
+
+ head_list = priv->txList + priv->txHead;
+ while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP)
+ && (ack < 255)) {
+ ack++;
+ if(tmpCStat & TLAN_CSTAT_EOC)
+ eoc =1;
+ head_list->cStat = TLAN_CSTAT_UNUSED;
+ CIRC_INC(priv->txHead, TLAN_NUM_TX_LISTS);
+ head_list = priv->txList + priv->txHead;
+
+ }
+ if(!ack)
+ printf("Incomplete TX Frame\n");
+
+ if(eoc) {
+ head_list = priv->txList + priv->txHead;
+ if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
+ outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
+ ack |= TLAN_HC_GO;
+ } else {
+ priv->txInProgress = 0;
+ }
+ }
+ if(ack) {
+ host_cmd = TLAN_HC_ACK | ack;
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+ }
+
+ if(priv->tlanRev < 0x30 ) {
+ ack = 1;
+ head_list = priv->txList + priv->txHead;
+ if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
+ outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
+ ack |= TLAN_HC_GO;
+ } else {
+ priv->txInProgress = 0;
+ }
+ host_cmd = TLAN_HC_ACK | ack | 0x00140000;
+ outl(host_cmd, BASE + TLAN_HOST_CMD);
+
+ }
+
+ if (currticks() >= to) {
+ printf("TX Time Out");
+ }
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void tlan_disable ( struct nic *nic __unused ) {
+ /* put the card in its initial state */
+ /* This function serves 3 purposes.
+ * This disables DMA and interrupts so we don't receive
+ * unexpected packets or interrupts from the card after
+ * etherboot has finished.
+ * This frees resources so etherboot may use
+ * this driver on another interface
+ * This allows etherboot to reinitialize the interface
+ * if something is something goes wrong.
+ *
+ */
+ outl(TLAN_HC_AD_RST, BASE + TLAN_HOST_CMD);
+}
+
+/**************************************************************************
+IRQ - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void tlan_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations tlan_operations = {
+ .connect = dummy_connect,
+ .poll = tlan_poll,
+ .transmit = tlan_transmit,
+ .irq = tlan_irq,
+
+};
+
+static void TLan_SetMulticastList(struct nic *nic) {
+ int i;
+ u8 tmp;
+
+ /* !IFF_PROMISC */
+ tmp = TLan_DioRead8(BASE, TLAN_NET_CMD);
+ TLan_DioWrite8(BASE, TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF);
+
+ /* IFF_ALLMULTI */
+ for(i = 0; i< 3; i++)
+ TLan_SetMac(nic, i + 1, NULL);
+ TLan_DioWrite32(BASE, TLAN_HASH_1, 0xFFFFFFFF);
+ TLan_DioWrite32(BASE, TLAN_HASH_2, 0xFFFFFFFF);
+
+
+}
+/**************************************************************************
+PROBE - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+
+#define board_found 1
+#define valid_link 0
+static int tlan_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ u16 data = 0;
+ int err;
+ int i;
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ nic->irqno = 0;
+ nic->ioaddr = pci->ioaddr;
+
+ BASE = pci->ioaddr;
+
+ /* Set nic as PCI bus master */
+ adjust_pci_device(pci);
+
+ /* Point to private storage */
+ priv = &TLanPrivateInfo;
+
+ /* Figure out which chip we're dealing with */
+ i = 0;
+ chip_idx = -1;
+ while (tlan_pci_tbl[i].name) {
+ if ((((u32) pci->device << 16) | pci->vendor) ==
+ (tlan_pci_tbl[i].id.pci & 0xffffffff)) {
+ chip_idx = i;
+ break;
+ }
+ i++;
+ }
+
+ priv->vendor_id = pci->vendor;
+ priv->dev_id = pci->device;
+ priv->nic_name = pci->driver_name;
+ priv->eoc = 0;
+
+ err = 0;
+ for (i = 0; i < 6; i++)
+ err |= TLan_EeReadByte(BASE,
+ (u8) tlan_pci_tbl[chip_idx].
+ addrOfs + i,
+ (u8 *) & nic->node_addr[i]);
+ if (err) {
+ printf ( "TLAN: %s: Error reading MAC from eeprom: %d\n",
+ pci->driver_name, err);
+ } else {
+ DBG ( "%s: %s at ioaddr %#lX, ",
+ pci->driver_name, eth_ntoa ( nic->node_addr ), pci->ioaddr );
+ }
+
+ priv->tlanRev = TLan_DioRead8(BASE, TLAN_DEF_REVISION);
+ printf("revision: 0x%hX\n", priv->tlanRev);
+
+ TLan_ResetLists(nic);
+ TLan_ResetAdapter(nic);
+
+ data = inl(BASE + TLAN_HOST_CMD);
+ data |= TLAN_HC_INT_OFF;
+ outw(data, BASE + TLAN_HOST_CMD);
+
+ TLan_SetMulticastList(nic);
+ udelay(100);
+ priv->txList = tx_ring;
+
+/* if (board_found && valid_link)
+ {*/
+ /* point to NIC specific routines */
+ nic->nic_op = &tlan_operations;
+ return 1;
+}
+
+
+/*****************************************************************************
+******************************************************************************
+
+ ThunderLAN Driver Eeprom routines
+
+ The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
+ EEPROM. These functions are based on information in Microchip's
+ data sheet. I don't know how well this functions will work with
+ other EEPROMs.
+
+******************************************************************************
+*****************************************************************************/
+
+
+/***************************************************************
+* TLan_EeSendStart
+*
+* Returns:
+* Nothing
+* Parms:
+* io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+*
+* This function sends a start cycle to an EEPROM attached
+* to a TLAN chip.
+*
+**************************************************************/
+
+void TLan_EeSendStart(u16 io_base)
+{
+ u16 sio;
+
+ outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
+ sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+
+} /* TLan_EeSendStart */
+
+/***************************************************************
+* TLan_EeSendByte
+*
+* Returns:
+* If the correct ack was received, 0, otherwise 1
+* Parms: io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+* data The 8 bits of information to
+* send to the EEPROM.
+* stop If TLAN_EEPROM_STOP is passed, a
+* stop cycle is sent after the
+* byte is sent after the ack is
+* read.
+*
+* This function sends a byte on the serial EEPROM line,
+* driving the clock to send each bit. The function then
+* reverses transmission direction and reads an acknowledge
+* bit.
+*
+**************************************************************/
+
+int TLan_EeSendByte(u16 io_base, u8 data, int stop)
+{
+ int err;
+ u8 place;
+ u16 sio;
+
+ outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
+ sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ /* Assume clock is low, tx is enabled; */
+ for (place = 0x80; place != 0; place >>= 1) {
+ if (place & data)
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ else
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ }
+ TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ err = TLan_GetBit(TLAN_NET_SIO_EDATA, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
+
+ if ((!err) && stop) {
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ }
+
+ return (err);
+
+} /* TLan_EeSendByte */
+
+/***************************************************************
+* TLan_EeReceiveByte
+*
+* Returns:
+* Nothing
+* Parms:
+* io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+* data An address to a char to hold the
+* data sent from the EEPROM.
+* stop If TLAN_EEPROM_STOP is passed, a
+* stop cycle is sent after the
+* byte is received, and no ack is
+* sent.
+*
+* This function receives 8 bits of data from the EEPROM
+* over the serial link. It then sends and ack bit, or no
+* ack and a stop bit. This function is used to retrieve
+* data after the address of a byte in the EEPROM has been
+* sent.
+*
+**************************************************************/
+
+void TLan_EeReceiveByte(u16 io_base, u8 * data, int stop)
+{
+ u8 place;
+ u16 sio;
+
+ outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
+ sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
+ *data = 0;
+
+ /* Assume clock is low, tx is enabled; */
+ TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
+ for (place = 0x80; place; place >>= 1) {
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ if (TLan_GetBit(TLAN_NET_SIO_EDATA, sio))
+ *data |= place;
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ }
+
+ TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
+ if (!stop) {
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* Ack = 0 */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ } else {
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio); /* No ack = 1 (?) */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */
+ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
+ TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
+ }
+
+} /* TLan_EeReceiveByte */
+
+/***************************************************************
+* TLan_EeReadByte
+*
+* Returns:
+* No error = 0, else, the stage at which the error
+* occurred.
+* Parms:
+* io_base The IO port base address for the
+* TLAN device with the EEPROM to
+* use.
+* ee_addr The address of the byte in the
+* EEPROM whose contents are to be
+* retrieved.
+* data An address to a char to hold the
+* data obtained from the EEPROM.
+*
+* This function reads a byte of information from an byte
+* cell in the EEPROM.
+*
+**************************************************************/
+
+int TLan_EeReadByte(u16 io_base, u8 ee_addr, u8 * data)
+{
+ int err;
+ int ret = 0;
+
+
+ TLan_EeSendStart(io_base);
+ err = TLan_EeSendByte(io_base, 0xA0, TLAN_EEPROM_ACK);
+ if (err) {
+ ret = 1;
+ goto fail;
+ }
+ err = TLan_EeSendByte(io_base, ee_addr, TLAN_EEPROM_ACK);
+ if (err) {
+ ret = 2;
+ goto fail;
+ }
+ TLan_EeSendStart(io_base);
+ err = TLan_EeSendByte(io_base, 0xA1, TLAN_EEPROM_ACK);
+ if (err) {
+ ret = 3;
+ goto fail;
+ }
+ TLan_EeReceiveByte(io_base, data, TLAN_EEPROM_STOP);
+ fail:
+
+ return ret;
+
+} /* TLan_EeReadByte */
+
+
+/*****************************************************************************
+******************************************************************************
+
+ThunderLAN Driver MII Routines
+
+These routines are based on the information in Chap. 2 of the
+"ThunderLAN Programmer's Guide", pp. 15-24.
+
+******************************************************************************
+*****************************************************************************/
+
+
+/***************************************************************
+* TLan_MiiReadReg
+*
+* Returns:
+* 0 if ack received ok
+* 1 otherwise.
+*
+* Parms:
+* dev The device structure containing
+* The io address and interrupt count
+* for this device.
+* phy The address of the PHY to be queried.
+* reg The register whose contents are to be
+* retreived.
+* val A pointer to a variable to store the
+* retrieved value.
+*
+* This function uses the TLAN's MII bus to retreive the contents
+* of a given register on a PHY. It sends the appropriate info
+* and then reads the 16-bit register value from the MII bus via
+* the TLAN SIO register.
+*
+**************************************************************/
+
+int TLan_MiiReadReg(struct nic *nic __unused, u16 phy, u16 reg, u16 * val)
+{
+ u8 nack;
+ u16 sio, tmp;
+ u32 i;
+ int err;
+ int minten;
+
+ err = FALSE;
+ outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
+ sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_MiiSync(BASE);
+
+ minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
+ if (minten)
+ TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
+
+ TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */
+ TLan_MiiSendData(BASE, 0x2, 2); /* Read ( 10b ) */
+ TLan_MiiSendData(BASE, phy, 5); /* Device # */
+ TLan_MiiSendData(BASE, reg, 5); /* Register # */
+
+
+ TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */
+
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Clock Idle bit */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Wait 300ns */
+
+ nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio); /* Check for ACK */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio); /* Finish ACK */
+ if (nack) { /* No ACK, so fake it */
+ for (i = 0; i < 16; i++) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+ tmp = 0xffff;
+ err = TRUE;
+ } else { /* ACK, so read data */
+ for (tmp = 0, i = 0x8000; i; i >>= 1) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
+ tmp |= i;
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+ }
+
+
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+
+ if (minten)
+ TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
+
+ *val = tmp;
+
+ return err;
+
+} /* TLan_MiiReadReg */
+
+/***************************************************************
+* TLan_MiiSendData
+*
+* Returns:
+* Nothing
+* Parms:
+* base_port The base IO port of the adapter in
+* question.
+* dev The address of the PHY to be queried.
+* data The value to be placed on the MII bus.
+* num_bits The number of bits in data that are to
+* be placed on the MII bus.
+*
+* This function sends on sequence of bits on the MII
+* configuration bus.
+*
+**************************************************************/
+
+void TLan_MiiSendData(u16 base_port, u32 data, unsigned num_bits)
+{
+ u16 sio;
+ u32 i;
+
+ if (num_bits == 0)
+ return;
+
+ outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
+ sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
+ TLan_SetBit(TLAN_NET_SIO_MTXEN, sio);
+
+ for (i = (0x1 << (num_bits - 1)); i; i >>= 1) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
+ if (data & i)
+ TLan_SetBit(TLAN_NET_SIO_MDATA, sio);
+ else
+ TLan_ClearBit(TLAN_NET_SIO_MDATA, sio);
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+
+} /* TLan_MiiSendData */
+
+/***************************************************************
+* TLan_MiiSync
+*
+* Returns:
+* Nothing
+* Parms:
+* base_port The base IO port of the adapter in
+* question.
+*
+* This functions syncs all PHYs in terms of the MII configuration
+* bus.
+*
+**************************************************************/
+
+void TLan_MiiSync(u16 base_port)
+{
+ int i;
+ u16 sio;
+
+ outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
+ sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);
+ for (i = 0; i < 32; i++) {
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+ }
+
+} /* TLan_MiiSync */
+
+/***************************************************************
+* TLan_MiiWriteReg
+*
+* Returns:
+* Nothing
+* Parms:
+* dev The device structure for the device
+* to write to.
+* phy The address of the PHY to be written to.
+* reg The register whose contents are to be
+* written.
+* val The value to be written to the register.
+*
+* This function uses the TLAN's MII bus to write the contents of a
+* given register on a PHY. It sends the appropriate info and then
+* writes the 16-bit register value from the MII configuration bus
+* via the TLAN SIO register.
+*
+**************************************************************/
+
+void TLan_MiiWriteReg(struct nic *nic __unused, u16 phy, u16 reg, u16 val)
+{
+ u16 sio;
+ int minten;
+
+ outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
+ sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
+
+ TLan_MiiSync(BASE);
+
+ minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
+ if (minten)
+ TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
+
+ TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */
+ TLan_MiiSendData(BASE, 0x1, 2); /* Write ( 01b ) */
+ TLan_MiiSendData(BASE, phy, 5); /* Device # */
+ TLan_MiiSendData(BASE, reg, 5); /* Register # */
+
+ TLan_MiiSendData(BASE, 0x2, 2); /* Send ACK */
+ TLan_MiiSendData(BASE, val, 16); /* Send Data */
+
+ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
+ TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+
+ if (minten)
+ TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
+
+
+} /* TLan_MiiWriteReg */
+
+/***************************************************************
+* TLan_SetMac
+*
+* Returns:
+* Nothing
+* Parms:
+* dev Pointer to device structure of adapter
+* on which to change the AREG.
+* areg The AREG to set the address in (0 - 3).
+* mac A pointer to an array of chars. Each
+* element stores one byte of the address.
+* IE, it isn't in ascii.
+*
+* This function transfers a MAC address to one of the
+* TLAN AREGs (address registers). The TLAN chip locks
+* the register on writing to offset 0 and unlocks the
+* register after writing to offset 5. If NULL is passed
+* in mac, then the AREG is filled with 0's.
+*
+**************************************************************/
+
+void TLan_SetMac(struct nic *nic __unused, int areg, unsigned char *mac)
+{
+ int i;
+
+ areg *= 6;
+
+ if (mac != NULL) {
+ for (i = 0; i < 6; i++)
+ TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i,
+ mac[i]);
+ } else {
+ for (i = 0; i < 6; i++)
+ TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, 0);
+ }
+
+} /* TLan_SetMac */
+
+/*********************************************************************
+* TLan_PhyDetect
+*
+* Returns:
+* Nothing
+* Parms:
+* dev A pointer to the device structure of the adapter
+* for which the PHY needs determined.
+*
+* So far I've found that adapters which have external PHYs
+* may also use the internal PHY for part of the functionality.
+* (eg, AUI/Thinnet). This function finds out if this TLAN
+* chip has an internal PHY, and then finds the first external
+* PHY (starting from address 0) if it exists).
+*
+********************************************************************/
+
+void TLan_PhyDetect(struct nic *nic)
+{
+ u16 control;
+ u16 hi;
+ u16 lo;
+ u32 phy;
+
+ if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+ priv->phyNum = 0xFFFF;
+ return;
+ }
+
+ TLan_MiiReadReg(nic, TLAN_PHY_MAX_ADDR, MII_PHYSID1, &hi);
+
+ if (hi != 0xFFFF) {
+ priv->phy[0] = TLAN_PHY_MAX_ADDR;
+ } else {
+ priv->phy[0] = TLAN_PHY_NONE;
+ }
+
+ priv->phy[1] = TLAN_PHY_NONE;
+ for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {
+ TLan_MiiReadReg(nic, phy, MII_BMCR, &control);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID1, &hi);
+ TLan_MiiReadReg(nic, phy, MII_PHYSID2, &lo);
+ if ((control != 0xFFFF) || (hi != 0xFFFF)
+ || (lo != 0xFFFF)) {
+ printf("PHY found at %hX %hX %hX %hX\n",
+ (unsigned int) phy, control, hi, lo);
+ if ((priv->phy[1] == TLAN_PHY_NONE)
+ && (phy != TLAN_PHY_MAX_ADDR)) {
+ priv->phy[1] = phy;
+ }
+ }
+ }
+
+ if (priv->phy[1] != TLAN_PHY_NONE) {
+ priv->phyNum = 1;
+ } else if (priv->phy[0] != TLAN_PHY_NONE) {
+ priv->phyNum = 0;
+ } else {
+ printf
+ ("TLAN: Cannot initialize device, no PHY was found!\n");
+ }
+
+} /* TLan_PhyDetect */
+
+void TLan_PhyPowerDown(struct nic *nic)
+{
+
+ u16 value;
+ DBG ( "%s: Powering down PHY(s).\n", priv->nic_name );
+ value = BMCR_PDOWN | BMCR_LOOPBACK | BMCR_ISOLATE;
+ TLan_MiiSync(BASE);
+ TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_BMCR, value);
+ if ((priv->phyNum == 0) && (priv->phy[1] != TLAN_PHY_NONE)
+ &&
+ (!(tlan_pci_tbl[chip_idx].
+ flags & TLAN_ADAPTER_USE_INTERN_10))) {
+ TLan_MiiSync(BASE);
+ TLan_MiiWriteReg(nic, priv->phy[1], MII_BMCR, value);
+ }
+
+ /* Wait for 50 ms and powerup
+ * This is abitrary. It is intended to make sure the
+ * tranceiver settles.
+ */
+ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP ); */
+ mdelay(50);
+ TLan_PhyPowerUp(nic);
+
+} /* TLan_PhyPowerDown */
+
+
+void TLan_PhyPowerUp(struct nic *nic)
+{
+ u16 value;
+
+ DBG ( "%s: Powering up PHY.\n", priv->nic_name );
+ TLan_MiiSync(BASE);
+ value = BMCR_LOOPBACK;
+ TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_BMCR, value);
+ TLan_MiiSync(BASE);
+ /* Wait for 500 ms and reset the
+ * tranceiver. The TLAN docs say both 50 ms and
+ * 500 ms, so do the longer, just in case.
+ */
+ mdelay(500);
+ TLan_PhyReset(nic);
+ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET ); */
+
+} /* TLan_PhyPowerUp */
+
+void TLan_PhyReset(struct nic *nic)
+{
+ u16 phy;
+ u16 value;
+
+ phy = priv->phy[priv->phyNum];
+
+ DBG ( "%s: Reseting PHY.\n", priv->nic_name );
+ TLan_MiiSync(BASE);
+ value = BMCR_LOOPBACK | BMCR_RESET;
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, value);
+ TLan_MiiReadReg(nic, phy, MII_BMCR, &value);
+ while (value & BMCR_RESET) {
+ TLan_MiiReadReg(nic, phy, MII_BMCR, &value);
+ }
+
+ /* Wait for 500 ms and initialize.
+ * I don't remember why I wait this long.
+ * I've changed this to 50ms, as it seems long enough.
+ */
+ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); */
+ mdelay(50);
+ TLan_PhyStartLink(nic);
+
+} /* TLan_PhyReset */
+
+
+void TLan_PhyStartLink(struct nic *nic)
+{
+
+ u16 ability;
+ u16 control;
+ u16 data;
+ u16 phy;
+ u16 status;
+ u16 tctl;
+
+ phy = priv->phy[priv->phyNum];
+ DBG ( "%s: Trying to activate link.\n", priv->nic_name );
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &ability);
+
+ if ((status & BMSR_ANEGCAPABLE) && (!priv->aui)) {
+ ability = status >> 11;
+ if (priv->speed == TLAN_SPEED_10 &&
+ priv->duplex == TLAN_DUPLEX_HALF) {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x0000);
+ } else if (priv->speed == TLAN_SPEED_10 &&
+ priv->duplex == TLAN_DUPLEX_FULL) {
+ priv->tlanFullDuplex = TRUE;
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x0100);
+ } else if (priv->speed == TLAN_SPEED_100 &&
+ priv->duplex == TLAN_DUPLEX_HALF) {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x2000);
+ } else if (priv->speed == TLAN_SPEED_100 &&
+ priv->duplex == TLAN_DUPLEX_FULL) {
+ priv->tlanFullDuplex = TRUE;
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x2100);
+ } else {
+
+ /* Set Auto-Neg advertisement */
+ TLan_MiiWriteReg(nic, phy, MII_ADVERTISE,
+ (ability << 5) | 1);
+ /* Enablee Auto-Neg */
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x1000);
+ /* Restart Auto-Neg */
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, 0x1200);
+ /* Wait for 4 sec for autonegotiation
+ * to complete. The max spec time is less than this
+ * but the card need additional time to start AN.
+ * .5 sec should be plenty extra.
+ */
+ DBG ( "TLAN: %s: Starting autonegotiation.\n",
+ priv->nic_name );
+ mdelay(4000);
+ TLan_PhyFinishAutoNeg(nic);
+ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
+ return;
+ }
+
+ }
+
+ if ((priv->aui) && (priv->phyNum != 0)) {
+ priv->phyNum = 0;
+ data =
+ TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
+ TLAN_NET_CFG_PHY_EN;
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
+ mdelay(50);
+ /* TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
+ TLan_PhyPowerDown(nic);
+ return;
+ } else if (priv->phyNum == 0) {
+ control = 0;
+ TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tctl);
+ if (priv->aui) {
+ tctl |= TLAN_TC_AUISEL;
+ } else {
+ tctl &= ~TLAN_TC_AUISEL;
+ if (priv->duplex == TLAN_DUPLEX_FULL) {
+ control |= BMCR_FULLDPLX;
+ priv->tlanFullDuplex = TRUE;
+ }
+ if (priv->speed == TLAN_SPEED_100) {
+ control |= BMCR_SPEED100;
+ }
+ }
+ TLan_MiiWriteReg(nic, phy, MII_BMCR, control);
+ TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tctl);
+ }
+
+ /* Wait for 2 sec to give the tranceiver time
+ * to establish link.
+ */
+ /* TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET ); */
+ mdelay(2000);
+ TLan_FinishReset(nic);
+
+} /* TLan_PhyStartLink */
+
+void TLan_PhyFinishAutoNeg(struct nic *nic)
+{
+
+ u16 an_adv;
+ u16 an_lpa;
+ u16 data;
+ u16 mode;
+ u16 phy;
+ u16 status;
+
+ phy = priv->phy[priv->phyNum];
+
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+ udelay(1000);
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &status);
+
+ if (!(status & BMSR_ANEGCOMPLETE)) {
+ /* Wait for 8 sec to give the process
+ * more time. Perhaps we should fail after a while.
+ */
+ if (!priv->neg_be_verbose++) {
+ printf
+ ("TLAN: Giving autonegotiation more time.\n");
+ printf
+ ("TLAN: Please check that your adapter has\n");
+ printf
+ ("TLAN: been properly connected to a HUB or Switch.\n");
+ printf
+ ("TLAN: Trying to establish link in the background...\n");
+ }
+ mdelay(8000);
+ TLan_PhyFinishAutoNeg(nic);
+ /* TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
+ return;
+ }
+
+ DBG ( "TLAN: %s: Autonegotiation complete.\n", priv->nic_name );
+ TLan_MiiReadReg(nic, phy, MII_ADVERTISE, &an_adv);
+ TLan_MiiReadReg(nic, phy, MII_LPA, &an_lpa);
+ mode = an_adv & an_lpa & 0x03E0;
+ if (mode & 0x0100) {
+ printf("Full Duplex\n");
+ priv->tlanFullDuplex = TRUE;
+ } else if (!(mode & 0x0080) && (mode & 0x0040)) {
+ priv->tlanFullDuplex = TRUE;
+ printf("Full Duplex\n");
+ }
+
+ if ((!(mode & 0x0180))
+ && (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_USE_INTERN_10)
+ && (priv->phyNum != 0)) {
+ priv->phyNum = 0;
+ data =
+ TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
+ TLAN_NET_CFG_PHY_EN;
+ TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
+ /* TLan_SetTimer( nic, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
+ mdelay(400);
+ TLan_PhyPowerDown(nic);
+ return;
+ }
+
+ if (priv->phyNum == 0) {
+ if ((priv->duplex == TLAN_DUPLEX_FULL)
+ || (an_adv & an_lpa & 0x0040)) {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR,
+ BMCR_ANENABLE | BMCR_FULLDPLX);
+ DBG
+ ( "TLAN: Starting internal PHY with FULL-DUPLEX\n" );
+ } else {
+ TLan_MiiWriteReg(nic, phy, MII_BMCR,
+ BMCR_ANENABLE);
+ DBG
+ ( "TLAN: Starting internal PHY with HALF-DUPLEX\n" );
+ }
+ }
+
+ /* Wait for 100 ms. No reason in partiticular.
+ */
+ /* TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); */
+ mdelay(100);
+ TLan_FinishReset(nic);
+
+} /* TLan_PhyFinishAutoNeg */
+
+#ifdef MONITOR
+
+/*********************************************************************
+*
+* TLan_phyMonitor
+*
+* Returns:
+* None
+*
+* Params:
+* dev The device structure of this device.
+*
+*
+* This function monitors PHY condition by reading the status
+* register via the MII bus. This can be used to give info
+* about link changes (up/down), and possible switch to alternate
+* media.
+*
+********************************************************************/
+
+void TLan_PhyMonitor(struct net_device *dev)
+{
+ TLanPrivateInfo *priv = dev->priv;
+ u16 phy;
+ u16 phy_status;
+
+ phy = priv->phy[priv->phyNum];
+
+ /* Get PHY status register */
+ TLan_MiiReadReg(nic, phy, MII_BMSR, &phy_status);
+
+ /* Check if link has been lost */
+ if (!(phy_status & BMSR_LSTATUS)) {
+ if (priv->link) {
+ priv->link = 0;
+ printf("TLAN: %s has lost link\n", priv->nic_name);
+ priv->flags &= ~IFF_RUNNING;
+ mdelay(2000);
+ TLan_PhyMonitor(nic);
+ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */
+ return;
+ }
+ }
+
+ /* Link restablished? */
+ if ((phy_status & BMSR_LSTATUS) && !priv->link) {
+ priv->link = 1;
+ printf("TLAN: %s has reestablished link\n",
+ priv->nic_name);
+ priv->flags |= IFF_RUNNING;
+ }
+
+ /* Setup a new monitor */
+ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */
+ mdelay(2000);
+ TLan_PhyMonitor(nic);
+}
+
+#endif /* MONITOR */
+
+static struct pci_device_id tlan_nics[] = {
+ PCI_ROM(0x0e11, 0xae34, "netel10", "Compaq Netelligent 10 T PCI UTP", 0),
+ PCI_ROM(0x0e11, 0xae32, "netel100","Compaq Netelligent 10/100 TX PCI UTP", 0),
+ PCI_ROM(0x0e11, 0xae35, "netflex3i", "Compaq Integrated NetFlex-3/P", 0),
+ PCI_ROM(0x0e11, 0xf130, "thunder", "Compaq NetFlex-3/P", 0),
+ PCI_ROM(0x0e11, 0xf150, "netflex3b", "Compaq NetFlex-3/P", 0),
+ PCI_ROM(0x0e11, 0xae43, "netel100pi", "Compaq Netelligent Integrated 10/100 TX UTP", 0),
+ PCI_ROM(0x0e11, 0xae40, "netel100d", "Compaq Netelligent Dual 10/100 TX PCI UTP", 0),
+ PCI_ROM(0x0e11, 0xb011, "netel100i", "Compaq Netelligent 10/100 TX Embedded UTP", 0),
+ PCI_ROM(0x108d, 0x0013, "oc2183", "Olicom OC-2183/2185", 0),
+ PCI_ROM(0x108d, 0x0012, "oc2325", "Olicom OC-2325", 0),
+ PCI_ROM(0x108d, 0x0014, "oc2326", "Olicom OC-2326", 0),
+ PCI_ROM(0x0e11, 0xb030, "netelligent_10_100_ws_5100", "Compaq Netelligent 10/100 TX UTP", 0),
+ PCI_ROM(0x0e11, 0xb012, "netelligent_10_t2", "Compaq Netelligent 10 T/2 PCI UTP/Coax", 0),
+};
+
+PCI_DRIVER ( tlan_driver, tlan_nics, PCI_NO_CLASS );
+
+DRIVER ( "TLAN/PCI", nic_driver, pci_driver, tlan_driver,
+ tlan_probe, tlan_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.h b/debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.h
new file mode 100644
index 0000000..31b3c8f
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/tlan.h
@@ -0,0 +1,491 @@
+/**************************************************************************
+*
+* tlan.c -- Etherboot device driver for the Texas Instruments ThunderLAN
+* Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code (almost all) based on:
+* tlan.c: Linux ThunderLan Driver:
+*
+* by James Banks
+*
+* (C) 1997-1998 Caldera, Inc.
+* (C) 1998 James Banks
+* (C) 1999-2001 Torben Mathiasen
+* (C) 2002 Samuel Chessman
+*
+* REVISION HISTORY:
+* ================
+* v1.0 07-08-2003 timlegge Initial not quite working version
+*
+* Indent Style: indent -kr -i8
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*****************************************************************
+* TLan Definitions
+*
+****************************************************************/
+
+#define FALSE 0
+#define TRUE 1
+
+#define TLAN_MIN_FRAME_SIZE 64
+#define TLAN_MAX_FRAME_SIZE 1600
+
+#define TLAN_NUM_RX_LISTS 4
+#define TLAN_NUM_TX_LISTS 2
+
+#define TLAN_IGNORE 0
+#define TLAN_RECORD 1
+/*
+#define TLAN_DBG(lvl, format, args...) if (debug&lvl) printf("TLAN: " format, ##args );
+*/
+#define TLAN_DEBUG_GNRL 0x0001
+#define TLAN_DEBUG_TX 0x0002
+#define TLAN_DEBUG_RX 0x0004
+#define TLAN_DEBUG_LIST 0x0008
+#define TLAN_DEBUG_PROBE 0x0010
+
+#define TX_TIMEOUT (10*HZ) /* We need time for auto-neg */
+#define MAX_TLAN_BOARDS 8 /* Max number of boards installed at a time */
+
+
+ /*****************************************************************
+ * Device Identification Definitions
+ *
+ ****************************************************************/
+
+#define PCI_DEVICE_ID_NETELLIGENT_10_T2 0xB012
+#define PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100 0xB030
+#ifndef PCI_DEVICE_ID_OLICOM_OC2183
+#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013
+#endif
+#ifndef PCI_DEVICE_ID_OLICOM_OC2325
+#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012
+#endif
+#ifndef PCI_DEVICE_ID_OLICOM_OC2326
+#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014
+#endif
+
+typedef struct tlan_adapter_entry {
+ u16 vendorId;
+ u16 deviceId;
+ char *deviceLabel;
+ u32 flags;
+ u16 addrOfs;
+} TLanAdapterEntry;
+
+#define TLAN_ADAPTER_NONE 0x00000000
+#define TLAN_ADAPTER_UNMANAGED_PHY 0x00000001
+#define TLAN_ADAPTER_BIT_RATE_PHY 0x00000002
+#define TLAN_ADAPTER_USE_INTERN_10 0x00000004
+#define TLAN_ADAPTER_ACTIVITY_LED 0x00000008
+
+#define TLAN_SPEED_DEFAULT 0
+#define TLAN_SPEED_10 10
+#define TLAN_SPEED_100 100
+
+#define TLAN_DUPLEX_DEFAULT 0
+#define TLAN_DUPLEX_HALF 1
+#define TLAN_DUPLEX_FULL 2
+
+
+
+ /*****************************************************************
+ * EISA Definitions
+ *
+ ****************************************************************/
+
+#define EISA_ID 0xc80 /* EISA ID Registers */
+#define EISA_ID0 0xc80 /* EISA ID Register 0 */
+#define EISA_ID1 0xc81 /* EISA ID Register 1 */
+#define EISA_ID2 0xc82 /* EISA ID Register 2 */
+#define EISA_ID3 0xc83 /* EISA ID Register 3 */
+#define EISA_CR 0xc84 /* EISA Control Register */
+#define EISA_REG0 0xc88 /* EISA Configuration Register 0 */
+#define EISA_REG1 0xc89 /* EISA Configuration Register 1 */
+#define EISA_REG2 0xc8a /* EISA Configuration Register 2 */
+#define EISA_REG3 0xc8f /* EISA Configuration Register 3 */
+#define EISA_APROM 0xc90 /* Ethernet Address PROM */
+
+
+
+ /*****************************************************************
+ * Rx/Tx List Definitions
+ *
+ ****************************************************************/
+
+#define TLAN_BUFFERS_PER_LIST 10
+#define TLAN_LAST_BUFFER 0x80000000
+#define TLAN_CSTAT_UNUSED 0x8000
+#define TLAN_CSTAT_FRM_CMP 0x4000
+#define TLAN_CSTAT_READY 0x3000
+#define TLAN_CSTAT_EOC 0x0800
+#define TLAN_CSTAT_RX_ERROR 0x0400
+#define TLAN_CSTAT_PASS_CRC 0x0200
+#define TLAN_CSTAT_DP_PR 0x0100
+
+
+
+
+
+
+ /*****************************************************************
+ * PHY definitions
+ *
+ ****************************************************************/
+
+#define TLAN_PHY_MAX_ADDR 0x1F
+#define TLAN_PHY_NONE 0x20
+
+
+
+ /*****************************************************************
+ * TLan Driver Timer Definitions
+ *
+ ****************************************************************/
+
+#define TLAN_TIMER_LINK_BEAT 1
+#define TLAN_TIMER_ACTIVITY 2
+#define TLAN_TIMER_PHY_PDOWN 3
+#define TLAN_TIMER_PHY_PUP 4
+#define TLAN_TIMER_PHY_RESET 5
+#define TLAN_TIMER_PHY_START_LINK 6
+#define TLAN_TIMER_PHY_FINISH_AN 7
+#define TLAN_TIMER_FINISH_RESET 8
+
+#define TLAN_TIMER_ACT_DELAY (HZ/10)
+
+
+
+
+ /*****************************************************************
+ * TLan Driver Eeprom Definitions
+ *
+ ****************************************************************/
+
+#define TLAN_EEPROM_ACK 0
+#define TLAN_EEPROM_STOP 1
+
+
+
+
+ /*****************************************************************
+ * Host Register Offsets and Contents
+ *
+ ****************************************************************/
+
+#define TLAN_HOST_CMD 0x00
+#define TLAN_HC_GO 0x80000000
+#define TLAN_HC_STOP 0x40000000
+#define TLAN_HC_ACK 0x20000000
+#define TLAN_HC_CS_MASK 0x1FE00000
+#define TLAN_HC_EOC 0x00100000
+#define TLAN_HC_RT 0x00080000
+#define TLAN_HC_NES 0x00040000
+#define TLAN_HC_AD_RST 0x00008000
+#define TLAN_HC_LD_TMR 0x00004000
+#define TLAN_HC_LD_THR 0x00002000
+#define TLAN_HC_REQ_INT 0x00001000
+#define TLAN_HC_INT_OFF 0x00000800
+#define TLAN_HC_INT_ON 0x00000400
+#define TLAN_HC_AC_MASK 0x000000FF
+#define TLAN_CH_PARM 0x04
+#define TLAN_DIO_ADR 0x08
+#define TLAN_DA_ADR_INC 0x8000
+#define TLAN_DA_RAM_ADR 0x4000
+#define TLAN_HOST_INT 0x0A
+#define TLAN_HI_IV_MASK 0x1FE0
+#define TLAN_HI_IT_MASK 0x001C
+#define TLAN_DIO_DATA 0x0C
+
+
+/* ThunderLAN Internal Register DIO Offsets */
+
+#define TLAN_NET_CMD 0x00
+#define TLAN_NET_CMD_NRESET 0x80
+#define TLAN_NET_CMD_NWRAP 0x40
+#define TLAN_NET_CMD_CSF 0x20
+#define TLAN_NET_CMD_CAF 0x10
+#define TLAN_NET_CMD_NOBRX 0x08
+#define TLAN_NET_CMD_DUPLEX 0x04
+#define TLAN_NET_CMD_TRFRAM 0x02
+#define TLAN_NET_CMD_TXPACE 0x01
+#define TLAN_NET_SIO 0x01
+#define TLAN_NET_SIO_MINTEN 0x80
+#define TLAN_NET_SIO_ECLOK 0x40
+#define TLAN_NET_SIO_ETXEN 0x20
+#define TLAN_NET_SIO_EDATA 0x10
+#define TLAN_NET_SIO_NMRST 0x08
+#define TLAN_NET_SIO_MCLK 0x04
+#define TLAN_NET_SIO_MTXEN 0x02
+#define TLAN_NET_SIO_MDATA 0x01
+#define TLAN_NET_STS 0x02
+#define TLAN_NET_STS_MIRQ 0x80
+#define TLAN_NET_STS_HBEAT 0x40
+#define TLAN_NET_STS_TXSTOP 0x20
+#define TLAN_NET_STS_RXSTOP 0x10
+#define TLAN_NET_STS_RSRVD 0x0F
+#define TLAN_NET_MASK 0x03
+#define TLAN_NET_MASK_MASK7 0x80
+#define TLAN_NET_MASK_MASK6 0x40
+#define TLAN_NET_MASK_MASK5 0x20
+#define TLAN_NET_MASK_MASK4 0x10
+#define TLAN_NET_MASK_RSRVD 0x0F
+#define TLAN_NET_CONFIG 0x04
+#define TLAN_NET_CFG_RCLK 0x8000
+#define TLAN_NET_CFG_TCLK 0x4000
+#define TLAN_NET_CFG_BIT 0x2000
+#define TLAN_NET_CFG_RXCRC 0x1000
+#define TLAN_NET_CFG_PEF 0x0800
+#define TLAN_NET_CFG_1FRAG 0x0400
+#define TLAN_NET_CFG_1CHAN 0x0200
+#define TLAN_NET_CFG_MTEST 0x0100
+#define TLAN_NET_CFG_PHY_EN 0x0080
+#define TLAN_NET_CFG_MSMASK 0x007F
+#define TLAN_MAN_TEST 0x06
+#define TLAN_DEF_VENDOR_ID 0x08
+#define TLAN_DEF_DEVICE_ID 0x0A
+#define TLAN_DEF_REVISION 0x0C
+#define TLAN_DEF_SUBCLASS 0x0D
+#define TLAN_DEF_MIN_LAT 0x0E
+#define TLAN_DEF_MAX_LAT 0x0F
+#define TLAN_AREG_0 0x10
+#define TLAN_AREG_1 0x16
+#define TLAN_AREG_2 0x1C
+#define TLAN_AREG_3 0x22
+#define TLAN_HASH_1 0x28
+#define TLAN_HASH_2 0x2C
+#define TLAN_GOOD_TX_FRMS 0x30
+#define TLAN_TX_UNDERUNS 0x33
+#define TLAN_GOOD_RX_FRMS 0x34
+#define TLAN_RX_OVERRUNS 0x37
+#define TLAN_DEFERRED_TX 0x38
+#define TLAN_CRC_ERRORS 0x3A
+#define TLAN_CODE_ERRORS 0x3B
+#define TLAN_MULTICOL_FRMS 0x3C
+#define TLAN_SINGLECOL_FRMS 0x3E
+#define TLAN_EXCESSCOL_FRMS 0x40
+#define TLAN_LATE_COLS 0x41
+#define TLAN_CARRIER_LOSS 0x42
+#define TLAN_ACOMMIT 0x43
+#define TLAN_LED_REG 0x44
+#define TLAN_LED_ACT 0x10
+#define TLAN_LED_LINK 0x01
+#define TLAN_BSIZE_REG 0x45
+#define TLAN_MAX_RX 0x46
+#define TLAN_INT_DIS 0x48
+#define TLAN_ID_TX_EOC 0x04
+#define TLAN_ID_RX_EOF 0x02
+#define TLAN_ID_RX_EOC 0x01
+
+
+
+/* ThunderLAN Interrupt Codes */
+
+#define TLAN_INT_NUMBER_OF_INTS 8
+
+#define TLAN_INT_NONE 0x0000
+#define TLAN_INT_TX_EOF 0x0001
+#define TLAN_INT_STAT_OVERFLOW 0x0002
+#define TLAN_INT_RX_EOF 0x0003
+#define TLAN_INT_DUMMY 0x0004
+#define TLAN_INT_TX_EOC 0x0005
+#define TLAN_INT_STATUS_CHECK 0x0006
+#define TLAN_INT_RX_EOC 0x0007
+
+
+
+/* ThunderLAN MII Registers */
+
+/* ThunderLAN Specific MII/PHY Registers */
+
+#define TLAN_TLPHY_ID 0x10
+#define TLAN_TLPHY_CTL 0x11
+#define TLAN_TC_IGLINK 0x8000
+#define TLAN_TC_SWAPOL 0x4000
+#define TLAN_TC_AUISEL 0x2000
+#define TLAN_TC_SQEEN 0x1000
+#define TLAN_TC_MTEST 0x0800
+#define TLAN_TC_RESERVED 0x07F8
+#define TLAN_TC_NFEW 0x0004
+#define TLAN_TC_INTEN 0x0002
+#define TLAN_TC_TINT 0x0001
+#define TLAN_TLPHY_STS 0x12
+#define TLAN_TS_MINT 0x8000
+#define TLAN_TS_PHOK 0x4000
+#define TLAN_TS_POLOK 0x2000
+#define TLAN_TS_TPENERGY 0x1000
+#define TLAN_TS_RESERVED 0x0FFF
+#define TLAN_TLPHY_PAR 0x19
+#define TLAN_PHY_CIM_STAT 0x0020
+#define TLAN_PHY_SPEED_100 0x0040
+#define TLAN_PHY_DUPLEX_FULL 0x0080
+#define TLAN_PHY_AN_EN_STAT 0x0400
+
+/* National Sem. & Level1 PHY id's */
+#define NAT_SEM_ID1 0x2000
+#define NAT_SEM_ID2 0x5C01
+#define LEVEL1_ID1 0x7810
+#define LEVEL1_ID2 0x0000
+
+#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0
+
+/* Routines to access internal registers. */
+
+static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ return (inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3)));
+
+} /* TLan_DioRead8 */
+
+
+
+
+static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ return (inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2)));
+
+} /* TLan_DioRead16 */
+
+
+
+
+static inline u32 TLan_DioRead32(u16 base_addr, u16 internal_addr)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ return (inl(base_addr + TLAN_DIO_DATA));
+
+} /* TLan_DioRead32 */
+
+
+
+
+static inline void TLan_DioWrite8(u16 base_addr, u16 internal_addr, u8 data)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ outb(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x3));
+
+}
+
+
+
+
+static inline void TLan_DioWrite16(u16 base_addr, u16 internal_addr, u16 data)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ outw(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
+
+}
+
+
+
+
+static inline void TLan_DioWrite32(u16 base_addr, u16 internal_addr, u32 data)
+{
+ outw(internal_addr, base_addr + TLAN_DIO_ADR);
+ outl(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
+
+}
+
+
+
+#if 0
+static inline void TLan_ClearBit(u8 bit, u16 port)
+{
+ outb_p(inb_p(port) & ~bit, port);
+}
+
+
+
+
+static inline int TLan_GetBit(u8 bit, u16 port)
+{
+ return ((int) (inb_p(port) & bit));
+}
+
+
+
+
+static inline void TLan_SetBit(u8 bit, u16 port)
+{
+ outb_p(inb_p(port) | bit, port);
+}
+#endif
+
+#define TLan_ClearBit( bit, port ) outb_p(inb_p(port) & ~bit, port)
+#define TLan_GetBit( bit, port ) ((int) (inb_p(port) & bit))
+#define TLan_SetBit( bit, port ) outb_p(inb_p(port) | bit, port)
+
+#ifdef I_LIKE_A_FAST_HASH_FUNCTION
+/* given 6 bytes, view them as 8 6-bit numbers and return the XOR of those */
+/* the code below is about seven times as fast as the original code */
+static inline u32 TLan_HashFunc(u8 * a)
+{
+ u8 hash;
+
+ hash = (a[0] ^ a[3]); /* & 077 */
+ hash ^= ((a[0] ^ a[3]) >> 6); /* & 003 */
+ hash ^= ((a[1] ^ a[4]) << 2); /* & 074 */
+ hash ^= ((a[1] ^ a[4]) >> 4); /* & 017 */
+ hash ^= ((a[2] ^ a[5]) << 4); /* & 060 */
+ hash ^= ((a[2] ^ a[5]) >> 2); /* & 077 */
+
+ return (hash & 077);
+}
+
+#else /* original code */
+
+static inline u32 xor(u32 a, u32 b)
+{
+ return ((a && !b) || (!a && b));
+}
+
+#define XOR8( a, b, c, d, e, f, g, h ) xor( a, xor( b, xor( c, xor( d, xor( e, xor( f, xor( g, h ) ) ) ) ) ) )
+#define DA( a, bit ) ( ( (u8) a[bit/8] ) & ( (u8) ( 1 << bit%8 ) ) )
+
+static inline u32 TLan_HashFunc(u8 * a)
+{
+ u32 hash;
+
+ hash =
+ XOR8(DA(a, 0), DA(a, 6), DA(a, 12), DA(a, 18), DA(a, 24),
+ DA(a, 30), DA(a, 36), DA(a, 42));
+ hash |=
+ XOR8(DA(a, 1), DA(a, 7), DA(a, 13), DA(a, 19), DA(a, 25),
+ DA(a, 31), DA(a, 37), DA(a, 43)) << 1;
+ hash |=
+ XOR8(DA(a, 2), DA(a, 8), DA(a, 14), DA(a, 20), DA(a, 26),
+ DA(a, 32), DA(a, 38), DA(a, 44)) << 2;
+ hash |=
+ XOR8(DA(a, 3), DA(a, 9), DA(a, 15), DA(a, 21), DA(a, 27),
+ DA(a, 33), DA(a, 39), DA(a, 45)) << 3;
+ hash |=
+ XOR8(DA(a, 4), DA(a, 10), DA(a, 16), DA(a, 22), DA(a, 28),
+ DA(a, 34), DA(a, 40), DA(a, 46)) << 4;
+ hash |=
+ XOR8(DA(a, 5), DA(a, 11), DA(a, 17), DA(a, 23), DA(a, 29),
+ DA(a, 35), DA(a, 41), DA(a, 47)) << 5;
+
+ return hash;
+
+}
+
+#endif /* I_LIKE_A_FAST_HASH_FUNCTION */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/tulip.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/tulip.c
new file mode 100644
index 0000000..b990586
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/tulip.c
@@ -0,0 +1,2098 @@
+/* -*- Mode:C; c-basic-offset:4; -*- */
+
+/*
+ Tulip and clone Etherboot Driver
+
+ By Marty Connor (mdc@etherboot.org)
+ Copyright (C) 2001 Entity Cyber, Inc.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ As of April 2001 this driver should support most tulip cards that
+ the Linux tulip driver supports because Donald Becker's Linux media
+ detection code is now included.
+
+ Based on Ken Yap's Tulip Etherboot Driver and Donald Becker's
+ Linux Tulip Driver. Supports N-Way speed auto-configuration on
+ MX98715, MX98715A and MX98725. Support inexpensive PCI 10/100 cards
+ based on the Macronix MX987x5 chip, such as the SOHOware Fast
+ model SFA110A, and the LinkSYS model LNE100TX. The NetGear
+ model FA310X, based on the LC82C168 chip is supported.
+ The TRENDnet TE100-PCIA NIC which uses a genuine Intel 21143-PD
+ chipset is supported. Also, Davicom DM9102's.
+
+ Documentation and source code used:
+ Source for Etherboot driver at
+ http://etherboot.sourceforge.net/
+ MX98715A Data Sheet and MX98715A Application Note
+ on http://www.macronix.com/ (PDF format files)
+ Source for Linux tulip driver at
+ http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
+
+ Adapted by Ken Yap from
+ FreeBSD netboot DEC 21143 driver
+ Author: David Sharp
+ date: Nov/98
+
+ Some code fragments were taken from verious places, Ken Yap's
+ etherboot, FreeBSD's if_de.c, and various Linux related files.
+ DEC's manuals for the 21143 and SROM format were very helpful.
+ The Linux de driver development page has a number of links to
+ useful related information. Have a look at:
+ ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
+*/
+
+FILE_LICENCE ( GPL_ANY );
+
+/*********************************************************************/
+/* Revision History */
+/*********************************************************************/
+
+/*
+ 08 Feb 2005 Ramesh Chander chhabaramesh at yahoo.co.in added table entries
+ for SGThomson STE10/100A
+ 07 Sep 2003 timlegge Multicast Support Added
+ 11 Apr 2001 mdc [patch to etherboot 4.7.24]
+ Major rewrite to include Linux tulip driver media detection
+ code. This driver should support a lot more cards now.
+ 16 Jul 2000 mdc 0.75b11
+ Added support for ADMtek 0985 Centaur-P, a "Comet" tulip clone
+ which is used on the LinkSYS LNE100TX v4.x cards. We already
+ support LNE100TX v2.0 cards, which use a different controller.
+ 04 Jul 2000 jam ?
+ Added test of status after receiving a packet from the card.
+ Also uncommented the tulip_disable routine. Stray packets
+ seemed to be causing problems.
+ 27 Apr 2000 njl ?
+ 29 Feb 2000 mdc 0.75b7
+ Increased reset delay to 3 seconds because Macronix cards seem to
+ need more reset time before card comes back to a usable state.
+ 26 Feb 2000 mdc 0.75b6
+ Added a 1 second delay after initializing the transmitter because
+ some cards seem to need the time or they drop the first packet
+ transmitted.
+ 23 Feb 2000 mdc 0.75b5
+ removed udelay code and used currticks() for more reliable delay
+ code in reset pause and sanity timeouts. Added function prototypes
+ and TX debugging code.
+ 21 Feb 2000 mdc patch to Etherboot 4.4.3
+ Incorporated patches from Bob Edwards and Paul Mackerras of
+ Linuxcare's OZLabs to deal with inefficiencies in tulip_transmit
+ and udelay. We now wait for packet transmission to complete
+ (or sanity timeout).
+ 04 Feb 2000 Robert.Edwards@anu.edu.au patch to Etherboot 4.4.2
+ patch to tulip.c that implements the automatic selection of the MII
+ interface on cards using the Intel/DEC 21143 reference design, in
+ particular, the TRENDnet TE100-PCIA NIC which uses a genuine Intel
+ 21143-PD chipset.
+ 11 Jan 2000 mdc 0.75b4
+ Added support for NetGear FA310TX card based on the LC82C168
+ chip. This should also support Lite-On LC82C168 boards.
+ Added simple MII support. Re-arranged code to better modularize
+ initializations.
+ 04 Dec 1999 mdc 0.75b3
+ Added preliminary support for LNE100TX PCI cards. Should work for
+ PNIC2 cards. No MII support, but single interface (RJ45) tulip
+ cards seem to not care.
+ 03 Dec 1999 mdc 0.75b2
+ Renamed from mx987x5 to tulip, merged in original tulip init code
+ from tulip.c to support other tulip compatible cards.
+ 02 Dec 1999 mdc 0.75b1
+ Released Beta MX987x5 Driver for code review and testing to netboot
+ and thinguin mailing lists.
+*/
+
+
+/*********************************************************************/
+/* Declarations */
+/*********************************************************************/
+
+#include "etherboot.h"
+#include "nic.h"
+
+#include <gpxe/ethernet.h>
+#include <gpxe/pci.h>
+
+/* User settable parameters */
+
+#undef TULIP_DEBUG
+#undef TULIP_DEBUG_WHERE
+#ifdef TULIP_DEBUG
+static int tulip_debug = 2; /* 1 normal messages, 0 quiet .. 7 verbose. */
+#endif
+
+#define TX_TIME_OUT 2*TICKS_PER_SEC
+
+/* helpful macros if on a big_endian machine for changing byte order.
+ not strictly needed on Intel */
+#define get_unaligned(ptr) (*(ptr))
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+#define get_u16(ptr) (*(u16 *)(ptr))
+#define virt_to_le32desc(addr) virt_to_bus(addr)
+
+#define TULIP_IOTYPE PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0
+#define TULIP_SIZE 0x80
+
+/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
+ to support a pre-NWay full-duplex signaling mechanism using short frames.
+ No one knows what it should be, but if left at its default value some
+ 10base2(!) packets trigger a full-duplex-request interrupt. */
+#define FULL_DUPLEX_MAGIC 0x6969
+
+static const int csr0 = 0x01A00000 | 0x8000;
+
+/* The possible media types that can be set in options[] are: */
+#define MEDIA_MASK 31
+static const char * const medianame[32] = {
+ "10baseT", "10base2", "AUI", "100baseTx",
+ "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
+ "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
+ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
+ "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
+};
+
+/* This much match tulip_tbl[]! Note 21142 == 21143. */
+enum tulip_chips {
+ DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
+ LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET,
+ COMPEX9881, I21145, XIRCOM, SGThomson, /*Ramesh Chander*/
+};
+
+enum pci_id_flags_bits {
+ /* Set PCI command register bits before calling probe1(). */
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ /* Read and map the single following PCI BAR. */
+ PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
+ PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
+ PCI_UNUSED_IRQ=0x800,
+};
+
+struct pci_id_info {
+ char *name;
+ struct match_info {
+ u32 pci, pci_mask, subsystem, subsystem_mask;
+ u32 revision, revision_mask; /* Only 8 bits. */
+ } id;
+ enum pci_id_flags_bits pci_flags;
+ int io_size; /* Needed for I/O region check or ioremap(). */
+ int drv_flags; /* Driver use, intended as capability flags. */
+};
+
+static const struct pci_id_info pci_id_tbl[] = {
+ { "Digital DC21040 Tulip", { 0x00021011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21040 },
+ { "Digital DC21041 Tulip", { 0x00141011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21041 },
+ { "Digital DS21140A Tulip", { 0x00091011, 0xffffffff, 0,0, 0x20,0xf0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Digital DS21140 Tulip", { 0x00091011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Digital DS21143 Tulip", { 0x00191011, 0xffffffff, 0,0, 65,0xff },
+ TULIP_IOTYPE, TULIP_SIZE, DC21142 },
+ { "Digital DS21142 Tulip", { 0x00191011, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, TULIP_SIZE, DC21142 },
+ { "Kingston KNE110tx (PNIC)", { 0x000211AD, 0xffffffff, 0xf0022646, 0xffffffff, 0, 0 },
+ TULIP_IOTYPE, 256, LC82C168 },
+ { "Lite-On 82c168 PNIC", { 0x000211AD, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, LC82C168 },
+ { "Macronix 98713 PMAC", { 0x051210d9, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98713 },
+ { "Macronix 98715 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98715 },
+ { "Macronix 98725 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98725 },
+ { "ASIX AX88141", { 0x1400125B, 0xffffffff, 0,0, 0x10, 0xf0 },
+ TULIP_IOTYPE, 128, AX88141 },
+ { "ASIX AX88140", { 0x1400125B, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, AX88140 },
+ { "Lite-On LC82C115 PNIC-II", { 0xc11511AD, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, PNIC2 },
+ { "ADMtek AN981 Comet", { 0x09811317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMTek AN983 Comet", { 0x12161113, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMTek Comet AN983b", { 0x95111317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMtek Centaur-P", { 0x09851317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "ADMtek Centaur-C", { 0x19851317, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET },
+ { "Compex RL100-TX", { 0x988111F6, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, COMPEX9881 },
+ { "Intel 21145 Tulip", { 0x00398086, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, I21145 },
+ { "Xircom Tulip clone", { 0x0003115d, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 128, XIRCOM },
+ { "Davicom DM9102", { 0x91021282, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Davicom DM9100", { 0x91001282, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 0x80, DC21140 },
+ { "Macronix mxic-98715 (EN1217)", { 0x12171113, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, MX98715 },
+ { "3Com 3cSOHO100B-TX (ADMtek Centuar)", { 0x930010b7, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, TULIP_SIZE, COMET },
+ { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 },
+ TULIP_IOTYPE, 256, COMET }, /*Ramesh Chander*/
+ { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 },
+};
+
+enum tbl_flag {
+ HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
+ HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
+ HAS_PNICNWAY=0x80, HAS_NWAY=0x40, /* Uses internal NWay xcvr. */
+ HAS_INTR_MITIGATION=0x100, IS_ASIX=0x200, HAS_8023X=0x400,
+};
+
+/* Note: this table must match enum tulip_chips above. */
+static struct tulip_chip_table {
+ char *chip_name;
+ int flags;
+} tulip_tbl[] = {
+ { "Digital DC21040 Tulip", 0},
+ { "Digital DC21041 Tulip", HAS_MEDIA_TABLE | HAS_NWAY },
+ { "Digital DS21140 Tulip", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
+ { "Digital DS21143 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
+ | HAS_PWRDWN | HAS_NWAY | HAS_INTR_MITIGATION },
+ { "Lite-On 82c168 PNIC", HAS_MII | HAS_PNICNWAY },
+ { "Macronix 98713 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
+ { "Macronix 98715 PMAC", HAS_MEDIA_TABLE },
+ { "Macronix 98725 PMAC", HAS_MEDIA_TABLE },
+ { "ASIX AX88140", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM
+ | MC_HASH_ONLY | IS_ASIX },
+ { "ASIX AX88141", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
+ | IS_ASIX },
+ { "Lite-On PNIC-II", HAS_MII | HAS_NWAY | HAS_8023X },
+ { "ADMtek Comet", HAS_MII | MC_HASH_ONLY },
+ { "Compex 9881 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
+ { "Intel DS21145 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
+ | HAS_PWRDWN | HAS_NWAY },
+ { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
+ | HAS_PWRDWN | HAS_NWAY },
+ { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY }, /*Ramesh Chander*/
+ { 0, 0 },
+};
+
+/* A full-duplex map for media types. */
+enum MediaIs {
+ MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+ MediaIs100=16};
+
+static const char media_cap[32] =
+{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20, 20,31,0,0, };
+static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0};
+
+/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD */
+static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
+static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
+static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+
+/* not used
+static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };
+*/
+static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
+/* not used
+static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+*/
+
+/* Offsets to the Command and Status Registers, "CSRs". All accesses
+ must be longword instructions and quadword aligned. */
+enum tulip_offsets {
+ CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+ CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+ CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
+};
+
+/* The bits in the CSR5 status registers, mostly interrupt sources. */
+enum status_bits {
+ TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
+ NormalIntr=0x10000, AbnormalIntr=0x8000,
+ RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
+ TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
+};
+
+/* The configuration bits in CSR6. */
+enum csr6_mode_bits {
+ TxOn=0x2000, RxOn=0x0002, FullDuplex=0x0200,
+ AcceptBroadcast=0x0100, AcceptAllMulticast=0x0080,
+ AcceptAllPhys=0x0040, AcceptRunt=0x0008,
+};
+
+
+enum desc_status_bits {
+ DescOwnded=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
+};
+
+struct medialeaf {
+ u8 type;
+ u8 media;
+ unsigned char *leafdata;
+};
+
+struct mediatable {
+ u16 defaultmedia;
+ u8 leafcount, csr12dir; /* General purpose pin directions. */
+ unsigned has_mii:1, has_nonmii:1, has_reset:6;
+ u32 csr15dir, csr15val; /* 21143 NWay setting. */
+ struct medialeaf mleaf[0];
+};
+
+struct mediainfo {
+ struct mediainfo *next;
+ int info_type;
+ int index;
+ unsigned char *info;
+};
+
+/* EEPROM Address width definitions */
+#define EEPROM_ADDRLEN 6
+#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5 << addr_len)
+#define EE_READ_CMD (6 << addr_len)
+#define EE_ERASE_CMD (7 << addr_len)
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
+#define EE_CS 0x01 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x05
+#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_ENB (0x4800 | EE_CS)
+
+/* Delay between EEPROM clock transitions. Even at 33Mhz current PCI
+ implementations don't overrun the EEPROM clock. We add a bus
+ turn-around to insure that this remains true. */
+#define eeprom_delay() inl(ee_addr)
+
+/* Size of transmit and receive buffers */
+#define BUFLEN 1536
+
+/* Ring-wrap flag in length field, use for last ring entry.
+ 0x01000000 means chain on buffer2 address,
+ 0x02000000 means use the ring start address in CSR2/3.
+ Note: Some work-alike chips do not function correctly in chained mode.
+ The ASIX chip works only in chained mode.
+ Thus we indicate ring mode, but always write the 'next' field for
+ chained mode as well. */
+#define DESC_RING_WRAP 0x02000000
+
+/* transmit and receive descriptor format */
+struct tulip_rx_desc {
+ volatile u32 status;
+ u32 length;
+ u32 buffer1, buffer2;
+};
+
+struct tulip_tx_desc {
+ volatile u32 status;
+ u32 length;
+ u32 buffer1, buffer2;
+};
+
+/*********************************************************************/
+/* Global Storage */
+/*********************************************************************/
+
+static u32 ioaddr;
+
+struct tulip_private {
+ int cur_rx;
+ int chip_id; /* index into tulip_tbl[] */
+ int pci_id_idx; /* index into pci_id_tbl[] */
+ int revision;
+ int flags;
+ unsigned short vendor_id; /* PCI card vendor code */
+ unsigned short dev_id; /* PCI card device code */
+ unsigned char ehdr[ETH_HLEN]; /* buffer for ethernet header */
+ const char *nic_name;
+ unsigned int csr0, csr6; /* Current CSR0, CSR6 settings. */
+ unsigned int if_port;
+ unsigned int full_duplex; /* Full-duplex operation requested. */
+ unsigned int full_duplex_lock;
+ unsigned int medialock; /* Do not sense media type. */
+ unsigned int mediasense; /* Media sensing in progress. */
+ unsigned int nway, nwayset; /* 21143 internal NWay. */
+ unsigned int default_port;
+ unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */
+ u8 media_table_storage[(sizeof(struct mediatable) + 32*sizeof(struct medialeaf))];
+ u16 sym_advertise, mii_advertise; /* NWay to-advertise. */
+ struct mediatable *mtable;
+ u16 lpar; /* 21143 Link partner ability. */
+ u16 advertising[4]; /* MII advertise, from SROM table. */
+ signed char phys[4], mii_cnt; /* MII device addresses. */
+ int cur_index; /* Current media index. */
+ int saved_if_port;
+};
+
+/* Note: transmit and receive buffers must be longword aligned and
+ longword divisable */
+
+#define TX_RING_SIZE 2
+#define RX_RING_SIZE 4
+struct {
+ struct tulip_tx_desc tx_ring[TX_RING_SIZE];
+ unsigned char txb[BUFLEN];
+ struct tulip_rx_desc rx_ring[RX_RING_SIZE];
+ unsigned char rxb[RX_RING_SIZE * BUFLEN];
+ struct tulip_private tpx;
+} tulip_bss __shared __attribute__ ((aligned(4)));
+#define tx_ring tulip_bss.tx_ring
+#define txb tulip_bss.txb
+#define rx_ring tulip_bss.rx_ring
+#define rxb tulip_bss.rxb
+
+static struct tulip_private *tp;
+
+/* Known cards that have old-style EEPROMs.
+ Writing this table is described at
+ http://cesdis.gsfc.nasa.gov/linux/drivers/tulip-drivers/tulip-media.html */
+static struct fixups {
+ char *name;
+ unsigned char addr0, addr1, addr2;
+ u16 newtable[32]; /* Max length below. */
+} eeprom_fixups[] = {
+ {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
+ 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
+ {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
+ 0x0000, 0x009E, /* 10baseT */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0903, 0x006D, /* 100baseTx */
+ 0x0905, 0x006D, /* 100baseTx-FD */ }},
+ {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
+ 0x0107, 0x8021, /* 100baseFx */
+ 0x0108, 0x8021, /* 100baseFx-FD */
+ 0x0100, 0x009E, /* 10baseT */
+ 0x0104, 0x009E, /* 10baseT-FD */
+ 0x0103, 0x006D, /* 100baseTx */
+ 0x0105, 0x006D, /* 100baseTx-FD */ }},
+ {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
+ 0x1001, 0x009E, /* 10base2, CSR12 0x10*/
+ 0x0000, 0x009E, /* 10baseT */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
+ 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
+ {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
+ 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */
+ 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */
+ 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
+ 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
+ 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
+ }},
+ {0, 0, 0, 0, {}}};
+
+static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
+ "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
+
+
+/*********************************************************************/
+/* Function Prototypes */
+/*********************************************************************/
+static int mdio_read(struct nic *nic, int phy_id, int location);
+static void mdio_write(struct nic *nic, int phy_id, int location, int value);
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
+static void parse_eeprom(struct nic *nic);
+static int tulip_probe(struct nic *nic,struct pci_device *pci);
+static void tulip_init_ring(struct nic *nic);
+static void tulip_reset(struct nic *nic);
+static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p);
+static int tulip_poll(struct nic *nic, int retrieve);
+static void tulip_disable(struct nic *nic);
+static void nway_start(struct nic *nic);
+static void pnic_do_nway(struct nic *nic);
+static void select_media(struct nic *nic, int startup);
+static void init_media(struct nic *nic);
+static void start_link(struct nic *nic);
+static int tulip_check_duplex(struct nic *nic);
+
+static void tulip_wait(unsigned int nticks);
+
+#ifdef TULIP_DEBUG_WHERE
+static void whereami(const char *str);
+#endif
+
+#ifdef TULIP_DEBUG
+static void tulip_more(void);
+#endif
+
+
+/*********************************************************************/
+/* Utility Routines */
+/*********************************************************************/
+
+#ifdef TULIP_DEBUG_WHERE
+static void whereami (const char *str, struct pci_device *pci)
+{
+ printf("%s: %s\n", tp->nic_name, str);
+ /* sleep(2); */
+}
+#endif
+
+#ifdef TULIP_DEBUG
+static void tulip_more(void)
+{
+ printf("\n\n-- more --");
+ while (!iskey())
+ /* wait */;
+ getchar();
+ printf("\n\n");
+}
+#endif /* TULIP_DEBUG */
+
+static void tulip_wait(unsigned int nticks)
+{
+ unsigned int to = currticks() + nticks;
+ while (currticks() < to)
+ /* wait */ ;
+}
+
+
+/*********************************************************************/
+/* Media Descriptor Code */
+/*********************************************************************/
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details. */
+
+/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+ "overclocking" issues or future 66Mhz PCI. */
+#define mdio_delay() inl(mdio_addr)
+
+/* Read and write the MII registers using software-generated serial
+ MDIO protocol. It is just different enough from the EEPROM protocol
+ to not share code. The maxium data clock rate is 2.5 Mhz. */
+#define MDIO_SHIFT_CLK 0x10000
+#define MDIO_DATA_WRITE0 0x00000
+#define MDIO_DATA_WRITE1 0x20000
+#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */
+#define MDIO_ENB_IN 0x40000
+#define MDIO_DATA_READ 0x80000
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details. */
+
+int mdio_read(struct nic *nic __unused, int phy_id, int location)
+{
+ int i;
+ int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int retval = 0;
+ long mdio_addr = ioaddr + CSR9;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("mdio_read\n");
+#endif
+
+ if (tp->chip_id == LC82C168) {
+ int i = 1000;
+ outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
+ inl(ioaddr + 0xA0);
+ inl(ioaddr + 0xA0);
+ while (--i > 0)
+ if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
+ return retval & 0xffff;
+ return 0xffff;
+ }
+
+ if (tp->chip_id == COMET) {
+ if (phy_id == 1) {
+ if (location < 7)
+ return inl(ioaddr + 0xB4 + (location<<2));
+ else if (location == 17)
+ return inl(ioaddr + 0xD0);
+ else if (location >= 29 && location <= 31)
+ return inl(ioaddr + 0xD4 + ((location-29)<<2));
+ }
+ return 0xffff;
+ }
+
+ /* Establish sync by sending at least 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+
+ outl(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ outl(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ return (retval>>1) & 0xffff;
+}
+
+void mdio_write(struct nic *nic __unused, int phy_id, int location, int value)
+{
+ int i;
+ int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+ long mdio_addr = ioaddr + CSR9;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("mdio_write\n");
+#endif
+
+ if (tp->chip_id == LC82C168) {
+ int i = 1000;
+ outl(cmd, ioaddr + 0xA0);
+ do
+ if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
+ break;
+ while (--i > 0);
+ return;
+ }
+
+ if (tp->chip_id == COMET) {
+ if (phy_id != 1)
+ return;
+ if (location < 7)
+ outl(value, ioaddr + 0xB4 + (location<<2));
+ else if (location == 17)
+ outl(value, ioaddr + 0xD0);
+ else if (location >= 29 && location <= 31)
+ outl(value, ioaddr + 0xD4 + ((location-29)<<2));
+ return;
+ }
+
+ /* Establish sync by sending 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ outl(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ outl(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+}
+
+
+/*********************************************************************/
+/* EEPROM Reading Code */
+/*********************************************************************/
+/* EEPROM routines adapted from the Linux Tulip Code */
+/* Reading a serial EEPROM is a "bit" grungy, but we work our way
+ through:->.
+*/
+static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
+{
+ int i;
+ unsigned short retval = 0;
+ long ee_addr = ioaddr + CSR9;
+ int read_cmd = location | EE_READ_CMD;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("read_eeprom\n");
+#endif
+
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ outl(EE_ENB, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ outl(EE_ENB | dataval, ee_addr);
+ eeprom_delay();
+ outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ }
+ outl(EE_ENB, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+ outl(EE_ENB, ee_addr);
+ eeprom_delay();
+ }
+
+ /* Terminate the EEPROM access. */
+ outl(EE_ENB & ~EE_CS, ee_addr);
+ return retval;
+}
+
+
+/*********************************************************************/
+/* EEPROM Parsing Code */
+/*********************************************************************/
+static void parse_eeprom(struct nic *nic)
+{
+ unsigned char *p, *ee_data = tp->eeprom;
+ int new_advertise = 0;
+ int i;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("parse_eeprom\n");
+#endif
+
+ tp->mtable = 0;
+ /* Detect an old-style (SA only) EEPROM layout:
+ memcmp(ee_data, ee_data+16, 8). */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ break;
+ if (i >= 8) {
+ /* Do a fix-up based on the vendor half of the station address. */
+ for (i = 0; eeprom_fixups[i].name; i++) {
+ if (nic->node_addr[0] == eeprom_fixups[i].addr0
+ && nic->node_addr[1] == eeprom_fixups[i].addr1
+ && nic->node_addr[2] == eeprom_fixups[i].addr2) {
+ if (nic->node_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
+ i++; /* An Accton EN1207, not an outlaw Maxtech. */
+ memcpy(ee_data + 26, eeprom_fixups[i].newtable,
+ sizeof(eeprom_fixups[i].newtable));
+#ifdef TULIP_DEBUG
+ printf("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n",
+ tp->nic_name, eeprom_fixups[i].name, tp->nic_name);
+#endif
+ break;
+ }
+ }
+ if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
+#ifdef TULIP_DEBUG
+ printf("%s: Old style EEPROM with no media selection information.\n",
+ tp->nic_name);
+#endif
+ return;
+ }
+ }
+
+ if (ee_data[19] > 1) {
+#ifdef TULIP_DEBUG
+ printf("%s: Multiport cards (%d ports) may not work correctly.\n",
+ tp->nic_name, ee_data[19]);
+#endif
+ }
+
+ p = (void *)ee_data + ee_data[27];
+
+ if (ee_data[27] == 0) { /* No valid media table. */
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1) {
+ printf("%s: No Valid Media Table. ee_data[27] = %hhX\n",
+ tp->nic_name, ee_data[27]);
+ }
+#endif
+ } else if (tp->chip_id == DC21041) {
+ int media = get_u16(p);
+ int count = p[2];
+ p += 3;
+
+ printf("%s: 21041 Media table, default media %hX (%s).\n",
+ tp->nic_name, media,
+ media & 0x0800 ? "Autosense" : medianame[media & 15]);
+ for (i = 0; i < count; i++) {
+ unsigned char media_block = *p++;
+ int media_code = media_block & MEDIA_MASK;
+ if (media_block & 0x40)
+ p += 6;
+ switch(media_code) {
+ case 0: new_advertise |= 0x0020; break;
+ case 4: new_advertise |= 0x0040; break;
+ }
+ printf("%s: 21041 media #%d, %s.\n",
+ tp->nic_name, media_code, medianame[media_code]);
+ }
+ } else {
+ unsigned char csr12dir = 0;
+ int count;
+ struct mediatable *mtable;
+ u16 media = get_u16(p);
+
+ p += 2;
+ if (tp->flags & CSR12_IN_SROM)
+ csr12dir = *p++;
+ count = *p++;
+
+ tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0];
+
+ mtable->defaultmedia = media;
+ mtable->leafcount = count;
+ mtable->csr12dir = csr12dir;
+ mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
+ mtable->csr15dir = mtable->csr15val = 0;
+
+ printf("%s: EEPROM default media type %s.\n", tp->nic_name,
+ media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
+
+ for (i = 0; i < count; i++) {
+ struct medialeaf *leaf = &mtable->mleaf[i];
+
+ if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
+ leaf->type = 0;
+ leaf->media = p[0] & 0x3f;
+ leaf->leafdata = p;
+ if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */
+ mtable->has_mii = 1;
+ p += 4;
+ } else {
+ switch(leaf->type = p[1]) {
+ case 5:
+ mtable->has_reset = i;
+ leaf->media = p[2] & 0x0f;
+ break;
+ case 1: case 3:
+ mtable->has_mii = 1;
+ leaf->media = 11;
+ break;
+ case 2:
+ if ((p[2] & 0x3f) == 0) {
+ u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008;
+ u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3));
+ mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15;
+ mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15;
+ }
+ /* Fall through. */
+ case 0: case 4:
+ mtable->has_nonmii = 1;
+ leaf->media = p[2] & MEDIA_MASK;
+ switch (leaf->media) {
+ case 0: new_advertise |= 0x0020; break;
+ case 4: new_advertise |= 0x0040; break;
+ case 3: new_advertise |= 0x0080; break;
+ case 5: new_advertise |= 0x0100; break;
+ case 6: new_advertise |= 0x0200; break;
+ }
+ break;
+ default:
+ leaf->media = 19;
+ }
+ leaf->leafdata = p + 2;
+ p += (p[0] & 0x3f) + 1;
+ }
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1 && leaf->media == 11) {
+ unsigned char *bp = leaf->leafdata;
+ printf("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n",
+ tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2],
+ bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
+ }
+#endif
+ printf("%s: Index #%d - Media %s (#%d) described "
+ "by a %s (%d) block.\n",
+ tp->nic_name, i, medianame[leaf->media], leaf->media,
+ leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN",
+ leaf->type);
+ }
+ if (new_advertise)
+ tp->sym_advertise = new_advertise;
+ }
+}
+
+
+/*********************************************************************/
+/* tulip_init_ring - setup the tx and rx descriptors */
+/*********************************************************************/
+static void tulip_init_ring(struct nic *nic __unused)
+{
+ int i;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_init_ring\n");
+#endif
+
+ tp->cur_rx = 0;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_ring[i].status = cpu_to_le32(0x80000000);
+ rx_ring[i].length = cpu_to_le32(BUFLEN);
+ rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]);
+ rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]);
+ }
+ /* Mark the last entry as wrapping the ring. */
+ rx_ring[i-1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
+ rx_ring[i-1].buffer2 = virt_to_le32desc(&rx_ring[0]);
+
+ /* We only use 1 transmit buffer, but we use 2 descriptors so
+ transmit engines have somewhere to point to if they feel the need */
+
+ tx_ring[0].status = 0x00000000;
+ tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
+ tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]);
+
+ /* this descriptor should never get used, since it will never be owned
+ by the machine (status will always == 0) */
+ tx_ring[1].status = 0x00000000;
+ tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]);
+ tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]);
+
+ /* Mark the last entry as wrapping the ring, though this should never happen */
+ tx_ring[1].length = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
+}
+
+
+static void set_rx_mode(struct nic *nic __unused) {
+ int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
+
+ tp->csr6 &= ~0x00D5;
+
+ /* !IFF_PROMISC */
+ tp->csr6 |= AcceptAllMulticast;
+ csr6 |= AcceptAllMulticast;
+
+ outl(csr6, ioaddr + CSR6);
+
+
+
+}
+
+/*********************************************************************/
+/* eth_reset - Reset adapter */
+/*********************************************************************/
+static void tulip_reset(struct nic *nic)
+{
+ int i;
+ unsigned long to;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_reset\n");
+#endif
+
+ /* Stop Tx and RX */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* On some chip revs we must set the MII/SYM port before the reset!? */
+ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) {
+ outl(0x814C0000, ioaddr + CSR6);
+ }
+
+ /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+ outl(0x00000001, ioaddr + CSR0);
+ tulip_wait(1);
+
+ /* turn off reset and set cache align=16lword, burst=unlimit */
+ outl(tp->csr0, ioaddr + CSR0);
+
+ /* Wait the specified 50 PCI cycles after a reset */
+ tulip_wait(1);
+
+ /* set up transmit and receive descriptors */
+ tulip_init_ring(nic);
+
+ if (tp->chip_id == PNIC2) {
+ u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0);
+ /* This address setting does not appear to impact chip operation?? */
+ outl((nic->node_addr[5]<<8) + nic->node_addr[4] +
+ (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16),
+ ioaddr + 0xB0);
+ outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
+ }
+
+ /* MC_HASH_ONLY boards don't support setup packets */
+ if (tp->flags & MC_HASH_ONLY) {
+ u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr));
+ u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4)));
+
+ /* clear multicast hash filters and setup MAC address filters */
+ if (tp->flags & IS_ASIX) {
+ outl(0, ioaddr + CSR13);
+ outl(addr_low, ioaddr + CSR14);
+ outl(1, ioaddr + CSR13);
+ outl(addr_high, ioaddr + CSR14);
+ outl(2, ioaddr + CSR13);
+ outl(0, ioaddr + CSR14);
+ outl(3, ioaddr + CSR13);
+ outl(0, ioaddr + CSR14);
+ } else if (tp->chip_id == COMET) {
+ outl(addr_low, ioaddr + 0xA4);
+ outl(addr_high, ioaddr + 0xA8);
+ outl(0, ioaddr + 0xAC);
+ outl(0, ioaddr + 0xB0);
+ }
+ } else {
+ /* for other boards we send a setup packet to initialize
+ the filters */
+ u32 tx_flags = 0x08000000 | 192;
+
+ /* construct perfect filter frame with mac address as first match
+ and broadcast address for all others */
+ for (i=0; i<192; i++)
+ txb[i] = 0xFF;
+ txb[0] = nic->node_addr[0];
+ txb[1] = nic->node_addr[1];
+ txb[4] = nic->node_addr[2];
+ txb[5] = nic->node_addr[3];
+ txb[8] = nic->node_addr[4];
+ txb[9] = nic->node_addr[5];
+
+ tx_ring[0].length = cpu_to_le32(tx_flags);
+ tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
+ tx_ring[0].status = cpu_to_le32(0x80000000);
+ }
+
+ /* Point to rx and tx descriptors */
+ outl(virt_to_le32desc(&rx_ring[0]), ioaddr + CSR3);
+ outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
+
+ init_media(nic);
+
+ /* set the chip's operating mode (but don't turn on xmit and recv yet) */
+ outl((tp->csr6 & ~0x00002002), ioaddr + CSR6);
+
+ /* send setup packet for cards that support it */
+ if (!(tp->flags & MC_HASH_ONLY)) {
+ /* enable transmit wait for completion */
+ outl(tp->csr6 | 0x00002000, ioaddr + CSR6);
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ printf ("%s: TX Setup Timeout.\n", tp->nic_name);
+ }
+ }
+
+ if (tp->chip_id == LC82C168)
+ tulip_check_duplex(nic);
+
+ set_rx_mode(nic);
+
+ /* enable transmit and receive */
+ outl(tp->csr6 | 0x00002002, ioaddr + CSR6);
+}
+
+
+/*********************************************************************/
+/* eth_transmit - Transmit a frame */
+/*********************************************************************/
+static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
+ unsigned int s, const char *p)
+{
+ u16 nstype;
+ u32 to;
+ u32 csr6 = inl(ioaddr + CSR6);
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_transmit\n");
+#endif
+
+ /* Disable Tx */
+ outl(csr6 & ~0x00002000, ioaddr + CSR6);
+
+ memcpy(txb, d, ETH_ALEN);
+ memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
+ nstype = htons((u16) t);
+ memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2);
+ memcpy(txb + ETH_HLEN, p, s);
+
+ s += ETH_HLEN;
+ s &= 0x0FFF;
+
+ /* pad to minimum packet size */
+ while (s < ETH_ZLEN)
+ txb[s++] = '\0';
+
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t);
+#endif
+
+ /* setup the transmit descriptor */
+ /* 0x60000000 = no interrupt on completion */
+ tx_ring[0].length = cpu_to_le32(0x60000000 | s);
+ tx_ring[0].status = cpu_to_le32(0x80000000);
+
+ /* Point to transmit descriptor */
+ outl(virt_to_le32desc(&tx_ring[0]), ioaddr + CSR4);
+
+ /* Enable Tx */
+ outl(csr6 | 0x00002000, ioaddr + CSR6);
+ /* immediate transmit demand */
+ outl(0, ioaddr + CSR1);
+
+ to = currticks() + TX_TIME_OUT;
+ while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
+ /* wait */ ;
+
+ if (currticks() >= to) {
+ printf ("TX Timeout!\n");
+ }
+
+ /* Disable Tx */
+ outl(csr6 & ~0x00002000, ioaddr + CSR6);
+}
+
+/*********************************************************************/
+/* eth_poll - Wait for a frame */
+/*********************************************************************/
+static int tulip_poll(struct nic *nic, int retrieve)
+{
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_poll\n");
+#endif
+
+ /* no packet waiting. packet still owned by NIC */
+ if (rx_ring[tp->cur_rx].status & 0x80000000)
+ return 0;
+
+ if ( ! retrieve ) return 1;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_poll got one\n");
+#endif
+
+ nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16;
+
+ /* if we get a corrupted packet. throw it away and move on */
+ if (rx_ring[tp->cur_rx].status & 0x00008000) {
+ /* return the descriptor and buffer to receive ring */
+ rx_ring[tp->cur_rx].status = 0x80000000;
+ tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
+ return 0;
+ }
+
+ /* copy packet to working buffer */
+ memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen);
+
+ /* return the descriptor and buffer to receive ring */
+ rx_ring[tp->cur_rx].status = 0x80000000;
+ tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
+
+ return 1;
+}
+
+/*********************************************************************/
+/* eth_disable - Disable the interface */
+/*********************************************************************/
+static void tulip_disable ( struct nic *nic ) {
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_disable\n");
+#endif
+
+ tulip_reset(nic);
+
+ /* disable interrupts */
+ outl(0x00000000, ioaddr + CSR7);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+}
+
+/*********************************************************************/
+/*IRQ - Enable, Disable, or Force interrupts */
+/*********************************************************************/
+static void tulip_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations tulip_operations = {
+ .connect = dummy_connect,
+ .poll = tulip_poll,
+ .transmit = tulip_transmit,
+ .irq = tulip_irq,
+
+};
+
+/*********************************************************************/
+/* eth_probe - Look for an adapter */
+/*********************************************************************/
+static int tulip_probe ( struct nic *nic, struct pci_device *pci ) {
+
+ u32 i;
+ u8 chip_rev;
+ u8 ee_data[EEPROM_SIZE];
+ unsigned short sum;
+ int chip_idx;
+ static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+
+ if (pci->ioaddr == 0)
+ return 0;
+
+ ioaddr = pci->ioaddr;
+ nic->ioaddr = pci->ioaddr & ~3;
+ nic->irqno = 0;
+
+ /* point to private storage */
+ tp = &tulip_bss.tpx;
+
+ tp->vendor_id = pci->vendor;
+ tp->dev_id = pci->device;
+
+ tp->if_port = 0;
+ tp->default_port = 0;
+
+ adjust_pci_device(pci);
+
+ /* disable interrupts */
+ outl(0x00000000, ioaddr + CSR7);
+
+ /* Stop the chip's Tx and Rx processes. */
+ outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
+
+ /* Clear the missed-packet counter. */
+ inl(ioaddr + CSR8);
+
+ printf("\n"); /* so we start on a fresh line */
+#ifdef TULIP_DEBUG_WHERE
+ whereami("tulip_probe\n");
+#endif
+
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf ("%s: Looking for Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name,
+ tp->vendor, tp->dev_id);
+#endif
+
+ /* Figure out which chip we're dealing with */
+ i = 0;
+ chip_idx = -1;
+
+ while (pci_id_tbl[i].name) {
+ if ( (((u32) tp->dev_id << 16) | tp->vendor_id) ==
+ (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) {
+ chip_idx = pci_id_tbl[i].drv_flags;
+ break;
+ }
+ i++;
+ }
+
+ if (chip_idx == -1) {
+ printf ("%s: Unknown Tulip Chip: Vendor=%hX Device=%hX\n", tp->nic_name,
+ tp->vendor_id, tp->dev_id);
+ return 0;
+ }
+
+ tp->pci_id_idx = i;
+ tp->flags = tulip_tbl[chip_idx].flags;
+
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1) {
+ printf ("%s: tp->pci_id_idx == %d, name == %s\n", tp->nic_name,
+ tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name);
+ printf ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx,
+ tulip_tbl[chip_idx].chip_name);
+ }
+#endif
+
+ /* Bring the 21041/21143 out of sleep mode.
+ Caution: Snooze mode does not work with some boards! */
+ if (tp->flags & HAS_PWRDWN)
+ pci_write_config_dword(pci, 0x40, 0x00000000);
+
+ if (inl(ioaddr + CSR5) == 0xFFFFFFFF) {
+ printf("%s: The Tulip chip at %X is not functioning.\n",
+ tp->nic_name, (unsigned int) ioaddr);
+ return 0;
+ }
+
+ pci_read_config_byte(pci, PCI_REVISION, &chip_rev);
+
+ printf("%s: [chip: %s] rev %d at %hX\n", tp->nic_name,
+ tulip_tbl[chip_idx].chip_name, chip_rev, (unsigned int) ioaddr);
+ printf("%s: Vendor=%hX Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id);
+
+ if (chip_idx == DC21041 && inl(ioaddr + CSR9) & 0x8000) {
+ printf(" 21040 compatible mode.");
+ chip_idx = DC21040;
+ }
+
+ printf("\n");
+
+ /* The SROM/EEPROM interface varies dramatically. */
+ sum = 0;
+ if (chip_idx == DC21040) {
+ outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */
+ for (i = 0; i < ETH_ALEN; i++) {
+ int value, boguscnt = 100000;
+ do
+ value = inl(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+ nic->node_addr[i] = value;
+ sum += value & 0xff;
+ }
+ } else if (chip_idx == LC82C168) {
+ for (i = 0; i < 3; i++) {
+ int value, boguscnt = 100000;
+ outl(0x600 | i, ioaddr + 0x98);
+ do
+ value = inl(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+ put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i);
+ sum += value & 0xffff;
+ }
+ } else if (chip_idx == COMET) {
+ /* No need to read the EEPROM. */
+ put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr);
+ put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4));
+ for (i = 0; i < ETH_ALEN; i ++)
+ sum += nic->node_addr[i];
+ } else {
+ /* A serial EEPROM interface, we read now and sort it out later. */
+ int sa_offset = 0;
+ int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+
+ for (i = 0; i < sizeof(ee_data)/2; i++)
+ ((u16 *)ee_data)[i] =
+ le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));
+
+ /* DEC now has a specification (see Notes) but early board makers
+ just put the address in the first EEPROM locations. */
+ /* This does memcmp(eedata, eedata+16, 8) */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ sa_offset = 20;
+ if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
+ sa_offset = 2; /* Grrr, damn Matrox boards. */
+ }
+ for (i = 0; i < ETH_ALEN; i ++) {
+ nic->node_addr[i] = ee_data[i + sa_offset];
+ sum += ee_data[i + sa_offset];
+ }
+ }
+ /* Lite-On boards have the address byte-swapped. */
+ if ((nic->node_addr[0] == 0xA0 || nic->node_addr[0] == 0xC0)
+ && nic->node_addr[1] == 0x00)
+ for (i = 0; i < ETH_ALEN; i+=2) {
+ char tmp = nic->node_addr[i];
+ nic->node_addr[i] = nic->node_addr[i+1];
+ nic->node_addr[i+1] = tmp;
+ }
+
+ if (sum == 0 || sum == ETH_ALEN*0xff) {
+ printf("%s: EEPROM not present!\n", tp->nic_name);
+ for (i = 0; i < ETH_ALEN-1; i++)
+ nic->node_addr[i] = last_phys_addr[i];
+ nic->node_addr[i] = last_phys_addr[i] + 1;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ last_phys_addr[i] = nic->node_addr[i];
+
+ DBG ( "%s: %s at ioaddr %hX\n", tp->nic_name, eth_ntoa ( nic->node_addr ),
+ (unsigned int) ioaddr );
+
+ tp->chip_id = chip_idx;
+ tp->revision = chip_rev;
+ tp->csr0 = csr0;
+
+ /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
+ And the ASIX must have a burst limit or horrible things happen. */
+ if (chip_idx == DC21143 && chip_rev == 65)
+ tp->csr0 &= ~0x01000000;
+ else if (tp->flags & IS_ASIX)
+ tp->csr0 |= 0x2000;
+
+ if (media_cap[tp->default_port] & MediaIsMII) {
+ static const u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60,
+ 0x80, 0x100, 0x200 };
+ tp->mii_advertise = media2advert[tp->default_port - 9];
+ tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
+ }
+
+ /* This is logically part of the probe routine, but too complex
+ to write inline. */
+ if (tp->flags & HAS_MEDIA_TABLE) {
+ memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
+ parse_eeprom(nic);
+ }
+
+ start_link(nic);
+
+ /* reset the device and make ready for tx and rx of packets */
+ tulip_reset(nic);
+ nic->nic_op = &tulip_operations;
+
+ /* give the board a chance to reset before returning */
+ tulip_wait(4*TICKS_PER_SEC);
+
+ return 1;
+}
+
+static void start_link(struct nic *nic)
+{
+ int i;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("start_link\n");
+#endif
+
+ if ((tp->flags & ALWAYS_CHECK_MII) ||
+ (tp->mtable && tp->mtable->has_mii) ||
+ ( ! tp->mtable && (tp->flags & HAS_MII))) {
+ unsigned int phy, phy_idx;
+ if (tp->mtable && tp->mtable->has_mii) {
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == 11) {
+ tp->cur_index = i;
+ tp->saved_if_port = tp->if_port;
+ select_media(nic, 2);
+ tp->if_port = tp->saved_if_port;
+ break;
+ }
+ }
+
+ /* Find the connected MII xcvrs. */
+ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+ phy++) {
+ int mii_status = mdio_read(nic, phy, 1);
+ if ((mii_status & 0x8301) == 0x8001 ||
+ ((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
+ int mii_reg0 = mdio_read(nic, phy, 0);
+ int mii_advert = mdio_read(nic, phy, 4);
+ int to_advert;
+
+ if (tp->mii_advertise)
+ to_advert = tp->mii_advertise;
+ else if (tp->advertising[phy_idx])
+ to_advert = tp->advertising[phy_idx];
+ else /* Leave unchanged. */
+ tp->mii_advertise = to_advert = mii_advert;
+
+ tp->phys[phy_idx++] = phy;
+ printf("%s: MII transceiver %d config %hX status %hX advertising %hX.\n",
+ tp->nic_name, phy, mii_reg0, mii_status, mii_advert);
+ /* Fixup for DLink with miswired PHY. */
+ if (mii_advert != to_advert) {
+ printf("%s: Advertising %hX on PHY %d previously advertising %hX.\n",
+ tp->nic_name, to_advert, phy, mii_advert);
+ mdio_write(nic, phy, 4, to_advert);
+ }
+ /* Enable autonegotiation: some boards default to off. */
+ mdio_write(nic, phy, 0, mii_reg0 |
+ (tp->full_duplex ? 0x1100 : 0x1000) |
+ (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
+ }
+ }
+ tp->mii_cnt = phy_idx;
+ if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
+ printf("%s: ***WARNING***: No MII transceiver found!\n",
+ tp->nic_name);
+ tp->phys[0] = 1;
+ }
+ }
+
+ /* Reset the xcvr interface and turn on heartbeat. */
+ switch (tp->chip_id) {
+ case DC21040:
+ outl(0x00000000, ioaddr + CSR13);
+ outl(0x00000004, ioaddr + CSR13);
+ break;
+ case DC21041:
+ /* This is nway_start(). */
+ if (tp->sym_advertise == 0)
+ tp->sym_advertise = 0x0061;
+ outl(0x00000000, ioaddr + CSR13);
+ outl(0xFFFFFFFF, ioaddr + CSR14);
+ outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
+ outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
+ outl(0x0000EF01, ioaddr + CSR13);
+ break;
+ case DC21140: default:
+ if (tp->mtable)
+ outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
+ break;
+ case DC21142:
+ case PNIC2:
+ if (tp->mii_cnt || media_cap[tp->if_port] & MediaIsMII) {
+ outl(0x82020000, ioaddr + CSR6);
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ outl(0x820E0000, ioaddr + CSR6);
+ } else
+ nway_start(nic);
+ break;
+ case LC82C168:
+ if ( ! tp->mii_cnt) {
+ tp->nway = 1;
+ tp->nwayset = 0;
+ outl(0x00420000, ioaddr + CSR6);
+ outl(0x30, ioaddr + CSR12);
+ outl(0x0001F078, ioaddr + 0xB8);
+ outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+ }
+ break;
+ case MX98713: case COMPEX9881:
+ outl(0x00000000, ioaddr + CSR6);
+ outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
+ outl(0x00000001, ioaddr + CSR13);
+ break;
+ case MX98715: case MX98725:
+ outl(0x01a80000, ioaddr + CSR6);
+ outl(0xFFFFFFFF, ioaddr + CSR14);
+ outl(0x00001000, ioaddr + CSR12);
+ break;
+ case COMET:
+ /* No initialization necessary. */
+ break;
+ }
+}
+
+static void nway_start(struct nic *nic __unused)
+{
+ int csr14 = ((tp->sym_advertise & 0x0780) << 9) |
+ ((tp->sym_advertise&0x0020)<<1) | 0xffbf;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("nway_start\n");
+#endif
+
+ tp->if_port = 0;
+ tp->nway = tp->mediasense = 1;
+ tp->nwayset = tp->lpar = 0;
+ if (tp->chip_id == PNIC2) {
+ tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
+ return;
+ }
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Restarting internal NWay autonegotiation, %X.\n",
+ tp->nic_name, csr14);
+#endif
+ outl(0x0001, ioaddr + CSR13);
+ outl(csr14, ioaddr + CSR14);
+ tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
+ outl(tp->csr6, ioaddr + CSR6);
+ if (tp->mtable && tp->mtable->csr15dir) {
+ outl(tp->mtable->csr15dir, ioaddr + CSR15);
+ outl(tp->mtable->csr15val, ioaddr + CSR15);
+ } else if (tp->chip_id != PNIC2)
+ outw(0x0008, ioaddr + CSR15);
+ if (tp->chip_id == DC21041) /* Trigger NWAY. */
+ outl(0xEF01, ioaddr + CSR12);
+ else
+ outl(0x1301, ioaddr + CSR12);
+}
+
+static void init_media(struct nic *nic)
+{
+ int i;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("init_media\n");
+#endif
+
+ tp->saved_if_port = tp->if_port;
+ if (tp->if_port == 0)
+ tp->if_port = tp->default_port;
+
+ /* Allow selecting a default media. */
+ i = 0;
+ if (tp->mtable == NULL)
+ goto media_picked;
+ if (tp->if_port) {
+ int looking_for = media_cap[tp->if_port] & MediaIsMII ? 11 :
+ (tp->if_port == 12 ? 0 : tp->if_port);
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ printf("%s: Using user-specified media %s.\n",
+ tp->nic_name, medianame[tp->if_port]);
+ goto media_picked;
+ }
+ }
+ if ((tp->mtable->defaultmedia & 0x0800) == 0) {
+ int looking_for = tp->mtable->defaultmedia & 15;
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ printf("%s: Using EEPROM-set media %s.\n",
+ tp->nic_name, medianame[looking_for]);
+ goto media_picked;
+ }
+ }
+ /* Start sensing first non-full-duplex media. */
+ for (i = tp->mtable->leafcount - 1;
+ (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
+ ;
+ media_picked:
+
+ tp->csr6 = 0;
+ tp->cur_index = i;
+ tp->nwayset = 0;
+
+ if (tp->if_port) {
+ if (tp->chip_id == DC21143 && media_cap[tp->if_port] & MediaIsMII) {
+ /* We must reset the media CSRs when we force-select MII mode. */
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ outl(0x0008, ioaddr + CSR15);
+ }
+ select_media(nic, 1);
+ return;
+ }
+ switch(tp->chip_id) {
+ case DC21041:
+ /* tp->nway = 1;*/
+ nway_start(nic);
+ break;
+ case DC21142:
+ if (tp->mii_cnt) {
+ select_media(nic, 1);
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Using MII transceiver %d, status %hX.\n",
+ tp->nic_name, tp->phys[0], mdio_read(nic, tp->phys[0], 1));
+#endif
+ outl(0x82020000, ioaddr + CSR6);
+ tp->csr6 = 0x820E0000;
+ tp->if_port = 11;
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ } else
+ nway_start(nic);
+ break;
+ case PNIC2:
+ nway_start(nic);
+ break;
+ case LC82C168:
+ if (tp->mii_cnt) {
+ tp->if_port = 11;
+ tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0001, ioaddr + CSR15);
+ } else if (inl(ioaddr + CSR5) & TPLnkPass)
+ pnic_do_nway(nic);
+ else {
+ /* Start with 10mbps to do autonegotiation. */
+ outl(0x32, ioaddr + CSR12);
+ tp->csr6 = 0x00420000;
+ outl(0x0001B078, ioaddr + 0xB8);
+ outl(0x0201B078, ioaddr + 0xB8);
+ }
+ break;
+ case MX98713: case COMPEX9881:
+ tp->if_port = 0;
+ tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+ break;
+ case MX98715: case MX98725:
+ /* Provided by BOLO, Macronix - 12/10/1998. */
+ tp->if_port = 0;
+ tp->csr6 = 0x01a80200;
+ outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+ outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
+ break;
+ case COMET:
+ /* Enable automatic Tx underrun recovery */
+ outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
+ tp->if_port = 0;
+ tp->csr6 = 0x00040000;
+ break;
+ case AX88140: case AX88141:
+ tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
+ break;
+ default:
+ select_media(nic, 1);
+ }
+}
+
+static void pnic_do_nway(struct nic *nic __unused)
+{
+ u32 phy_reg = inl(ioaddr + 0xB8);
+ u32 new_csr6 = tp->csr6 & ~0x40C40200;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("pnic_do_nway\n");
+#endif
+
+ if (phy_reg & 0x78000000) { /* Ignore baseT4 */
+ if (phy_reg & 0x20000000) tp->if_port = 5;
+ else if (phy_reg & 0x40000000) tp->if_port = 3;
+ else if (phy_reg & 0x10000000) tp->if_port = 4;
+ else if (phy_reg & 0x08000000) tp->if_port = 0;
+ tp->nwayset = 1;
+ new_csr6 = (tp->if_port & 1) ? 0x01860000 : 0x00420000;
+ outl(0x32 | (tp->if_port & 1), ioaddr + CSR12);
+ if (tp->if_port & 1)
+ outl(0x1F868, ioaddr + 0xB8);
+ if (phy_reg & 0x30000000) {
+ tp->full_duplex = 1;
+ new_csr6 |= 0x00000200;
+ }
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: PNIC autonegotiated status %X, %s.\n",
+ tp->nic_name, phy_reg, medianame[tp->if_port]);
+#endif
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ }
+ }
+}
+
+/* Set up the transceiver control registers for the selected media type. */
+static void select_media(struct nic *nic, int startup)
+{
+ struct mediatable *mtable = tp->mtable;
+ u32 new_csr6;
+ int i;
+
+#ifdef TULIP_DEBUG_WHERE
+ whereami("select_media\n");
+#endif
+
+ if (mtable) {
+ struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
+ unsigned char *p = mleaf->leafdata;
+ switch (mleaf->type) {
+ case 0: /* 21140 non-MII xcvr. */
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Using a 21140 non-MII transceiver"
+ " with control setting %hhX.\n",
+ tp->nic_name, p[1]);
+#endif
+ tp->if_port = p[0];
+ if (startup)
+ outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ outl(p[1], ioaddr + CSR12);
+ new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
+ break;
+ case 2: case 4: {
+ u16 setup[5];
+ u32 csr13val, csr14val, csr15dir, csr15val;
+ for (i = 0; i < 5; i++)
+ setup[i] = get_u16(&p[i*2 + 1]);
+
+ tp->if_port = p[0] & 15;
+ if (media_cap[tp->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+
+ if (startup && mtable->has_reset) {
+ struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+ unsigned char *rst = rleaf->leafdata;
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Resetting the transceiver.\n",
+ tp->nic_name);
+#endif
+ for (i = 0; i < rst[0]; i++)
+ outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+ }
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: 21143 non-MII %s transceiver control "
+ "%hX/%hX.\n",
+ tp->nic_name, medianame[tp->if_port], setup[0], setup[1]);
+#endif
+ if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */
+ csr13val = setup[0];
+ csr14val = setup[1];
+ csr15dir = (setup[3]<<16) | setup[2];
+ csr15val = (setup[4]<<16) | setup[2];
+ outl(0, ioaddr + CSR13);
+ outl(csr14val, ioaddr + CSR14);
+ outl(csr15dir, ioaddr + CSR15); /* Direction */
+ outl(csr15val, ioaddr + CSR15); /* Data */
+ outl(csr13val, ioaddr + CSR13);
+ } else {
+ csr13val = 1;
+ csr14val = 0x0003FF7F;
+ csr15dir = (setup[0]<<16) | 0x0008;
+ csr15val = (setup[1]<<16) | 0x0008;
+ if (tp->if_port <= 4)
+ csr14val = t21142_csr14[tp->if_port];
+ if (startup) {
+ outl(0, ioaddr + CSR13);
+ outl(csr14val, ioaddr + CSR14);
+ }
+ outl(csr15dir, ioaddr + CSR15); /* Direction */
+ outl(csr15val, ioaddr + CSR15); /* Data */
+ if (startup) outl(csr13val, ioaddr + CSR13);
+ }
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Setting CSR15 to %X/%X.\n",
+ tp->nic_name, csr15dir, csr15val);
+#endif
+ if (mleaf->type == 4)
+ new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
+ else
+ new_csr6 = 0x82420000;
+ break;
+ }
+ case 1: case 3: {
+ int phy_num = p[0];
+ int init_length = p[1];
+ u16 *misc_info;
+
+ tp->if_port = 11;
+ new_csr6 = 0x020E0000;
+ if (mleaf->type == 3) { /* 21142 */
+ u16 *init_sequence = (u16*)(p+2);
+ u16 *reset_sequence = &((u16*)(p+3))[init_length];
+ int reset_length = p[2 + init_length*2];
+ misc_info = reset_sequence + reset_length;
+ if (startup)
+ for (i = 0; i < reset_length; i++)
+ outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
+ for (i = 0; i < init_length; i++)
+ outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
+ } else {
+ u8 *init_sequence = p + 2;
+ u8 *reset_sequence = p + 3 + init_length;
+ int reset_length = p[2 + init_length];
+ misc_info = (u16*)(reset_sequence + reset_length);
+ if (startup) {
+ outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ for (i = 0; i < reset_length; i++)
+ outl(reset_sequence[i], ioaddr + CSR12);
+ }
+ for (i = 0; i < init_length; i++)
+ outl(init_sequence[i], ioaddr + CSR12);
+ }
+ tp->advertising[phy_num] = get_u16(&misc_info[1]) | 1;
+ if (startup < 2) {
+ if (tp->mii_advertise == 0)
+ tp->mii_advertise = tp->advertising[phy_num];
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Advertising %hX on MII %d.\n",
+ tp->nic_name, tp->mii_advertise, tp->phys[phy_num]);
+#endif
+ mdio_write(nic, tp->phys[phy_num], 4, tp->mii_advertise);
+ }
+ break;
+ }
+ default:
+ printf("%s: Invalid media table selection %d.\n",
+ tp->nic_name, mleaf->type);
+ new_csr6 = 0x020E0000;
+ }
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: Using media type %s, CSR12 is %hhX.\n",
+ tp->nic_name, medianame[tp->if_port],
+ inl(ioaddr + CSR12) & 0xff);
+#endif
+ } else if (tp->chip_id == DC21041) {
+ int port = tp->if_port <= 4 ? tp->if_port : 0;
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: 21041 using media %s, CSR12 is %hX.\n",
+ tp->nic_name, medianame[port == 3 ? 12: port],
+ inl(ioaddr + CSR12));
+#endif
+ outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
+ outl(t21041_csr14[port], ioaddr + CSR14);
+ outl(t21041_csr15[port], ioaddr + CSR15);
+ outl(t21041_csr13[port], ioaddr + CSR13);
+ new_csr6 = 0x80020000;
+ } else if (tp->chip_id == LC82C168) {
+ if (startup && ! tp->medialock)
+ tp->if_port = tp->mii_cnt ? 11 : 0;
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: PNIC PHY status is %hX, media %s.\n",
+ tp->nic_name, inl(ioaddr + 0xB8), medianame[tp->if_port]);
+#endif
+ if (tp->mii_cnt) {
+ new_csr6 = 0x810C0000;
+ outl(0x0001, ioaddr + CSR15);
+ outl(0x0201B07A, ioaddr + 0xB8);
+ } else if (startup) {
+ /* Start with 10mbps to do autonegotiation. */
+ outl(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ outl(0x0001B078, ioaddr + 0xB8);
+ outl(0x0201B078, ioaddr + 0xB8);
+ } else if (tp->if_port == 3 || tp->if_port == 5) {
+ outl(0x33, ioaddr + CSR12);
+ new_csr6 = 0x01860000;
+ /* Trigger autonegotiation. */
+ outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
+ } else {
+ outl(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ outl(0x1F078, ioaddr + 0xB8);
+ }
+ } else if (tp->chip_id == DC21040) { /* 21040 */
+ /* Turn on the xcvr interface. */
+#ifdef TULIP_DEBUG
+ int csr12 = inl(ioaddr + CSR12);
+ if (tulip_debug > 1)
+ printf("%s: 21040 media type is %s, CSR12 is %hhX.\n",
+ tp->nic_name, medianame[tp->if_port], csr12);
+#endif
+ if (media_cap[tp->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+ new_csr6 = 0x20000;
+ /* Set the full duplux match frame. */
+ outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
+ outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
+ if (t21040_csr13[tp->if_port] & 8) {
+ outl(0x0705, ioaddr + CSR14);
+ outl(0x0006, ioaddr + CSR15);
+ } else {
+ outl(0xffff, ioaddr + CSR14);
+ outl(0x0000, ioaddr + CSR15);
+ }
+ outl(0x8f01 | t21040_csr13[tp->if_port], ioaddr + CSR13);
+ } else { /* Unknown chip type with no media table. */
+ if (tp->default_port == 0)
+ tp->if_port = tp->mii_cnt ? 11 : 3;
+ if (media_cap[tp->if_port] & MediaIsMII) {
+ new_csr6 = 0x020E0000;
+ } else if (media_cap[tp->if_port] & MediaIsFx) {
+ new_csr6 = 0x028600000;
+ } else
+ new_csr6 = 0x038600000;
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: No media description table, assuming "
+ "%s transceiver, CSR12 %hhX.\n",
+ tp->nic_name, medianame[tp->if_port],
+ inl(ioaddr + CSR12));
+#endif
+ }
+
+ tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
+ return;
+}
+
+/*
+ Check the MII negotiated duplex and change the CSR6 setting if
+ required.
+ Return 0 if everything is OK.
+ Return < 0 if the transceiver is missing or has no link beat.
+*/
+static int tulip_check_duplex(struct nic *nic)
+{
+ unsigned int bmsr, lpa, negotiated, new_csr6;
+
+ bmsr = mdio_read(nic, tp->phys[0], 1);
+ lpa = mdio_read(nic, tp->phys[0], 5);
+
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: MII status %#x, Link partner report "
+ "%#x.\n", tp->nic_name, bmsr, lpa);
+#endif
+
+ if (bmsr == 0xffff)
+ return -2;
+ if ((bmsr & 4) == 0) {
+ int new_bmsr = mdio_read(nic, tp->phys[0], 1);
+ if ((new_bmsr & 4) == 0) {
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 1)
+ printf("%s: No link beat on the MII interface,"
+ " status %#x.\n", tp->nic_name,
+ new_bmsr);
+#endif
+ return -1;
+ }
+ }
+ tp->full_duplex = lpa & 0x140;
+
+ new_csr6 = tp->csr6;
+ negotiated = lpa & tp->advertising[0];
+
+ if(negotiated & 0x380) new_csr6 &= ~0x400000;
+ else new_csr6 |= 0x400000;
+ if (tp->full_duplex) new_csr6 |= 0x200;
+ else new_csr6 &= ~0x200;
+
+ if (new_csr6 != tp->csr6) {
+ tp->csr6 = new_csr6;
+
+#ifdef TULIP_DEBUG
+ if (tulip_debug > 0)
+ printf("%s: Setting %s-duplex based on MII"
+ "#%d link partner capability of %#x.\n",
+ tp->nic_name,
+ tp->full_duplex ? "full" : "half",
+ tp->phys[0], lpa);
+#endif
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct pci_device_id tulip_nics[] = {
+PCI_ROM(0x1011, 0x0002, "dc21040", "Digital Tulip", 0),
+PCI_ROM(0x1011, 0x0009, "ds21140", "Digital Tulip Fast", 0),
+PCI_ROM(0x1011, 0x0014, "dc21041", "Digital Tulip+", 0),
+PCI_ROM(0x1011, 0x0019, "ds21142", "Digital Tulip 21142", 0),
+PCI_ROM(0x10b7, 0x9300, "3csoho100b-tx","3ComSOHO100B-TX", 0),
+PCI_ROM(0x10b9, 0x5261, "ali1563", "ALi 1563 integrated ethernet", 0),
+PCI_ROM(0x10d9, 0x0512, "mx98713", "Macronix MX987x3", 0),
+PCI_ROM(0x10d9, 0x0531, "mx98715", "Macronix MX987x5", 0),
+PCI_ROM(0x1113, 0x1217, "mxic-98715", "Macronix MX987x5", 0),
+PCI_ROM(0x11ad, 0xc115, "lc82c115", "LinkSys LNE100TX", 0),
+PCI_ROM(0x11ad, 0x0002, "82c168", "Netgear FA310TX", 0),
+PCI_ROM(0x1282, 0x9100, "dm9100", "Davicom 9100", 0),
+PCI_ROM(0x1282, 0x9102, "dm9102", "Davicom 9102", 0),
+PCI_ROM(0x1282, 0x9009, "dm9009", "Davicom 9009", 0),
+PCI_ROM(0x1282, 0x9132, "dm9132", "Davicom 9132", 0),
+PCI_ROM(0x1317, 0x0985, "centaur-p", "ADMtek Centaur-P", 0),
+PCI_ROM(0x1317, 0x0981, "an981", "ADMtek AN981 Comet", 0), /* ADMTek Centaur-P (stmicro) */
+PCI_ROM(0x1113, 0x1216, "an983", "ADMTek AN983 Comet", 0),
+PCI_ROM(0x1317, 0x9511, "an983b", "ADMTek Comet 983b", 0),
+PCI_ROM(0x1317, 0x1985, "centaur-c", "ADMTek Centaur-C", 0),
+PCI_ROM(0x8086, 0x0039, "intel21145", "Intel Tulip", 0),
+PCI_ROM(0x125b, 0x1400, "ax88140", "ASIX AX88140", 0),
+PCI_ROM(0x11f6, 0x9881, "rl100tx", "Compex RL100-TX", 0),
+PCI_ROM(0x115d, 0x0003, "xircomtulip", "Xircom Tulip", 0),
+PCI_ROM(0x104a, 0x0981, "tulip-0981", "Tulip 0x104a 0x0981", 0),
+PCI_ROM(0x104a, 0x2774, "SGThomson-STE10100A", "Tulip 0x104a 0x2774", 0), /*Modified by Ramesh Chander*/
+PCI_ROM(0x1113, 0x9511, "tulip-9511", "Tulip 0x1113 0x9511", 0),
+PCI_ROM(0x1186, 0x1561, "tulip-1561", "Tulip 0x1186 0x1561", 0),
+PCI_ROM(0x1259, 0xa120, "tulip-a120", "Tulip 0x1259 0xa120", 0),
+PCI_ROM(0x13d1, 0xab02, "tulip-ab02", "Tulip 0x13d1 0xab02", 0),
+PCI_ROM(0x13d1, 0xab03, "tulip-ab03", "Tulip 0x13d1 0xab03", 0),
+PCI_ROM(0x13d1, 0xab08, "tulip-ab08", "Tulip 0x13d1 0xab08", 0),
+PCI_ROM(0x14f1, 0x1803, "lanfinity", "Conexant LANfinity", 0),
+PCI_ROM(0x1626, 0x8410, "tulip-8410", "Tulip 0x1626 0x8410", 0),
+PCI_ROM(0x1737, 0xab08, "tulip-1737-ab08","Tulip 0x1737 0xab08", 0),
+PCI_ROM(0x1737, 0xab09, "tulip-ab09", "Tulip 0x1737 0xab09", 0),
+};
+
+PCI_DRIVER ( tulip_driver, tulip_nics, PCI_NO_CLASS );
+
+DRIVER ( "Tulip", nic_driver, pci_driver, tulip_driver,
+ tulip_probe, tulip_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/net/w89c840.c b/debian/grub-extras/disabled/gpxe/src/drivers/net/w89c840.c
new file mode 100644
index 0000000..fa6188a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/net/w89c840.c
@@ -0,0 +1,964 @@
+/*
+ * Etherboot - BOOTP/TFTP Bootstrap Program
+ *
+ * w89c840.c -- This file implements the winbond-840 driver for etherboot.
+ *
+ */
+
+/*
+ * Adapted by Igor V. Kovalenko
+ * -- <garrison@mail.ru>
+ * OR
+ * -- <iko@crec.mipt.ru>
+ * Initial adaptaion stage, including testing, completed 23 August 2000.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * date version by what
+ * Written: Aug 20 2000 V0.10 iko Initial revision.
+ * changes: Aug 22 2000 V0.90 iko Works!
+ * Aug 23 2000 V0.91 iko Cleanup, posted to etherboot
+ * maintainer.
+ * Aug 26 2000 V0.92 iko Fixed Rx ring handling.
+ * First Linux Kernel (TM)
+ * successfully loaded using
+ * this driver.
+ * Jan 07 2001 V0.93 iko Transmitter timeouts are handled
+ * using timer2 routines. Proposed
+ * by Ken Yap to eliminate CPU speed
+ * dependency.
+ * Dec 12 2003 V0.94 timlegge Fixed issues in 5.2, removed
+ * interrupt usage, enabled
+ * multicast support
+ *
+ * This is the etherboot driver for cards based on Winbond W89c840F chip.
+ *
+ * It was written from skeleton source, with Donald Becker's winbond-840.c
+ * kernel driver as a guideline. Mostly the w89c840 related definitions
+ * and the lower level routines have been cut-and-pasted into this source.
+ *
+ * Frankly speaking, about 90% of the code was obtained using cut'n'paste
+ * sequence :) while the remainder appeared while brainstorming
+ * Linux Kernel 2.4.0-testX source code. Thanks, Donald and Linus!
+ *
+ * There was a demand for using this card in a rather large
+ * remote boot environment at MSKP OVTI Lab of
+ * Moscow Institute for Physics and Technology (MIPT) -- http://www.mipt.ru/
+ * so you may count that for motivation.
+ *
+ */
+
+/*
+ * If you want to see debugging output then define W89C840_DEBUG
+ */
+
+/*
+#define W89C840_DEBUG
+*/
+
+/*
+ * Keep using IO_OPS for Etherboot driver!
+ */
+#define USE_IO_OPS
+
+#include "etherboot.h"
+#include "nic.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
+
+static const char *w89c840_version = "driver Version 0.94 - December 12, 2003";
+
+/* Linux support functions */
+#define virt_to_le32desc(addr) virt_to_bus(addr)
+#define le32desc_to_virt(addr) bus_to_virt(addr)
+
+/*
+#define cpu_to_le32(val) (val)
+#define le32_to_cpu(val) (val)
+*/
+
+/* Operational parameters that are set at compile time. */
+
+/* Keep the ring sizes a power of two for compile efficiency.
+ The compiler will convert <unsigned>'%'<2^N> into a bit mask.
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE 2
+#define RX_RING_SIZE 2
+
+/* The presumed FIFO size for working around the Tx-FIFO-overflow bug.
+ To avoid overflowing we don't queue again until we have room for a
+ full-size packet.
+ */
+#define TX_FIFO_SIZE (2048)
+#define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (10*1000)
+
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+
+/*
+ * Used to be this much CPU loops on Celeron@400 (?),
+ * now using real timer and TX_TIMEOUT!
+ * #define TX_LOOP_COUNT 10000000
+ */
+
+#if !defined(__OPTIMIZE__)
+#warning You must compile this file with the correct options!
+#warning See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
+enum chip_capability_flags {CanHaveMII=1, HasBrokenTx=2};
+
+#ifdef USE_IO_OPS
+#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
+#else
+#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
+#endif
+
+static u32 driver_flags = CanHaveMII | HasBrokenTx;
+
+/* This driver was written to use PCI memory space, however some x86 systems
+ work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space
+ accesses instead of memory space. */
+
+#ifdef USE_IO_OPS
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+#define readb inb
+#define readw inw
+#define readl inl
+#define writeb outb
+#define writew outw
+#define writel outl
+#endif
+
+/* Offsets to the Command and Status Registers, "CSRs".
+ While similar to the Tulip, these registers are longword aligned.
+ Note: It's not useful to define symbolic names for every register bit in
+ the device. The name can only partially document the semantics and make
+ the driver longer and more difficult to read.
+*/
+enum w840_offsets {
+ PCIBusCfg=0x00, TxStartDemand=0x04, RxStartDemand=0x08,
+ RxRingPtr=0x0C, TxRingPtr=0x10,
+ IntrStatus=0x14, NetworkConfig=0x18, IntrEnable=0x1C,
+ RxMissed=0x20, EECtrl=0x24, MIICtrl=0x24, BootRom=0x28, GPTimer=0x2C,
+ CurRxDescAddr=0x30, CurRxBufAddr=0x34, /* Debug use */
+ MulticastFilter0=0x38, MulticastFilter1=0x3C, StationAddr=0x40,
+ CurTxDescAddr=0x4C, CurTxBufAddr=0x50,
+};
+
+/* Bits in the interrupt status/enable registers. */
+/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
+enum intr_status_bits {
+ NormalIntr=0x10000, AbnormalIntr=0x8000,
+ IntrPCIErr=0x2000, TimerInt=0x800,
+ IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40,
+ TxFIFOUnderflow=0x20, RxErrIntr=0x10,
+ TxIdle=0x04, IntrTxStopped=0x02, IntrTxDone=0x01,
+};
+
+/* Bits in the NetworkConfig register. */
+enum rx_mode_bits {
+ AcceptErr=0x80, AcceptRunt=0x40,
+ AcceptBroadcast=0x20, AcceptMulticast=0x10,
+ AcceptAllPhys=0x08, AcceptMyPhys=0x02,
+};
+
+enum mii_reg_bits {
+ MDIO_ShiftClk=0x10000, MDIO_DataIn=0x80000, MDIO_DataOut=0x20000,
+ MDIO_EnbOutput=0x40000, MDIO_EnbIn = 0x00000,
+};
+
+/* The Tulip Rx and Tx buffer descriptors. */
+struct w840_rx_desc {
+ s32 status;
+ s32 length;
+ u32 buffer1;
+ u32 next_desc;
+};
+
+struct w840_tx_desc {
+ s32 status;
+ s32 length;
+ u32 buffer1, buffer2; /* We use only buffer 1. */
+};
+
+/* Bits in network_desc.status */
+enum desc_status_bits {
+ DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000,
+ DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000,
+ DescIntr=0x80000000,
+};
+#define PRIV_ALIGN 15 /* Required alignment mask */
+#define PRIV_ALIGN_BYTES 32
+
+static struct winbond_private
+{
+ /* Descriptor rings first for alignment. */
+ struct w840_rx_desc rx_ring[RX_RING_SIZE];
+ struct w840_tx_desc tx_ring[TX_RING_SIZE];
+ struct net_device *next_module; /* Link for devices of this type. */
+ void *priv_addr; /* Unaligned address for kfree */
+ const char *product_name;
+ /* Frequently used values: keep some adjacent for cache effect. */
+ int chip_id, drv_flags;
+ struct pci_dev *pci_dev;
+ int csr6;
+ struct w840_rx_desc *rx_head_desc;
+ unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
+ unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ unsigned int cur_tx, dirty_tx;
+ int tx_q_bytes;
+ unsigned int tx_full:1; /* The Tx queue is full. */
+ /* These values are keep track of the transceiver/media in use. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int duplex_lock:1;
+ unsigned int medialock:1; /* Do not sense media. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
+ /* MII transceiver section. */
+ int mii_cnt; /* MII device addresses. */
+ u16 advertising; /* NWay media advertisement */
+ unsigned char phys[2]; /* MII device addresses. */
+} w840private __attribute__ ((aligned (PRIV_ALIGN_BYTES)));
+
+/* NIC specific static variables go here */
+
+static int ioaddr;
+static unsigned short eeprom [0x40];
+struct {
+ char rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
+ char tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
+} w89c840_buf __shared;
+
+static int eeprom_read(long ioaddr, int location);
+static int mdio_read(int base_address, int phy_id, int location);
+#if 0
+static void mdio_write(int base_address, int phy_id, int location, int value);
+#endif
+
+static void check_duplex(void);
+static void set_rx_mode(void);
+static void init_ring(void);
+
+#if defined(W89C840_DEBUG)
+static void decode_interrupt(u32 intr_status)
+{
+ printf("Interrupt status: ");
+
+#define TRACE_INTR(_intr_) \
+ if (intr_status & (_intr_)) { printf (" " #_intr_); }
+
+ TRACE_INTR(NormalIntr);
+ TRACE_INTR(AbnormalIntr);
+ TRACE_INTR(IntrPCIErr);
+ TRACE_INTR(TimerInt);
+ TRACE_INTR(IntrRxDied);
+ TRACE_INTR(RxNoBuf);
+ TRACE_INTR(IntrRxDone);
+ TRACE_INTR(TxFIFOUnderflow);
+ TRACE_INTR(RxErrIntr);
+ TRACE_INTR(TxIdle);
+ TRACE_INTR(IntrTxStopped);
+ TRACE_INTR(IntrTxDone);
+
+ printf("\n");
+ /*sleep(1);*/
+}
+#endif
+
+/**************************************************************************
+w89c840_reset - Reset adapter
+***************************************************************************/
+static void w89c840_reset(struct nic *nic)
+{
+ int i;
+
+ /* Reset the chip to erase previous misconfiguration.
+ No hold time required! */
+ writel(0x00000001, ioaddr + PCIBusCfg);
+
+ init_ring();
+
+ writel(virt_to_bus(w840private.rx_ring), ioaddr + RxRingPtr);
+ writel(virt_to_bus(w840private.tx_ring), ioaddr + TxRingPtr);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ writeb(nic->node_addr[i], ioaddr + StationAddr + i);
+
+ /* Initialize other registers. */
+ /* Configure the PCI bus bursts and FIFO thresholds.
+ 486: Set 8 longword cache alignment, 8 longword burst.
+ 586: Set 16 longword cache alignment, no burst limit.
+ Cache alignment bits 15:14 Burst length 13:8
+ 0000 <not allowed> 0000 align to cache 0800 8 longwords
+ 4000 8 longwords 0100 1 longword 1000 16 longwords
+ 8000 16 longwords 0200 2 longwords 2000 32 longwords
+ C000 32 longwords 0400 4 longwords
+ Wait the specified 50 PCI cycles after a reset by initializing
+ Tx and Rx queues and the address filter list. */
+
+ writel(0xE010, ioaddr + PCIBusCfg);
+
+ writel(0, ioaddr + RxStartDemand);
+ w840private.csr6 = 0x20022002;
+ check_duplex();
+ set_rx_mode();
+
+ /* Do not enable the interrupts Etherboot doesn't need them */
+/*
+ writel(0x1A0F5, ioaddr + IntrStatus);
+ writel(0x1A0F5, ioaddr + IntrEnable);
+*/
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Done reset.\n");
+#endif
+}
+
+#if 0
+static void handle_intr(u32 intr_stat)
+{
+ if ((intr_stat & (NormalIntr|AbnormalIntr)) == 0) {
+ /* we are polling, do not return now */
+ /*return 0;*/
+ } else {
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ writel(intr_stat & 0x001ffff, ioaddr + IntrStatus);
+ }
+
+ if (intr_stat & AbnormalIntr) {
+ /* There was an abnormal interrupt */
+ printf("\n-=- Abnormal interrupt.\n");
+
+#if defined(W89C840_DEBUG)
+ decode_interrupt(intr_stat);
+#endif
+
+ if (intr_stat & RxNoBuf) {
+ /* There was an interrupt */
+ printf("-=- <=> No receive buffers available.\n");
+ writel(0, ioaddr + RxStartDemand);
+ }
+ }
+}
+#endif
+
+/**************************************************************************
+w89c840_poll - Wait for a frame
+***************************************************************************/
+static int w89c840_poll(struct nic *nic, int retrieve)
+{
+ /* return true if there's an ethernet packet ready to read */
+ /* nic->packet should contain data on return */
+ /* nic->packetlen should contain length of data */
+ int packet_received = 0;
+
+#if defined(W89C840_DEBUG)
+ u32 intr_status = readl(ioaddr + IntrStatus);
+#endif
+
+ do {
+ /* Code from netdev_rx(dev) */
+
+ int entry = w840private.cur_rx % RX_RING_SIZE;
+
+ struct w840_rx_desc *desc = w840private.rx_head_desc;
+ s32 status = desc->status;
+
+ if (status & DescOwn) {
+ /* DescOwn bit is still set, we should wait for RX to complete */
+ packet_received = 0;
+ break;
+ }
+
+ if ( !retrieve ) {
+ packet_received = 1;
+ break;
+ }
+
+ if ((status & 0x38008300) != 0x0300) {
+ if ((status & 0x38000300) != 0x0300) {
+ /* Ingore earlier buffers. */
+ if ((status & 0xffff) != 0x7fff) {
+ printf("winbond-840 : Oversized Ethernet frame spanned "
+ "multiple buffers, entry %d status %X !\n",
+ w840private.cur_rx, (unsigned int) status);
+ }
+ } else if (status & 0x8000) {
+ /* There was a fatal error. */
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Receive error, Rx status %X :", status);
+ if (status & 0x0890) {
+ printf(" RXLEN_ERROR");
+ }
+ if (status & 0x004C) {
+ printf(", FRAME_ERROR");
+ }
+ if (status & 0x0002) {
+ printf(", CRC_ERROR");
+ }
+ printf("\n");
+#endif
+
+ /* Simpy do a reset now... */
+ w89c840_reset(nic);
+
+ packet_received = 0;
+ break;
+ }
+ } else {
+ /* Omit the four octet CRC from the length. */
+ int pkt_len = ((status >> 16) & 0x7ff) - 4;
+
+#if defined(W89C840_DEBUG)
+ printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status);
+#endif
+
+ nic->packetlen = pkt_len;
+
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+
+ memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len);
+ packet_received = 1;
+
+ /* Release buffer to NIC */
+ w840private.rx_ring[entry].status = DescOwn;
+
+#if defined(W89C840_DEBUG)
+ /* You will want this info for the initial debug. */
+ printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:"
+ "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX "
+ "%hhX.%hhX.%hhX.%hhX.\n",
+ nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3],
+ nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7],
+ nic->packet[8], nic->packet[9], nic->packet[10],
+ nic->packet[11], nic->packet[12], nic->packet[13],
+ nic->packet[14], nic->packet[15], nic->packet[16],
+ nic->packet[17]);
+#endif
+
+ }
+
+ entry = (++w840private.cur_rx) % RX_RING_SIZE;
+ w840private.rx_head_desc = &w840private.rx_ring[entry];
+ } while (0);
+
+ return packet_received;
+}
+
+/**************************************************************************
+w89c840_transmit - Transmit a frame
+***************************************************************************/
+
+static void w89c840_transmit(
+ struct nic *nic,
+ const char *d, /* Destination */
+ unsigned int t, /* Type */
+ unsigned int s, /* size */
+ const char *p) /* Packet */
+{
+ /* send the packet to destination */
+ unsigned entry;
+ int transmit_status;
+ unsigned long ct;
+
+ /* Caution: the write order is important here, set the field
+ with the "ownership" bits last. */
+
+ /* Fill in our transmit buffer */
+ entry = w840private.cur_tx % TX_RING_SIZE;
+
+ memcpy (w89c840_buf.tx_packet, d, ETH_ALEN); /* dst */
+ memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/
+
+ *((char *) w89c840_buf.tx_packet + 12) = t >> 8; /* type */
+ *((char *) w89c840_buf.tx_packet + 13) = t;
+
+ memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s);
+ s += ETH_HLEN;
+
+ while (s < ETH_ZLEN)
+ *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0;
+
+ w840private.tx_ring[entry].buffer1
+ = virt_to_le32desc(w89c840_buf.tx_packet);
+
+ w840private.tx_ring[entry].length = (DescWholePkt | (u32) s);
+ if (entry >= TX_RING_SIZE-1) /* Wrap ring */
+ w840private.tx_ring[entry].length |= (DescIntr | DescEndRing);
+ w840private.tx_ring[entry].status = (DescOwn);
+ w840private.cur_tx++;
+
+ w840private.tx_q_bytes = (u16) s;
+ writel(0, ioaddr + TxStartDemand);
+
+ /* Work around horrible bug in the chip by marking the queue as full
+ when we do not have FIFO room for a maximum sized packet. */
+
+ if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) {
+ /* Actually this is left to help finding error tails later in debugging...
+ * See Linux kernel driver in winbond-840.c for details.
+ */
+ w840private.tx_full = 1;
+ }
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
+#endif
+
+ /* Now wait for TX to complete. */
+ transmit_status = w840private.tx_ring[entry].status;
+
+ ct = currticks();
+ {
+#if defined W89C840_DEBUG
+ u32 intr_stat = 0;
+#endif
+ while (1) {
+
+#if defined(W89C840_DEBUG)
+ decode_interrupt(intr_stat);
+#endif
+
+ while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) {
+
+ transmit_status = w840private.tx_ring[entry].status;
+ }
+
+ break;
+ }
+ }
+
+ if ((transmit_status & DescOwn) == 0) {
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
+ w840private.tx_ring[entry].status);
+#endif
+
+ return;
+ }
+
+ /* Transmit timed out... */
+
+ printf("winbond-840 : transmission TIMEOUT : status %X\n",
+ (unsigned int) w840private.tx_ring[entry].status);
+
+ return;
+}
+
+/**************************************************************************
+w89c840_disable - Turn off ethernet interface
+***************************************************************************/
+static void w89c840_disable ( struct nic *nic ) {
+
+ w89c840_reset(nic);
+
+ /* Don't know what to do to disable the board. Is this needed at all? */
+ /* Yes, a live NIC can corrupt the loaded memory later [Ken] */
+ /* Stop the chip's Tx and Rx processes. */
+ writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig);
+}
+
+/**************************************************************************
+w89c840_irq - Enable, Disable, or Force interrupts
+***************************************************************************/
+static void w89c840_irq(struct nic *nic __unused, irq_action_t action __unused)
+{
+ switch ( action ) {
+ case DISABLE :
+ break;
+ case ENABLE :
+ break;
+ case FORCE :
+ break;
+ }
+}
+
+static struct nic_operations w89c840_operations = {
+ .connect = dummy_connect,
+ .poll = w89c840_poll,
+ .transmit = w89c840_transmit,
+ .irq = w89c840_irq,
+
+};
+
+static struct pci_device_id w89c840_nics[] = {
+PCI_ROM(0x1050, 0x0840, "winbond840", "Winbond W89C840F", 0),
+PCI_ROM(0x11f6, 0x2011, "compexrl100atx", "Compex RL100ATX", 0),
+};
+
+PCI_DRIVER ( w89c840_driver, w89c840_nics, PCI_NO_CLASS );
+
+/**************************************************************************
+w89c840_probe - Look for an adapter, this routine's visible to the outside
+***************************************************************************/
+static int w89c840_probe ( struct nic *nic, struct pci_device *p ) {
+
+
+ u16 sum = 0;
+ int i, j;
+ unsigned short value;
+
+ if (p->ioaddr == 0)
+ return 0;
+
+ nic->ioaddr = p->ioaddr;
+ nic->irqno = 0;
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr);
+#endif
+
+ ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
+
+#define PCI_DEVICE_ID_WINBOND2_89C840 0x0840
+#define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011
+
+ /* From Matt Hortman <mbhortman@acpthinclient.com> */
+ if (p->vendor == PCI_VENDOR_ID_WINBOND2
+ && p->device == PCI_DEVICE_ID_WINBOND2_89C840) {
+
+ /* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
+
+ } else if ( p->vendor == PCI_VENDOR_ID_COMPEX
+ && p->device == PCI_DEVICE_ID_COMPEX_RL100ATX) {
+
+ /* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
+
+ } else {
+ /* Gee, guess what? They missed again. */
+ printf("device ID : %X - is not a Compex RL100ATX NIC.\n",
+ p->device);
+ return 0;
+ }
+
+ printf(" %s\n", w89c840_version);
+
+ adjust_pci_device(p);
+
+ /* Ok. Got one. Read the eeprom. */
+ for (j = 0, i = 0; i < 0x40; i++) {
+ value = eeprom_read(ioaddr, i);
+ eeprom[i] = value;
+ sum += value;
+ }
+
+ for (i=0;i<ETH_ALEN;i++) {
+ nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
+ }
+
+ DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840: EEPROM checksum %hX, got eeprom", sum);
+#endif
+
+ /* Reset the chip to erase previous misconfiguration.
+ No hold time required! */
+ writel(0x00000001, ioaddr + PCIBusCfg);
+
+ if (driver_flags & CanHaveMII) {
+ int phy, phy_idx = 0;
+ for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+ int mii_status = mdio_read(ioaddr, phy, 1);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ w840private.phys[phy_idx++] = phy;
+ w840private.advertising = mdio_read(ioaddr, phy, 4);
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : MII PHY found at address %d, status "
+ "%X advertising %hX.\n", phy, mii_status, w840private.advertising);
+#endif
+
+ }
+ }
+
+ w840private.mii_cnt = phy_idx;
+
+ if (phy_idx == 0) {
+ printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
+ }
+ }
+
+ /* point to NIC specific routines */
+ nic->nic_op = &w89c840_operations;
+
+ w89c840_reset(nic);
+
+ return 1;
+}
+
+/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are
+ often serial bit streams generated by the host processor.
+ The example below is for the common 93c46 EEPROM, 64 16 bit words. */
+
+/* Delay between EEPROM clock transitions.
+ No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
+ a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
+ made udelay() unreliable.
+ The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
+ depricated.
+*/
+#define eeprom_delay(ee_addr) readl(ee_addr)
+
+enum EEPROM_Ctrl_Bits {
+ EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805,
+ EE_ChipSelect=0x801, EE_DataIn=0x08,
+};
+
+/* The EEPROM commands include the alway-set leading bit. */
+enum EEPROM_Cmds {
+ EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
+};
+
+static int eeprom_read(long addr, int location)
+{
+ int i;
+ int retval = 0;
+ int ee_addr = addr + EECtrl;
+ int read_cmd = location | EE_ReadCmd;
+ writel(EE_ChipSelect, ee_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 10; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
+ writel(dataval, ee_addr);
+ eeprom_delay(ee_addr);
+ writel(dataval | EE_ShiftClk, ee_addr);
+ eeprom_delay(ee_addr);
+ }
+ writel(EE_ChipSelect, ee_addr);
+
+ for (i = 16; i > 0; i--) {
+ writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
+ eeprom_delay(ee_addr);
+ retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);
+ writel(EE_ChipSelect, ee_addr);
+ eeprom_delay(ee_addr);
+ }
+
+ /* Terminate the EEPROM access. */
+ writel(0, ee_addr);
+ return retval;
+}
+
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details.
+
+ The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back 33Mhz PCI cycles. */
+#define mdio_delay(mdio_addr) readl(mdio_addr)
+
+/* Set iff a MII transceiver on any interface requires mdio preamble.
+ This only set with older tranceivers, so the extra
+ code size of a per-interface flag is not worthwhile. */
+static char mii_preamble_required = 1;
+
+#define MDIO_WRITE0 (MDIO_EnbOutput)
+#define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)
+
+/* Generate the preamble required for initial synchronization and
+ a few older transceivers. */
+static void mdio_sync(long mdio_addr)
+{
+ int bits = 32;
+
+ /* Establish sync by sending at least 32 logic ones. */
+ while (--bits >= 0) {
+ writel(MDIO_WRITE1, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+}
+
+static int mdio_read(int base_address, int phy_id, int location)
+{
+ long mdio_addr = base_address + MIICtrl;
+ int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int i, retval = 0;
+
+ if (mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+
+ writel(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 20; i > 0; i--) {
+ writel(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0);
+ writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return (retval>>1) & 0xffff;
+}
+
+#if 0
+static void mdio_write(int base_address, int phy_id, int location, int value)
+{
+ long mdio_addr = base_address + MIICtrl;
+ int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+ int i;
+
+ if (location == 4 && phy_id == w840private.phys[0])
+ w840private.advertising = value;
+
+ if (mii_preamble_required)
+ mdio_sync(mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+
+ writel(dataval, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(dataval | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ writel(MDIO_EnbIn, mdio_addr);
+ mdio_delay(mdio_addr);
+ writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+ mdio_delay(mdio_addr);
+ }
+ return;
+}
+#endif
+
+static void check_duplex(void)
+{
+ int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5);
+ int negotiated = mii_reg5 & w840private.advertising;
+ int duplex;
+
+ if (w840private.duplex_lock || mii_reg5 == 0xffff)
+ return;
+
+ duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
+ if (w840private.full_duplex != duplex) {
+ w840private.full_duplex = duplex;
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
+ duplex ? "full" : "half", w840private.phys[0], negotiated);
+#endif
+
+ w840private.csr6 &= ~0x200;
+ w840private.csr6 |= duplex ? 0x200 : 0;
+ }
+}
+
+static void set_rx_mode(void)
+{
+ u32 mc_filter[2]; /* Multicast hash filter */
+ u32 rx_mode;
+
+ /* Accept all multicasts from now on. */
+ memset(mc_filter, 0xff, sizeof(mc_filter));
+
+/*
+ * works OK with multicast enabled.
+ */
+
+ rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
+
+ writel(mc_filter[0], ioaddr + MulticastFilter0);
+ writel(mc_filter[1], ioaddr + MulticastFilter1);
+ w840private.csr6 &= ~0x00F8;
+ w840private.csr6 |= rx_mode;
+ writel(w840private.csr6, ioaddr + NetworkConfig);
+
+#if defined(W89C840_DEBUG)
+ printf("winbond-840 : Done setting RX mode.\n");
+#endif
+}
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void init_ring(void)
+{
+ int i;
+ char * p;
+
+ w840private.tx_full = 0;
+ w840private.tx_q_bytes = w840private.cur_rx = w840private.cur_tx = 0;
+ w840private.dirty_rx = w840private.dirty_tx = 0;
+
+ w840private.rx_buf_sz = PKT_BUF_SZ;
+ w840private.rx_head_desc = &w840private.rx_ring[0];
+
+ /* Initial all Rx descriptors. Fill in the Rx buffers. */
+
+ p = &w89c840_buf.rx_packet[0];
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ w840private.rx_ring[i].length = w840private.rx_buf_sz;
+ w840private.rx_ring[i].status = 0;
+ w840private.rx_ring[i].next_desc = virt_to_le32desc(&w840private.rx_ring[i+1]);
+
+ w840private.rx_ring[i].buffer1 = virt_to_le32desc(p + (PKT_BUF_SZ * i));
+ w840private.rx_ring[i].status = DescOwn | DescIntr;
+ }
+
+ /* Mark the last entry as wrapping the ring. */
+ w840private.rx_ring[i-1].length |= DescEndRing;
+ w840private.rx_ring[i-1].next_desc = virt_to_le32desc(&w840private.rx_ring[0]);
+
+ w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ w840private.tx_ring[i].status = 0;
+ }
+ return;
+}
+
+
+DRIVER ( "W89C840F", nic_driver, pci_driver, w89c840_driver,
+ w89c840_probe, w89c840_disable );
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/nvs/nvs.c b/debian/grub-extras/disabled/gpxe/src/drivers/nvs/nvs.c
new file mode 100644
index 0000000..7252808
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/nvs/nvs.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/nvs.h>
+
+/** @file
+ *
+ * Non-volatile storage
+ *
+ */
+
+/**
+ * Read from non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int nvs_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ size_t frag_len;
+ int rc;
+
+ /* We don't even attempt to handle buffer lengths that aren't
+ * an integral number of words.
+ */
+ assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
+
+ while ( len ) {
+
+ /* Calculate space remaining up to next block boundary */
+ frag_len = ( ( nvs->block_size -
+ ( address & ( nvs->block_size - 1 ) ) )
+ << nvs->word_len_log2 );
+
+ /* Limit to space remaining in buffer */
+ if ( frag_len > len )
+ frag_len = len;
+
+ /* Read this portion of the buffer from the device */
+ if ( ( rc = nvs->read ( nvs, address, data, frag_len ) ) != 0 )
+ return rc;
+
+ /* Update parameters */
+ data += frag_len;
+ address += ( frag_len >> nvs->word_len_log2 );
+ len -= frag_len;
+ }
+
+ return 0;
+}
+
+/**
+ * Verify content of non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data to compare against
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int nvs_verify ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ uint8_t read_data[len];
+ int rc;
+
+ /* Read data into temporary buffer */
+ if ( ( rc = nvs_read ( nvs, address, read_data, len ) ) != 0 )
+ return rc;
+
+ /* Compare data */
+ if ( memcmp ( data, read_data, len ) != 0 ) {
+ DBG ( "NVS %p verification failed at %#04x+%zd\n",
+ nvs, address, len );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Write to non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int nvs_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ size_t frag_len;
+ int rc;
+
+ /* We don't even attempt to handle buffer lengths that aren't
+ * an integral number of words.
+ */
+ assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
+
+ while ( len ) {
+
+ /* Calculate space remaining up to next block boundary */
+ frag_len = ( ( nvs->block_size -
+ ( address & ( nvs->block_size - 1 ) ) )
+ << nvs->word_len_log2 );
+
+ /* Limit to space remaining in buffer */
+ if ( frag_len > len )
+ frag_len = len;
+
+ /* Write this portion of the buffer to the device */
+ if ( ( rc = nvs->write ( nvs, address, data, frag_len ) ) != 0)
+ return rc;
+
+ /* Read back and verify data */
+ if ( ( rc = nvs_verify ( nvs, address, data, frag_len ) ) != 0)
+ return rc;
+
+ /* Update parameters */
+ data += frag_len;
+ address += ( frag_len >> nvs->word_len_log2 );
+ len -= frag_len;
+ }
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/nvs/spi.c b/debian/grub-extras/disabled/gpxe/src/drivers/nvs/spi.c
new file mode 100644
index 0000000..793080a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/nvs/spi.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <gpxe/spi.h>
+
+/** @file
+ *
+ * SPI devices
+ *
+ */
+
+/**
+ * Munge SPI device address into command
+ *
+ * @v command SPI command
+ * @v address Address
+ * @v munge_address Device requires address munging
+ * @ret command Actual SPI command to use
+ *
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3
+ * of the command byte as address bit A8, rather than having a
+ * two-byte address. This function takes care of generating the
+ * appropriate command.
+ */
+static inline unsigned int spi_command ( unsigned int command,
+ unsigned int address,
+ int munge_address ) {
+ return ( command | ( ( ( address >> 8 ) & munge_address ) << 3 ) );
+}
+
+/**
+ * Wait for SPI device to complete operation
+ *
+ * @v device SPI device
+ * @ret rc Return status code
+ */
+static int spi_wait ( struct spi_device *device ) {
+ struct spi_bus *bus = device->bus;
+ uint8_t status;
+ int i;
+ int rc;
+
+ for ( i = 0 ; i < 50 ; i++ ) {
+ udelay ( 20 );
+ if ( ( rc = bus->rw ( bus, device, SPI_RDSR, -1, NULL,
+ &status, sizeof ( status ) ) ) != 0 )
+ return rc;
+ if ( ! ( status & SPI_STATUS_NRDY ) )
+ return 0;
+ }
+ DBG ( "SPI %p timed out\n", device );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Read data from SPI device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int spi_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ unsigned int command = spi_command ( SPI_READ, address,
+ device->munge_address );
+ int rc;
+
+ DBG ( "SPI %p reading %zd bytes from %#04x\n", device, len, address );
+ if ( ( rc = bus->rw ( bus, device, command, address,
+ NULL, data, len ) ) != 0 ) {
+ DBG ( "SPI %p failed to read data from device\n", device );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Write data to SPI device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int spi_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ unsigned int command = spi_command ( SPI_WRITE, address,
+ device->munge_address );
+ int rc;
+
+ DBG ( "SPI %p writing %zd bytes to %#04x\n", device, len, address );
+
+ if ( ( rc = bus->rw ( bus, device, SPI_WREN, -1,
+ NULL, NULL, 0 ) ) != 0 ) {
+ DBG ( "SPI %p failed to write-enable device\n", device );
+ return rc;
+ }
+
+ if ( ( rc = bus->rw ( bus, device, command, address,
+ data, NULL, len ) ) != 0 ) {
+ DBG ( "SPI %p failed to write data to device\n", device );
+ return rc;
+ }
+
+ if ( ( rc = spi_wait ( device ) ) != 0 ) {
+ DBG ( "SPI %p failed to complete write operation\n", device );
+ return rc;
+ }
+
+ return 0;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/drivers/nvs/threewire.c b/debian/grub-extras/disabled/gpxe/src/drivers/nvs/threewire.c
new file mode 100644
index 0000000..8e52138
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/drivers/nvs/threewire.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <gpxe/threewire.h>
+
+/** @file
+ *
+ * Three-wire serial devices
+ *
+ */
+
+/**
+ * Read data from three-wire device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int threewire_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ int rc;
+
+ assert ( bus->mode == SPI_MODE_THREEWIRE );
+
+ DBGC ( device, "3wire %p reading %zd bytes at %04x\n",
+ device, len, address );
+
+ if ( ( rc = bus->rw ( bus, device, THREEWIRE_READ, address,
+ NULL, data, len ) ) != 0 ) {
+ DBGC ( device, "3wire %p could not read: %s\n",
+ device, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Write data to three-wire device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int threewire_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len ) {
+ struct spi_device *device = nvs_to_spi ( nvs );
+ struct spi_bus *bus = device->bus;
+ int rc;
+
+ assert ( bus->mode == SPI_MODE_THREEWIRE );
+
+ DBGC ( device, "3wire %p writing %zd bytes at %04x\n",
+ device, len, address );
+
+ /* Enable device for writing */
+ if ( ( rc = bus->rw ( bus, device, THREEWIRE_EWEN,
+ THREEWIRE_EWEN_ADDRESS, NULL, NULL, 0 ) ) != 0 ){
+ DBGC ( device, "3wire %p could not enable writing: %s\n",
+ device, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Write data */
+ if ( ( rc = bus->rw ( bus, device, THREEWIRE_WRITE, address,
+ data, NULL, len ) ) != 0 ) {
+ DBGC ( device, "3wire %p could not write: %s\n",
+ device, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Our model of an SPI bus doesn't provide a mechanism for
+ * "assert CS, wait for MISO to become high, so just wait for
+ * long enough to ensure that the write has completed.
+ */
+ mdelay ( THREEWIRE_WRITE_MDELAY );
+
+ return 0;
+}
+
+/**
+ * Autodetect device address length
+ *
+ * @v device SPI device
+ * @ret rc Return status code
+ */
+int threewire_detect_address_len ( struct spi_device *device ) {
+ struct nvs_device *nvs = &device->nvs;
+ int rc;
+
+ DBGC ( device, "3wire %p autodetecting address length\n", device );
+
+ device->address_len = SPI_AUTODETECT_ADDRESS_LEN;
+ if ( ( rc = threewire_read ( nvs, 0, NULL,
+ ( 1 << nvs->word_len_log2 ) ) ) != 0 ) {
+ DBGC ( device, "3wire %p could not autodetect address "
+ "length: %s\n", device, strerror ( rc ) );
+ return rc;
+ }
+
+ DBGC ( device, "3wire %p autodetected address length %d\n",
+ device, device->address_len );
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/hci/strerror.c b/debian/grub-extras/disabled/gpxe/src/hci/strerror.c
new file mode 100644
index 0000000..b608e18
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/hci/strerror.c
@@ -0,0 +1,123 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <gpxe/errortab.h>
+
+/** @file
+ *
+ * Error descriptions.
+ *
+ * The error numbers used by Etherboot are a superset of those defined
+ * by the PXE specification version 2.1. See errno.h for a listing of
+ * the error values.
+ *
+ * To save space in ROM images, error string tables are optional. Use
+ * the ERRORMSG_XXX options in config.h to select which error string
+ * tables you want to include. If an error string table is omitted,
+ * strerror() will simply return the text "Error 0x<errno>".
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Find error description
+ *
+ * @v errno Error number
+ * @v mask Mask of bits that we care about
+ * @ret errortab Error description, or NULL
+ */
+static struct errortab * find_error ( int errno, int mask ) {
+ struct errortab *errortab;
+
+ for_each_table_entry ( errortab, ERRORTAB ) {
+ if ( ( ( errortab->errno ^ errno ) & mask ) == 0 )
+ return errortab;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find closest error description
+ *
+ * @v errno Error number
+ * @ret errortab Error description, or NULL
+ *
+ *
+ */
+static struct errortab * find_closest_error ( int errno ) {
+ struct errortab *errortab;
+
+ /* First, look for an exact match */
+ if ( ( errortab = find_error ( errno, 0x7fffffff ) ) != NULL )
+ return errortab;
+
+ /* Second, try masking off the gPXE-specific bit and seeing if
+ * we have an entry for the generic POSIX error message.
+ */
+ if ( ( errortab = find_error ( errno, 0x4f0000ff ) ) != NULL )
+ return errortab;
+
+ return NULL;
+}
+
+/**
+ * Retrieve string representation of error number.
+ *
+ * @v errno/rc Error number or return status code
+ * @ret strerror Pointer to error text
+ *
+ * If the error is not found in the linked-in error tables, generates
+ * a generic "Error 0x<errno>" message.
+ *
+ * The pointer returned by strerror() is valid only until the next
+ * call to strerror().
+ *
+ */
+const char * strerror ( int errno ) {
+ static char errbuf[64];
+ struct errortab *errortab;
+
+ /* Allow for strerror(rc) as well as strerror(errno) */
+ if ( errno < 0 )
+ errno = -errno;
+
+ /* Find the error description, if one exists */
+ errortab = find_closest_error ( errno );
+
+ /* Construct the error message */
+ if ( errortab ) {
+ snprintf ( errbuf, sizeof ( errbuf ), "%s (#%08x)",
+ errortab->text, errno );
+ } else {
+ snprintf ( errbuf, sizeof ( errbuf ), "Error #%08x", errno );
+ }
+
+ return errbuf;
+}
+
+/* Do not include ERRFILE portion in the numbers in the error table */
+#undef ERRFILE
+#define ERRFILE 0
+
+/** The most common errors */
+struct errortab common_errors[] __errortab = {
+ { 0, "No error" },
+ { EACCES, "Permission denied" },
+ { ECANCELED, "Operation cancelled" },
+ { ECONNRESET, "Connection reset" },
+ { EINVAL, "Invalid argument" },
+ { EIO, "Input/output error" },
+ { ENETUNREACH, "Network unreachable" },
+ { ENODEV, "No such device" },
+ { ENOENT, "File not found" },
+ { ENOEXEC, "Not an executable image" },
+ { ENOMEM, "Out of memory" },
+ { ENOSPC, "No space left on device" },
+ { ENOTCONN, "Not connected" },
+ { ENOTSUP, "Not supported" },
+ { EPERM, "Operation not permitted" },
+ { ERANGE, "Out of range" },
+ { ETIMEDOUT, "Connection timed out" },
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/include/etherboot.h b/debian/grub-extras/disabled/gpxe/src/include/etherboot.h
new file mode 100644
index 0000000..ad44e8a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/etherboot.h
@@ -0,0 +1,44 @@
+#ifndef ETHERBOOT_H
+#define ETHERBOOT_H
+
+/*
+ * Standard includes that we always want
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <console.h>
+#include <gpxe/timer.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/if_ether.h>
+
+typedef unsigned long Address;
+
+/*
+ * IMPORTANT!!!!!!!!!!!!!!
+ *
+ * Everything below this point is cruft left over from older versions
+ * of Etherboot. Do not add *anything* below this point. Things are
+ * gradually being moved to individual header files.
+ *
+ */
+
+/* Link configuration time in tenths of a second */
+#ifndef VALID_LINK_TIMEOUT
+#define VALID_LINK_TIMEOUT 100 /* 10.0 seconds */
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
+#endif /* ETHERBOOT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/acpi.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/acpi.h
new file mode 100644
index 0000000..12edda9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/acpi.h
@@ -0,0 +1,43 @@
+#ifndef _GPXE_ACPI_H
+#define _GPXE_ACPI_H
+
+/** @file
+ *
+ * ACPI data structures
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * An ACPI description header
+ *
+ * This is the structure common to the start of all ACPI system
+ * description tables.
+ */
+struct acpi_description_header {
+ /** ACPI signature (4 ASCII characters) */
+ char signature[4];
+ /** Length of table, in bytes, including header */
+ uint32_t length;
+ /** ACPI Specification minor version number */
+ uint8_t revision;
+ /** To make sum of entire table == 0 */
+ uint8_t checksum;
+ /** OEM identification */
+ char oem_id[6];
+ /** OEM table identification */
+ char oem_table_id[8];
+ /** OEM revision number */
+ uint32_t oem_revision;
+ /** ASL compiler vendor ID */
+ char asl_compiler_id[4];
+ /** ASL compiler revision number */
+ uint32_t asl_compiler_revision;
+} __attribute__ (( packed ));
+
+extern void acpi_fix_checksum ( struct acpi_description_header *acpi );
+
+#endif /* _GPXE_ACPI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/aes.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/aes.h
new file mode 100644
index 0000000..bdc32bd
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/aes.h
@@ -0,0 +1,10 @@
+#ifndef _GPXE_AES_H
+#define _GPXE_AES_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct cipher_algorithm;
+
+extern struct cipher_algorithm aes_cbc_algorithm;
+
+#endif /* _GPXE_AES_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ansiesc.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ansiesc.h
new file mode 100644
index 0000000..85f7a9f
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ansiesc.h
@@ -0,0 +1,120 @@
+#ifndef _GPXE_ANSIESC_H
+#define _GPXE_ANSIESC_H
+
+/** @file
+ *
+ * ANSI escape sequences
+ *
+ * ANSI X3.64 (aka ECMA-48 or ISO/IEC 6429, available from
+ * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf)
+ * defines escape sequences consisting of:
+ *
+ * A Control Sequence Introducer (CSI)
+ *
+ * Zero or more Parameter Bytes (P)
+ *
+ * Zero or more Intermediate Bytes (I)
+ *
+ * A Final Byte (F)
+ *
+ * The CSI consists of ESC (0x1b) followed by "[" (0x5b). The
+ * Parameter Bytes, for a standardised (i.e. not private or
+ * experimental) sequence, consist of a list of ASCII decimal integers
+ * separated by semicolons. The Intermediate Bytes (in the range 0x20
+ * to 0x2f) and the Final Byte (in the range 0x40 to 0x4f) determine
+ * the control function.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A handler for an escape sequence */
+struct ansiesc_handler {
+ /** The control function identifier
+ *
+ * The control function identifier consists of the
+ * Intermediate Bytes (if any) and the Final Byte. In
+ * practice, no more than one immediate byte is ever used, so
+ * the byte combination can be efficiently expressed as a
+ * single integer, in the obvious way (with the Final Byte
+ * being the least significant byte).
+ */
+ unsigned int function;
+ /** Handle escape sequence
+ *
+ * @v count Parameter count
+ * @v params Parameter list
+ *
+ * A negative parameter value indicates that the parameter was
+ * omitted and that the default value for this control
+ * function should be used.
+ *
+ * Since all parameters are optional, there is no way to
+ * distinguish between "zero parameters" and "single parameter
+ * omitted". Consequently, the parameter list will always
+ * contain at least one item.
+ */
+ void ( * handle ) ( unsigned int count, int params[] );
+};
+
+/** Maximum number of parameters within a single escape sequence */
+#define ANSIESC_MAX_PARAMS 4
+
+/**
+ * ANSI escape sequence context
+ *
+ * This provides temporary storage for processing escape sequences,
+ * and points to the list of escape sequence handlers.
+ */
+struct ansiesc_context {
+ /** Array of handlers
+ *
+ * Must be terminated by a handler with @c function set to
+ * zero.
+ */
+ struct ansiesc_handler *handlers;
+ /** Parameter count
+ *
+ * Will be zero when not currently in an escape sequence.
+ */
+ unsigned int count;
+ /** Parameter list */
+ int params[ANSIESC_MAX_PARAMS];
+ /** Control function identifier */
+ unsigned int function;
+};
+
+/** Escape character */
+#define ESC 0x1b
+
+/** Control Sequence Introducer */
+#define CSI "\033["
+
+/**
+ * @defgroup ansifuncs ANSI escape sequence function identifiers
+ * @{
+ */
+
+/** Cursor position */
+#define ANSIESC_CUP 'H'
+
+/** Erase in page */
+#define ANSIESC_ED 'J'
+
+/** Erase from cursor to end of page */
+#define ANSIESC_ED_TO_END 0
+
+/** Erase from start of page to cursor */
+#define ANSIESC_ED_FROM_START 1
+
+/** Erase whole page */
+#define ANSIESC_ED_ALL 2
+
+/** Select graphic rendition */
+#define ANSIESC_SGR 'm'
+
+/** @} */
+
+extern int ansiesc_process ( struct ansiesc_context *ctx, int c );
+
+#endif /* _GPXE_ANSIESC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/aoe.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/aoe.h
new file mode 100644
index 0000000..6b42fd5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/aoe.h
@@ -0,0 +1,150 @@
+#ifndef _GPXE_AOE_H
+#define _GPXE_AOE_H
+
+/** @file
+ *
+ * AoE protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/list.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/retry.h>
+#include <gpxe/ata.h>
+
+/** An AoE config command */
+struct aoecfg {
+ /** AoE Queue depth */
+ uint16_t bufcnt;
+ /** ATA target firmware version */
+ uint16_t fwver;
+ /** ATA target sector count */
+ uint8_t scnt;
+ /** AoE config string subcommand */
+ uint8_t aoeccmd;
+ /** AoE config string length */
+ uint16_t cfglen;
+ /** AoE config string */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** An AoE ATA command */
+struct aoeata {
+ /** AoE command flags */
+ uint8_t aflags;
+ /** ATA error/feature register */
+ uint8_t err_feat;
+ /** ATA sector count register */
+ uint8_t count;
+ /** ATA command/status register */
+ uint8_t cmd_stat;
+ /** Logical block address, in little-endian order */
+ union {
+ uint64_t u64;
+ uint8_t bytes[6];
+ } lba;
+ /** Data payload */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+#define AOE_FL_EXTENDED 0x40 /**< LBA48 extended addressing */
+#define AOE_FL_DEV_HEAD 0x10 /**< Device/head flag */
+#define AOE_FL_ASYNC 0x02 /**< Asynchronous write */
+#define AOE_FL_WRITE 0x01 /**< Write command */
+
+/** An AoE command */
+union aoecmd {
+ /** Config command */
+ struct aoecfg cfg;
+ /** ATA command */
+ struct aoeata ata;
+};
+
+/** An AoE header */
+struct aoehdr {
+ /** Protocol version number and flags */
+ uint8_t ver_flags;
+ /** Error code */
+ uint8_t error;
+ /** Major device number, in network byte order */
+ uint16_t major;
+ /** Minor device number */
+ uint8_t minor;
+ /** Command number */
+ uint8_t command;
+ /** Tag, in network byte order */
+ uint32_t tag;
+ /** Payload */
+ union aoecmd cmd[0];
+} __attribute__ (( packed ));
+
+#define AOE_VERSION 0x10 /**< Version 1 */
+#define AOE_VERSION_MASK 0xf0 /**< Version part of ver_flags field */
+
+#define AOE_FL_RESPONSE 0x08 /**< Message is a response */
+#define AOE_FL_ERROR 0x04 /**< Command generated an error */
+
+#define AOE_MAJOR_BROADCAST 0xffff
+#define AOE_MINOR_BROADCAST 0xff
+
+#define AOE_CMD_ATA 0x00 /**< Issue ATA command */
+#define AOE_CMD_CONFIG 0x01 /**< Query Config Information */
+
+#define AOE_TAG_MAGIC 0xebeb0000
+
+#define AOE_ERR_BAD_COMMAND 1 /**< Unrecognised command code */
+#define AOE_ERR_BAD_PARAMETER 2 /**< Bad argument parameter */
+#define AOE_ERR_UNAVAILABLE 3 /**< Device unavailable */
+#define AOE_ERR_CONFIG_EXISTS 4 /**< Config string present */
+#define AOE_ERR_BAD_VERSION 5 /**< Unsupported version */
+
+/** An AoE session */
+struct aoe_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** List of all AoE sessions */
+ struct list_head list;
+
+ /** Network device */
+ struct net_device *netdev;
+
+ /** Major number */
+ uint16_t major;
+ /** Minor number */
+ uint8_t minor;
+ /** Target MAC address */
+ uint8_t target[ETH_ALEN];
+
+ /** Tag for current AoE command */
+ uint32_t tag;
+
+ /** Current AOE command */
+ uint8_t aoe_cmd_type;
+ /** Current ATA command */
+ struct ata_command *command;
+ /** Overall status of current ATA command */
+ unsigned int status;
+ /** Byte offset within command's data buffer */
+ unsigned int command_offset;
+ /** Return status code for command */
+ int rc;
+
+ /** Retransmission timer */
+ struct retry_timer timer;
+};
+
+#define AOE_STATUS_ERR_MASK 0x0f /**< Error portion of status code */
+#define AOE_STATUS_PENDING 0x80 /**< Command pending */
+
+/** Maximum number of sectors per packet */
+#define AOE_MAX_COUNT 2
+
+extern void aoe_detach ( struct ata_device *ata );
+extern int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
+ const char *root_path );
+
+#endif /* _GPXE_AOE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/api.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/api.h
new file mode 100644
index 0000000..ff2ba59
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/api.h
@@ -0,0 +1,84 @@
+#ifndef _GPXE_API_H
+#define _GPXE_API_H
+
+/** @file
+ *
+ * gPXE internal APIs
+ *
+ * There are various formally-defined APIs internal to gPXE, with
+ * several differing implementations specific to particular execution
+ * environments (e.g. PC BIOS, EFI, LinuxBIOS).
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @defgroup Single-implementation APIs
+ *
+ * These are APIs for which only a single implementation may be
+ * compiled in at any given time.
+ *
+ * @{
+ */
+
+/**
+ * Calculate function implementation name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ *
+ * The subsystem prefix should be an empty string for the currently
+ * selected subsystem, and should be a subsystem-unique string for all
+ * other subsystems.
+ */
+#define SINGLE_API_NAME( _prefix, _api_func ) _prefix ## _api_func
+
+/**
+ * Calculate static inline function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define SINGLE_API_INLINE( _prefix, _api_func ) \
+ SINGLE_API_NAME ( _prefix, _api_func )
+
+/**
+ * Provide an API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_SINGLE_API( _prefix, _api_func, _func ) \
+ /* Ensure that _api_func exists */ \
+ typeof ( _api_func ) _api_func; \
+ /* Ensure that _func exists */ \
+ typeof ( _func ) _func; \
+ /* Ensure that _func is type-compatible with _api_func */ \
+ typeof ( _api_func ) _func; \
+ /* Ensure that _subsys_func is non-static */ \
+ extern typeof ( _api_func ) SINGLE_API_NAME ( _prefix, _api_func ); \
+ /* Provide symbol alias from _subsys_func to _func */ \
+ typeof ( _api_func ) SINGLE_API_NAME ( _prefix, _api_func ) \
+ __attribute__ (( alias ( #_func ) ));
+
+/**
+ * Provide a static inline API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_SINGLE_API_INLINE( _prefix, _api_func ) \
+ /* Ensure that _api_func exists */ \
+ typeof ( _api_func ) _api_func; \
+ /* Ensure that _subsys_func exists and is static */ \
+ static typeof ( SINGLE_API_INLINE ( _prefix, _api_func ) ) \
+ SINGLE_API_INLINE ( _prefix, _api_func ); \
+ /* Ensure that _subsys_func is type-compatible with _api_func */ \
+ typeof ( _api_func ) SINGLE_API_INLINE ( _prefix, _api_func );
+
+/** @} */
+
+#endif /* _GPXE_API_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/arp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/arp.h
new file mode 100644
index 0000000..0623d35
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/arp.h
@@ -0,0 +1,46 @@
+#ifndef _GPXE_ARP_H
+#define _GPXE_ARP_H
+
+/** @file
+ *
+ * Address Resolution Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tables.h>
+
+struct net_device;
+struct net_protocol;
+
+/** A network-layer protocol that relies upon ARP */
+struct arp_net_protocol {
+ /** Network-layer protocol */
+ struct net_protocol *net_protocol;
+ /** Check existence of address
+ *
+ * @v netdev Network device
+ * @v net_addr Network-layer address
+ * @ret rc Return status code
+ */
+ int ( * check ) ( struct net_device *netdev,
+ const void *net_addr );
+};
+
+/** ARP protocol table */
+#define ARP_NET_PROTOCOLS \
+ __table ( struct arp_net_protocol, "arp_net_protocols" )
+
+/** Declare an ARP protocol */
+#define __arp_net_protocol __table_entry ( ARP_NET_PROTOCOLS, 01 )
+
+extern struct net_protocol arp_protocol;
+
+extern int arp_resolve ( struct net_device *netdev,
+ struct net_protocol *net_protocol,
+ const void *dest_net_addr,
+ const void *source_net_addr,
+ void *dest_ll_addr );
+
+#endif /* _GPXE_ARP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/asn1.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/asn1.h
new file mode 100644
index 0000000..477c209
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/asn1.h
@@ -0,0 +1,34 @@
+#ifndef _GPXE_ASN1_H
+#define _GPXE_ASN1_H
+
+/** @file
+ *
+ * ASN.1 encoding
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define ASN1_INTEGER 0x02
+#define ASN1_BIT_STRING 0x03
+#define ASN1_OCTET_STRING 0x04
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+#define ASN1_SEQUENCE 0x30
+#define ASN1_IP_ADDRESS 0x40
+#define ASN1_EXPLICIT_TAG 0xa0
+
+/**
+ * A DER-encoded ASN.1 object cursor
+ */
+struct asn1_cursor {
+ /** Start of data */
+ void *data;
+ /** Length of data */
+ size_t len;
+};
+
+extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
+extern int asn1_skip ( struct asn1_cursor *cursor, unsigned int type );
+
+#endif /* _GPXE_ASN1_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ata.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ata.h
new file mode 100644
index 0000000..3c56584
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ata.h
@@ -0,0 +1,209 @@
+#ifndef _GPXE_ATA_H
+#define _GPXE_ATA_H
+
+#include <stdint.h>
+#include <gpxe/blockdev.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
+
+/** @file
+ *
+ * ATA devices
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * An ATA Logical Block Address
+ *
+ * ATA controllers have three byte-wide registers for specifying the
+ * block address: LBA Low, LBA Mid and LBA High. This allows for a
+ * 24-bit address. Some devices support the "48-bit address feature
+ * set" (LBA48), in which case each of these byte-wide registers is
+ * actually a two-entry FIFO, and the "previous" byte pushed into the
+ * FIFO is used as the corresponding high-order byte. So, to set up
+ * the 48-bit address 0x123456abcdef, you would issue
+ *
+ * 0x56 -> LBA Low register
+ * 0xef -> LBA Low register
+ * 0x34 -> LBA Mid register
+ * 0xcd -> LBA Mid register
+ * 0x12 -> LBA High register
+ * 0xab -> LBA High register
+ *
+ * This structure encapsulates this information by providing a single
+ * 64-bit integer in native byte order, unioned with bytes named so
+ * that the sequence becomes
+ *
+ * low_prev -> LBA Low register
+ * low_cur -> LBA Low register
+ * mid_prev -> LBA Mid register
+ * mid_cur -> LBA Mid register
+ * high_prev -> LBA High register
+ * high_cur -> LBA High register
+ *
+ * Just to complicate matters further, in non-LBA48 mode it is
+ * possible to have a 28-bit address, in which case bits 27:24 must be
+ * written into the low four bits of the Device register.
+ */
+union ata_lba {
+ /** LBA as a 64-bit integer in native-endian order */
+ uint64_t native;
+ /** ATA registers */
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t low_cur;
+ uint8_t mid_cur;
+ uint8_t high_cur;
+ uint8_t low_prev;
+ uint8_t mid_prev;
+ uint8_t high_prev;
+ uint16_t pad;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint16_t pad;
+ uint8_t high_prev;
+ uint8_t mid_prev;
+ uint8_t low_prev;
+ uint8_t high_cur;
+ uint8_t mid_cur;
+ uint8_t low_cur;
+#else
+#error "I need a byte order"
+#endif
+ } bytes;
+};
+
+/** An ATA 2-byte FIFO register */
+union ata_fifo {
+ /** Value in native-endian order */
+ uint16_t native;
+ /** ATA registers */
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint8_t cur;
+ uint8_t prev;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint8_t prev;
+ uint8_t cur;
+#else
+#error "I need a byte order"
+#endif
+ } bytes;
+};
+
+/** ATA command block */
+struct ata_cb {
+ /** Logical block address */
+ union ata_lba lba;
+ /** Sector count */
+ union ata_fifo count;
+ /** Error/feature register */
+ union ata_fifo err_feat;
+ /** Device register */
+ uint8_t device;
+ /** Command/status register */
+ uint8_t cmd_stat;
+ /** LBA48 addressing flag */
+ int lba48;
+};
+
+/** Obsolete bits in the ATA device register */
+#define ATA_DEV_OBSOLETE 0xa0
+
+/** LBA flag in the ATA device register */
+#define ATA_DEV_LBA 0x40
+
+/** Slave ("device 1") flag in the ATA device register */
+#define ATA_DEV_SLAVE 0x10
+
+/** Master ("device 0") flag in the ATA device register */
+#define ATA_DEV_MASTER 0x00
+
+/** Mask of non-LBA portion of device register */
+#define ATA_DEV_MASK 0xf0
+
+/** "Read sectors" command */
+#define ATA_CMD_READ 0x20
+
+/** "Read sectors (ext)" command */
+#define ATA_CMD_READ_EXT 0x24
+
+/** "Write sectors" command */
+#define ATA_CMD_WRITE 0x30
+
+/** "Write sectors (ext)" command */
+#define ATA_CMD_WRITE_EXT 0x34
+
+/** "Identify" command */
+#define ATA_CMD_IDENTIFY 0xec
+
+/** An ATA command */
+struct ata_command {
+ /** ATA command block */
+ struct ata_cb cb;
+ /** Data-out buffer (may be NULL)
+ *
+ * If non-NULL, this buffer must be ata_command::cb::count
+ * sectors in size.
+ */
+ userptr_t data_out;
+ /** Data-in buffer (may be NULL)
+ *
+ * If non-NULL, this buffer must be ata_command::cb::count
+ * sectors in size.
+ */
+ userptr_t data_in;
+ /** Command status code */
+ int rc;
+};
+
+/**
+ * Structure returned by ATA IDENTIFY command
+ *
+ * This is a huge structure with many fields that we don't care about,
+ * so we implement only a few fields.
+ */
+struct ata_identity {
+ uint16_t ignore_a[60]; /* words 0-59 */
+ uint32_t lba_sectors; /* words 60-61 */
+ uint16_t ignore_b[21]; /* words 62-82 */
+ uint16_t supports_lba48; /* word 83 */
+ uint16_t ignore_c[16]; /* words 84-99 */
+ uint64_t lba48_sectors; /* words 100-103 */
+ uint16_t ignore_d[152]; /* words 104-255 */
+};
+
+/** Supports LBA48 flag */
+#define ATA_SUPPORTS_LBA48 ( 1 << 10 )
+
+/** ATA sector size */
+#define ATA_SECTOR_SIZE 512
+
+/** An ATA device */
+struct ata_device {
+ /** Block device interface */
+ struct block_device blockdev;
+ /** Device number
+ *
+ * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
+ */
+ int device;
+ /** LBA48 extended addressing */
+ int lba48;
+ /**
+ * Issue ATA command
+ *
+ * @v ata ATA device
+ * @v command ATA command
+ * @ret rc Return status code
+ */
+ int ( * command ) ( struct ata_device *ata,
+ struct ata_command *command );
+ /** Backing device */
+ struct refcnt *backend;
+};
+
+extern int init_atadev ( struct ata_device *ata );
+
+#endif /* _GPXE_ATA_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/base64.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/base64.h
new file mode 100644
index 0000000..e38bef0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/base64.h
@@ -0,0 +1,26 @@
+#ifndef _GPXE_BASE64_H
+#define _GPXE_BASE64_H
+
+/** @file
+ *
+ * Base64 encoding
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * Calculate length of base64-encoded string
+ *
+ * @v raw_len Raw string length (excluding NUL)
+ * @ret encoded_len Encoded string length (excluding NUL)
+ */
+static inline size_t base64_encoded_len ( size_t raw_len ) {
+ return ( ( ( raw_len + 3 - 1 ) / 3 ) * 4 );
+}
+
+extern void base64_encode ( const char *raw, char *encoded );
+
+#endif /* _GPXE_BASE64_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitbash.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitbash.h
new file mode 100644
index 0000000..f2ba9f7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitbash.h
@@ -0,0 +1,52 @@
+#ifndef _GPXE_BITBASH_H
+#define _GPXE_BITBASH_H
+
+/** @file
+ *
+ * Bit-bashing interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct bit_basher;
+
+/** Bit-bashing operations */
+struct bit_basher_operations {
+ /**
+ * Set/clear output bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @v data Value to write
+ *
+ * @c data will be 0 if a logic 0 should be written (i.e. the
+ * bit should be cleared), or -1UL if a logic 1 should be
+ * written (i.e. the bit should be set). This is done so that
+ * the method may simply binary-AND @c data with the
+ * appropriate bit mask.
+ */
+ void ( * write ) ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data );
+ /**
+ * Read input bit
+ *
+ * @v basher Bit-bashing interface
+ * @v bit_id Bit number
+ * @ret zero Input is a logic 0
+ * @ret non-zero Input is a logic 1
+ */
+ int ( * read ) ( struct bit_basher *basher, unsigned int bit_id );
+};
+
+/** A bit-bashing interface */
+struct bit_basher {
+ /** Bit-bashing operations */
+ struct bit_basher_operations *op;
+};
+
+extern void write_bit ( struct bit_basher *basher, unsigned int bit_id,
+ unsigned long data );
+extern int read_bit ( struct bit_basher *basher, unsigned int bit_id );
+
+#endif /* _GPXE_BITBASH_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitmap.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitmap.h
new file mode 100644
index 0000000..d6911a5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitmap.h
@@ -0,0 +1,85 @@
+#ifndef _GPXE_BITMAP_H
+#define _GPXE_BITMAP_H
+
+/** @file
+ *
+ * Bitmaps for multicast downloads
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/** A single block of bits within a bitmap */
+typedef unsigned long bitmap_block_t;
+
+/** Size of a block of bits (in bits) */
+#define BITMAP_BLKSIZE ( sizeof ( bitmap_block_t ) * 8 )
+
+/**
+ * Block index within bitmap
+ *
+ * @v bit Bit index
+ * @ret index Block index
+ */
+#define BITMAP_INDEX( bit ) ( (bit) / BITMAP_BLKSIZE )
+
+/**
+ * Block mask within bitmap
+ *
+ * @v bit Bit index
+ * @ret mask Block mask
+ */
+#define BITMAP_MASK( bit ) ( 1 << ( (bit) % BITMAP_BLKSIZE ) )
+
+/** A bitmap */
+struct bitmap {
+ /** Bitmap data */
+ bitmap_block_t *blocks;
+ /** Length of the bitmap, in bits */
+ unsigned int length;
+ /** Index of first gap in the bitmap */
+ unsigned int first_gap;
+};
+
+extern int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length );
+extern int bitmap_test ( struct bitmap *bitmap, unsigned int bit );
+extern void bitmap_set ( struct bitmap *bitmap, unsigned int bit );
+
+/**
+ * Free bitmap resources
+ *
+ * @v bitmap Bitmap
+ */
+static inline void bitmap_free ( struct bitmap *bitmap ) {
+ free ( bitmap->blocks );
+}
+
+/**
+ * Get first gap within bitmap
+ *
+ * @v bitmap Bitmap
+ * @ret first_gap First gap
+ *
+ * The first gap is the first unset bit within the bitmap.
+ */
+static inline unsigned int bitmap_first_gap ( struct bitmap *bitmap ) {
+ return bitmap->first_gap;
+}
+
+/**
+ * Check to see if bitmap is full
+ *
+ * @v bitmap Bitmap
+ * @ret is_full Bitmap is full
+ *
+ * The bitmap is full if it has no gaps (i.e. no unset bits).
+ */
+static inline int bitmap_full ( struct bitmap *bitmap ) {
+ return ( bitmap->first_gap == bitmap->length );
+}
+
+#endif /* _GPXE_BITMAP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitops.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitops.h
new file mode 100644
index 0000000..8db3431
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/bitops.h
@@ -0,0 +1,230 @@
+#ifndef _GPXE_BITOPS_H
+#define _GPXE_BITOPS_H
+
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Bit operations
+ *
+ */
+
+#include <stdint.h>
+#include <byteswap.h>
+
+/* Endianness selection.
+ *
+ * This is a property of the NIC, not a property of the host CPU.
+ */
+#ifdef BITOPS_LITTLE_ENDIAN
+#define cpu_to_BIT64 cpu_to_le64
+#define cpu_to_BIT32 cpu_to_le32
+#define BIT64_to_cpu le64_to_cpu
+#define BIT32_to_cpu le32_to_cpu
+#endif
+#ifdef BITOPS_BIG_ENDIAN
+#define cpu_to_BIT64 cpu_to_be64
+#define cpu_to_BIT32 cpu_to_be32
+#define BIT64_to_cpu be64_to_cpu
+#define BIT32_to_cpu be32_to_cpu
+#endif
+
+/** Datatype used to represent a bit in the pseudo-structures */
+typedef unsigned char pseudo_bit_t;
+
+/**
+ * Wrapper structure for pseudo_bit_t structures
+ *
+ * This structure provides a wrapper around pseudo_bit_t structures.
+ * It has the correct size, and also encapsulates type information
+ * about the underlying pseudo_bit_t-based structure, which allows the
+ * BIT_FILL() etc. macros to work without requiring explicit type
+ * information.
+ */
+#define PSEUDO_BIT_STRUCT( _structure ) \
+ union { \
+ uint8_t bytes[ sizeof ( _structure ) / 8 ]; \
+ uint32_t dwords[ sizeof ( _structure ) / 32 ]; \
+ uint64_t qwords[ sizeof ( _structure ) / 64 ]; \
+ _structure *dummy[0]; \
+ } u
+
+/** Get pseudo_bit_t structure type from wrapper structure pointer */
+#define PSEUDO_BIT_STRUCT_TYPE( _ptr ) \
+ typeof ( *((_ptr)->u.dummy[0]) )
+
+/** Bit offset of a field within a pseudo_bit_t structure */
+#define BIT_OFFSET( _ptr, _field ) \
+ offsetof ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ), _field )
+
+/** Bit width of a field within a pseudo_bit_t structure */
+#define BIT_WIDTH( _ptr, _field ) \
+ sizeof ( ( ( PSEUDO_BIT_STRUCT_TYPE ( _ptr ) * ) NULL )->_field )
+
+/** Qword offset of a field within a pseudo_bit_t structure */
+#define QWORD_OFFSET( _ptr, _field ) \
+ ( BIT_OFFSET ( _ptr, _field ) / 64 )
+
+/** Qword bit offset of a field within a pseudo_bit_t structure */
+#define QWORD_BIT_OFFSET( _ptr, _index, _field ) \
+ ( BIT_OFFSET ( _ptr, _field ) - ( 64 * (_index) ) )
+
+/** Bit mask for a field within a pseudo_bit_t structure */
+#define BIT_MASK( _ptr, _field ) \
+ ( ( ~( ( uint64_t ) 0 ) ) >> \
+ ( 64 - BIT_WIDTH ( _ptr, _field ) ) )
+
+/*
+ * Assemble native-endian qword from named fields and values
+ *
+ */
+
+#define BIT_ASSEMBLE_1( _ptr, _index, _field, _value ) \
+ ( ( ( uint64_t) (_value) ) << \
+ QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
+
+#define BIT_ASSEMBLE_2( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_3( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_4( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_5( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_6( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_ASSEMBLE_7( _ptr, _index, _field, _value, ... ) \
+ ( BIT_ASSEMBLE_1 ( _ptr, _index, _field, _value ) | \
+ BIT_ASSEMBLE_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+/*
+ * Build native-endian (positive) qword bitmasks from named fields
+ *
+ */
+
+#define BIT_MASK_1( _ptr, _index, _field ) \
+ ( BIT_MASK ( _ptr, _field ) << \
+ QWORD_BIT_OFFSET ( _ptr, _index, _field ) )
+
+#define BIT_MASK_2( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_1 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_3( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_2 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_4( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_3 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_5( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_4 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_6( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_5 ( _ptr, _index, __VA_ARGS__ ) )
+
+#define BIT_MASK_7( _ptr, _index, _field, ... ) \
+ ( BIT_MASK_1 ( _ptr, _index, _field ) | \
+ BIT_MASK_6 ( _ptr, _index, __VA_ARGS__ ) )
+
+/*
+ * Populate little-endian qwords from named fields and values
+ *
+ */
+
+#define BIT_FILL( _ptr, _index, _assembled ) do { \
+ uint64_t *__ptr = &(_ptr)->u.qwords[(_index)]; \
+ uint64_t __assembled = (_assembled); \
+ *__ptr = cpu_to_BIT64 ( __assembled ); \
+ } while ( 0 )
+
+#define BIT_FILL_1( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_1 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_2( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_2 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_3( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_3 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_4( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_4 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_5( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_5 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+#define BIT_FILL_6( _ptr, _field1, ... ) \
+ BIT_FILL ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ BIT_ASSEMBLE_6 ( _ptr, QWORD_OFFSET ( _ptr, _field1 ), \
+ _field1, __VA_ARGS__ ) )
+
+/** Extract value of named field */
+#define BIT_GET64( _ptr, _field ) \
+ ( { \
+ unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
+ uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
+ uint64_t __value = BIT64_to_cpu ( *__ptr ); \
+ __value >>= \
+ QWORD_BIT_OFFSET ( _ptr, __index, _field ); \
+ __value &= BIT_MASK ( _ptr, _field ); \
+ __value; \
+ } )
+
+/** Extract value of named field (for fields up to the size of a long) */
+#define BIT_GET( _ptr, _field ) \
+ ( ( unsigned long ) BIT_GET64 ( _ptr, _field ) )
+
+#define BIT_SET( _ptr, _field, _value ) do { \
+ unsigned int __index = QWORD_OFFSET ( _ptr, _field ); \
+ uint64_t *__ptr = &(_ptr)->u.qwords[__index]; \
+ unsigned int __shift = \
+ QWORD_BIT_OFFSET ( _ptr, __index, _field ); \
+ uint64_t __value = (_value); \
+ *__ptr &= cpu_to_BIT64 ( ~( BIT_MASK ( _ptr, _field ) << \
+ __shift ) ); \
+ *__ptr |= cpu_to_BIT64 ( __value << __shift ); \
+ } while ( 0 )
+
+#endif /* _GPXE_BITOPS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/blockdev.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/blockdev.h
new file mode 100644
index 0000000..cf28524
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/blockdev.h
@@ -0,0 +1,53 @@
+#ifndef _GPXE_BLOCKDEV_H
+#define _GPXE_BLOCKDEV_H
+
+/**
+ * @file
+ *
+ * Block devices
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/uaccess.h>
+
+struct block_device;
+
+/** Block device operations */
+struct block_device_operations {
+ /**
+ * Read block
+ *
+ * @v blockdev Block device
+ * @v block Block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+ int ( * read ) ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer );
+ /**
+ * Write block
+ *
+ * @v blockdev Block device
+ * @v block Block number
+ * @v count Block count
+ * @v buffer Data buffer
+ * @ret rc Return status code
+ */
+ int ( * write ) ( struct block_device *blockdev, uint64_t block,
+ unsigned long count, userptr_t buffer );
+};
+
+/** A block device */
+struct block_device {
+ /** Block device operations */
+ struct block_device_operations *op;
+ /** Block size */
+ size_t blksize;
+ /** Total number of blocks */
+ uint64_t blocks;
+};
+
+#endif /* _GPXE_BLOCKDEV_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/cbc.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/cbc.h
new file mode 100644
index 0000000..1262f1d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/cbc.h
@@ -0,0 +1,100 @@
+#ifndef _GPXE_CBC_H
+#define _GPXE_CBC_H
+
+/** @file
+ *
+ * Cipher-block chaining
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crypto.h>
+
+/**
+ * Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ * @ret rc Return status code
+ */
+static inline int cbc_setkey ( void *ctx, const void *key, size_t keylen,
+ struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx __unused ) {
+
+ return cipher_setkey ( raw_cipher, ctx, key, keylen );
+}
+
+/**
+ * Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ */
+static inline void cbc_setiv ( void *ctx __unused, const void *iv,
+ struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx ) {
+ memcpy ( cbc_ctx, iv, raw_cipher->blocksize );
+}
+
+extern void cbc_encrypt ( void *ctx, const void *src, void *dst,
+ size_t len, struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx );
+extern void cbc_decrypt ( void *ctx, const void *src, void *dst,
+ size_t len, struct cipher_algorithm *raw_cipher,
+ void *cbc_ctx );
+
+/**
+ * Create a cipher-block chaining mode of behaviour of an existing cipher
+ *
+ * @v _cbc_name Name for the new CBC cipher
+ * @v _cbc_cipher New cipher algorithm
+ * @v _raw_cipher Underlying cipher algorithm
+ * @v _raw_context Context structure for the underlying cipher
+ * @v _blocksize Cipher block size
+ */
+#define CBC_CIPHER( _cbc_name, _cbc_cipher, _raw_cipher, _raw_context, \
+ _blocksize ) \
+struct _cbc_name ## _context { \
+ _raw_context raw_ctx; \
+ uint8_t cbc_ctx[_blocksize]; \
+}; \
+static int _cbc_name ## _setkey ( void *ctx, const void *key, \
+ size_t keylen ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ return cbc_setkey ( &_cbc_name ## _ctx->raw_ctx, key, keylen, \
+ &_raw_cipher, &_cbc_name ## _ctx->cbc_ctx );\
+} \
+static void _cbc_name ## _setiv ( void *ctx, const void *iv ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, \
+ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
+} \
+static void _cbc_name ## _encrypt ( void *ctx, const void *src, \
+ void *dst, size_t len ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ cbc_encrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
+ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
+} \
+static void _cbc_name ## _decrypt ( void *ctx, const void *src, \
+ void *dst, size_t len ) { \
+ struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
+ cbc_decrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
+ &_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
+} \
+struct cipher_algorithm _cbc_cipher = { \
+ .name = #_cbc_name, \
+ .ctxsize = sizeof ( struct _cbc_name ## _context ), \
+ .blocksize = _blocksize, \
+ .setkey = _cbc_name ## _setkey, \
+ .setiv = _cbc_name ## _setiv, \
+ .encrypt = _cbc_name ## _encrypt, \
+ .decrypt = _cbc_name ## _decrypt, \
+};
+
+#endif /* _GPXE_CBC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/chap.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/chap.h
new file mode 100644
index 0000000..e86ede3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/chap.h
@@ -0,0 +1,53 @@
+#ifndef _GPXE_CHAP_H
+#define _GPXE_CHAP_H
+
+/** @file
+ *
+ * CHAP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/md5.h>
+
+struct digest_algorithm;
+
+/** A CHAP response */
+struct chap_response {
+ /** Digest algorithm used for the response */
+ struct digest_algorithm *digest;
+ /** Context used by the digest algorithm */
+ uint8_t *digest_context;
+ /** CHAP response */
+ uint8_t *response;
+ /** Length of CHAP response */
+ size_t response_len;
+};
+
+extern int chap_init ( struct chap_response *chap,
+ struct digest_algorithm *digest );
+extern void chap_update ( struct chap_response *chap, const void *data,
+ size_t len );
+extern void chap_respond ( struct chap_response *chap );
+extern void chap_finish ( struct chap_response *chap );
+
+/**
+ * Add identifier data to the CHAP challenge
+ *
+ * @v chap CHAP response
+ * @v identifier CHAP identifier
+ *
+ * The CHAP identifier is the first byte of the CHAP challenge. This
+ * function is a notational convenience for calling chap_update() for
+ * the identifier byte.
+ */
+static inline void chap_set_identifier ( struct chap_response *chap,
+ unsigned int identifier ) {
+ uint8_t ident_byte = identifier;
+
+ chap_update ( chap, &ident_byte, sizeof ( ident_byte ) );
+}
+
+#endif /* _GPXE_CHAP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/command.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/command.h
new file mode 100644
index 0000000..51ca6d6
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/command.h
@@ -0,0 +1,26 @@
+#ifndef _GPXE_COMMAND_H
+#define _GPXE_COMMAND_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tables.h>
+
+/** A command-line command */
+struct command {
+ /** Name of the command */
+ const char *name;
+ /**
+ * Function implementing the command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+ int ( * exec ) ( int argc, char **argv );
+};
+
+#define COMMANDS __table ( struct command, "commands" )
+
+#define __command __table_entry ( COMMANDS, 01 )
+
+#endif /* _GPXE_COMMAND_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/cpio.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/cpio.h
new file mode 100644
index 0000000..f462cec
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/cpio.h
@@ -0,0 +1,53 @@
+#ifndef _GPXE_CPIO_H
+#define _GPXE_CPIO_H
+
+/** @file
+ *
+ * CPIO archives
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A CPIO archive header
+ *
+ * All field are hexadecimal ASCII numbers padded with '0' on the
+ * left to the full width of the field.
+ */
+struct cpio_header {
+ /** The string "070701" or "070702" */
+ char c_magic[6];
+ /** File inode number */
+ char c_ino[8];
+ /** File mode and permissions */
+ char c_mode[8];
+ /** File uid */
+ char c_uid[8];
+ /** File gid */
+ char c_gid[8];
+ /** Number of links */
+ char c_nlink[8];
+ /** Modification time */
+ char c_mtime[8];
+ /** Size of data field */
+ char c_filesize[8];
+ /** Major part of file device number */
+ char c_maj[8];
+ /** Minor part of file device number */
+ char c_min[8];
+ /** Major part of device node reference */
+ char c_rmaj[8];
+ /** Minor part of device node reference */
+ char c_rmin[8];
+ /** Length of filename, including final NUL */
+ char c_namesize[8];
+ /** Checksum of data field if c_magic is 070702, othersize zero */
+ char c_chksum[8];
+} __attribute__ (( packed ));
+
+/** CPIO magic */
+#define CPIO_MAGIC "070701"
+
+extern void cpio_set_field ( char *field, unsigned long value );
+
+#endif /* _GPXE_CPIO_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/crypto.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/crypto.h
new file mode 100644
index 0000000..3831b79
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/crypto.h
@@ -0,0 +1,154 @@
+#ifndef _GPXE_CRYPTO_H
+#define _GPXE_CRYPTO_H
+
+/** @file
+ *
+ * Cryptographic API
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** A message digest algorithm */
+struct digest_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+ /** Block size */
+ size_t blocksize;
+ /** Digest size */
+ size_t digestsize;
+ /** Initialise digest
+ *
+ * @v ctx Context
+ */
+ void ( * init ) ( void *ctx );
+ /** Update digest with new data
+ *
+ * @v ctx Context
+ * @v src Data to digest
+ * @v len Length of data
+ *
+ * @v len is not necessarily a multiple of @c blocksize.
+ */
+ void ( * update ) ( void *ctx, const void *src, size_t len );
+ /** Finalise digest
+ *
+ * @v ctx Context
+ * @v out Buffer for digest output
+ */
+ void ( * final ) ( void *ctx, void *out );
+};
+
+/** A cipher algorithm */
+struct cipher_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+ /** Block size */
+ size_t blocksize;
+ /** Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @ret rc Return status code
+ */
+ int ( * setkey ) ( void *ctx, const void *key, size_t keylen );
+ /** Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ */
+ void ( * setiv ) ( void *ctx, const void *iv );
+ /** Encrypt data
+ *
+ * @v ctx Context
+ * @v src Data to encrypt
+ * @v dst Buffer for encrypted data
+ * @v len Length of data
+ *
+ * @v len is guaranteed to be a multiple of @c blocksize.
+ */
+ void ( * encrypt ) ( void *ctx, const void *src, void *dst,
+ size_t len );
+ /** Decrypt data
+ *
+ * @v ctx Context
+ * @v src Data to decrypt
+ * @v dst Buffer for decrypted data
+ * @v len Length of data
+ *
+ * @v len is guaranteed to be a multiple of @c blocksize.
+ */
+ void ( * decrypt ) ( void *ctx, const void *src, void *dst,
+ size_t len );
+};
+
+/** A public key algorithm */
+struct pubkey_algorithm {
+ /** Algorithm name */
+ const char *name;
+ /** Context size */
+ size_t ctxsize;
+};
+
+static inline void digest_init ( struct digest_algorithm *digest,
+ void *ctx ) {
+ digest->init ( ctx );
+}
+
+static inline void digest_update ( struct digest_algorithm *digest,
+ void *ctx, const void *data, size_t len ) {
+ digest->update ( ctx, data, len );
+}
+
+static inline void digest_final ( struct digest_algorithm *digest,
+ void *ctx, void *out ) {
+ digest->final ( ctx, out );
+}
+
+static inline int cipher_setkey ( struct cipher_algorithm *cipher,
+ void *ctx, const void *key, size_t keylen ) {
+ return cipher->setkey ( ctx, key, keylen );
+}
+
+static inline void cipher_setiv ( struct cipher_algorithm *cipher,
+ void *ctx, const void *iv ) {
+ cipher->setiv ( ctx, iv );
+}
+
+static inline void cipher_encrypt ( struct cipher_algorithm *cipher,
+ void *ctx, const void *src, void *dst,
+ size_t len ) {
+ cipher->encrypt ( ctx, src, dst, len );
+}
+#define cipher_encrypt( cipher, ctx, src, dst, len ) do { \
+ assert ( ( len & ( (cipher)->blocksize - 1 ) ) == 0 ); \
+ cipher_encrypt ( (cipher), (ctx), (src), (dst), (len) ); \
+ } while ( 0 )
+
+static inline void cipher_decrypt ( struct cipher_algorithm *cipher,
+ void *ctx, const void *src, void *dst,
+ size_t len ) {
+ cipher->decrypt ( ctx, src, dst, len );
+}
+#define cipher_decrypt( cipher, ctx, src, dst, len ) do { \
+ assert ( ( len & ( (cipher)->blocksize - 1 ) ) == 0 ); \
+ cipher_decrypt ( (cipher), (ctx), (src), (dst), (len) ); \
+ } while ( 0 )
+
+static inline int is_stream_cipher ( struct cipher_algorithm *cipher ) {
+ return ( cipher->blocksize == 1 );
+}
+
+extern struct digest_algorithm digest_null;
+extern struct cipher_algorithm cipher_null;
+extern struct pubkey_algorithm pubkey_null;
+
+#endif /* _GPXE_CRYPTO_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcp.h
new file mode 100644
index 0000000..2d9f885
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcp.h
@@ -0,0 +1,618 @@
+#ifndef _GPXE_DHCP_H
+#define _GPXE_DHCP_H
+
+/** @file
+ *
+ * Dynamic Host Configuration Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/in.h>
+#include <gpxe/list.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/tables.h>
+#include <gpxe/uuid.h>
+#include <gpxe/netdevice.h>
+
+struct job_interface;
+struct dhcp_options;
+struct dhcp_packet;
+
+/** BOOTP/DHCP server port */
+#define BOOTPS_PORT 67
+
+/** BOOTP/DHCP client port */
+#define BOOTPC_PORT 68
+
+/** PXE server port */
+#define PXE_PORT 4011
+
+/** Construct a tag value for an encapsulated option
+ *
+ * This tag value can be passed to Etherboot functions when searching
+ * for DHCP options in order to search for a tag within an
+ * encapsulated options block.
+ */
+#define DHCP_ENCAP_OPT( encapsulator, encapsulated ) \
+ ( ( (encapsulator) << 8 ) | (encapsulated) )
+/** Extract encapsulating option block tag from encapsulated tag value */
+#define DHCP_ENCAPSULATOR( encap_opt ) ( (encap_opt) >> 8 )
+/** Extract encapsulated option tag from encapsulated tag value */
+#define DHCP_ENCAPSULATED( encap_opt ) ( (encap_opt) & 0xff )
+/** Option is encapsulated */
+#define DHCP_IS_ENCAP_OPT( opt ) DHCP_ENCAPSULATOR( opt )
+
+/**
+ * @defgroup dhcpopts DHCP option tags
+ * @{
+ */
+
+/** Padding
+ *
+ * This tag does not have a length field; it is always only a single
+ * byte in length.
+ */
+#define DHCP_PAD 0
+
+/** Minimum normal DHCP option */
+#define DHCP_MIN_OPTION 1
+
+/** Subnet mask */
+#define DHCP_SUBNET_MASK 1
+
+/** Routers */
+#define DHCP_ROUTERS 3
+
+/** DNS servers */
+#define DHCP_DNS_SERVERS 6
+
+/** Syslog servers */
+#define DHCP_LOG_SERVERS 7
+
+/** Host name */
+#define DHCP_HOST_NAME 12
+
+/** Domain name */
+#define DHCP_DOMAIN_NAME 15
+
+/** Root path */
+#define DHCP_ROOT_PATH 17
+
+/** Vendor encapsulated options */
+#define DHCP_VENDOR_ENCAP 43
+
+/** PXE boot server discovery control */
+#define DHCP_PXE_DISCOVERY_CONTROL DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 6 )
+
+/** PXE boot server discovery control bits */
+enum dhcp_pxe_discovery_control {
+ /** Inhibit broadcast discovery */
+ PXEBS_NO_BROADCAST = 1,
+ /** Inhibit multicast discovery */
+ PXEBS_NO_MULTICAST = 2,
+ /** Accept only servers in DHCP_PXE_BOOT_SERVERS list */
+ PXEBS_NO_UNKNOWN_SERVERS = 4,
+ /** Skip discovery if filename present */
+ PXEBS_SKIP = 8,
+};
+
+/** PXE boot server multicast address */
+#define DHCP_PXE_BOOT_SERVER_MCAST DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 7 )
+
+/** PXE boot servers */
+#define DHCP_PXE_BOOT_SERVERS DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 8 )
+
+/** PXE boot server */
+struct dhcp_pxe_boot_server {
+ /** "Type" */
+ uint16_t type;
+ /** Number of IPv4 addresses */
+ uint8_t num_ip;
+ /** IPv4 addresses */
+ struct in_addr ip[0];
+} __attribute__ (( packed ));
+
+/** PXE boot menu */
+#define DHCP_PXE_BOOT_MENU DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 9 )
+
+/** PXE boot menu */
+struct dhcp_pxe_boot_menu {
+ /** "Type" */
+ uint16_t type;
+ /** Description length */
+ uint8_t desc_len;
+ /** Description */
+ char desc[0];
+} __attribute__ (( packed ));
+
+/** PXE boot menu prompt */
+#define DHCP_PXE_BOOT_MENU_PROMPT DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 10 )
+
+/** PXE boot menu prompt */
+struct dhcp_pxe_boot_menu_prompt {
+ /** Timeout
+ *
+ * A value of 0 means "time out immediately and select first
+ * boot item, without displaying the prompt". A value of 255
+ * means "display menu immediately with no timeout". Any
+ * other value means "display prompt, wait this many seconds
+ * for keypress, if key is F8, display menu, otherwise select
+ * first boot item".
+ */
+ uint8_t timeout;
+ /** Prompt to press F8 */
+ char prompt[0];
+} __attribute__ (( packed ));
+
+/** PXE boot menu item */
+#define DHCP_PXE_BOOT_MENU_ITEM DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 71 )
+
+/** PXE boot menu item */
+struct dhcp_pxe_boot_menu_item {
+ /** "Type"
+ *
+ * This field actually identifies the specific boot server (or
+ * cluster of boot servers offering identical boot files).
+ */
+ uint16_t type;
+ /** "Layer"
+ *
+ * Just don't ask.
+ */
+ uint16_t layer;
+} __attribute__ (( packed ));
+
+/** Requested IP address */
+#define DHCP_REQUESTED_ADDRESS 50
+
+/** Lease time */
+#define DHCP_LEASE_TIME 51
+
+/** Option overloading
+ *
+ * The value of this option is the bitwise-OR of zero or more
+ * DHCP_OPTION_OVERLOAD_XXX constants.
+ */
+#define DHCP_OPTION_OVERLOAD 52
+
+/** The "file" field is overloaded to contain extra DHCP options */
+#define DHCP_OPTION_OVERLOAD_FILE 1
+
+/** The "sname" field is overloaded to contain extra DHCP options */
+#define DHCP_OPTION_OVERLOAD_SNAME 2
+
+/** DHCP message type */
+#define DHCP_MESSAGE_TYPE 53
+#define DHCPNONE 0
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/** DHCP server identifier */
+#define DHCP_SERVER_IDENTIFIER 54
+
+/** Parameter request list */
+#define DHCP_PARAMETER_REQUEST_LIST 55
+
+/** Maximum DHCP message size */
+#define DHCP_MAX_MESSAGE_SIZE 57
+
+/** Vendor class identifier */
+#define DHCP_VENDOR_CLASS_ID 60
+
+/** Client identifier */
+#define DHCP_CLIENT_ID 61
+
+/** Client identifier */
+struct dhcp_client_id {
+ /** Link-layer protocol */
+ uint8_t ll_proto;
+ /** Link-layer address */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+} __attribute__ (( packed ));
+
+/** TFTP server name
+ *
+ * This option replaces the fixed "sname" field, when that field is
+ * used to contain overloaded options.
+ */
+#define DHCP_TFTP_SERVER_NAME 66
+
+/** Bootfile name
+ *
+ * This option replaces the fixed "file" field, when that field is
+ * used to contain overloaded options.
+ */
+#define DHCP_BOOTFILE_NAME 67
+
+/** User class identifier */
+#define DHCP_USER_CLASS_ID 77
+
+/** Client system architecture */
+#define DHCP_CLIENT_ARCHITECTURE 93
+
+/** Client network device interface */
+#define DHCP_CLIENT_NDI 94
+
+/** UUID client identifier */
+#define DHCP_CLIENT_UUID 97
+
+/** UUID client identifier */
+struct dhcp_client_uuid {
+ /** Identifier type */
+ uint8_t type;
+ /** UUID */
+ union uuid uuid;
+} __attribute__ (( packed ));
+
+#define DHCP_CLIENT_UUID_TYPE 0
+
+/** Etherboot-specific encapsulated options
+ *
+ * This encapsulated options field is used to contain all options
+ * specific to Etherboot (i.e. not assigned by IANA or other standards
+ * bodies).
+ */
+#define DHCP_EB_ENCAP 175
+
+/** Priority of this options block
+ *
+ * This is a signed 8-bit integer field indicating the priority of
+ * this block of options. It can be used to specify the relative
+ * priority of multiple option blocks (e.g. options from non-volatile
+ * storage versus options from a DHCP server).
+ */
+#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x01 )
+
+/** "Your" IP address
+ *
+ * This option is used internally to contain the value of the "yiaddr"
+ * field, in order to provide a consistent approach to storing and
+ * processing options. It should never be present in a DHCP packet.
+ */
+#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x02 )
+
+/** "Server" IP address
+ *
+ * This option is used internally to contain the value of the "siaddr"
+ * field, in order to provide a consistent approach to storing and
+ * processing options. It should never be present in a DHCP packet.
+ */
+#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x03 )
+
+/** Keep SAN drive registered
+ *
+ * If set to a non-zero value, gPXE will not detach any SAN drive
+ * after failing to boot from it. (This option is required in order
+ * to perform a Windows Server 2008 installation direct to an iSCSI
+ * target.)
+ */
+#define DHCP_EB_KEEP_SAN DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x08 )
+
+/*
+ * Tags in the range 0x10-0x7f are reserved for feature markers
+ *
+ */
+
+/** Skip PXE DHCP protocol extensions such as ProxyDHCP
+ *
+ * If set to a non-zero value, gPXE will not wait for ProxyDHCP offers
+ * and will ignore any PXE-specific DHCP options that it receives.
+ */
+#define DHCP_EB_NO_PXEDHCP DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb0 )
+
+/** Network device descriptor
+ *
+ * Byte 0 is the bus type ID; remaining bytes depend on the bus type.
+ *
+ * PCI devices:
+ * Byte 0 : 1 (PCI)
+ * Byte 1 : PCI vendor ID MSB
+ * Byte 2 : PCI vendor ID LSB
+ * Byte 3 : PCI device ID MSB
+ * Byte 4 : PCI device ID LSB
+ */
+#define DHCP_EB_BUS_ID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb1 )
+
+/** Network device descriptor */
+struct dhcp_netdev_desc {
+ /** Bus type ID */
+ uint8_t type;
+ /** Vendor ID */
+ uint16_t vendor;
+ /** Device ID */
+ uint16_t device;
+} __attribute__ (( packed ));
+
+/** BIOS drive number
+ *
+ * This is the drive number for a drive emulated via INT 13. 0x80 is
+ * the first hard disk, 0x81 is the second hard disk, etc.
+ */
+#define DHCP_EB_BIOS_DRIVE DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbd )
+
+/** Username
+ *
+ * This will be used as the username for any required authentication.
+ * It is expected that this option's value will be held in
+ * non-volatile storage, rather than transmitted as part of a DHCP
+ * packet.
+ */
+#define DHCP_EB_USERNAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbe )
+
+/** Password
+ *
+ * This will be used as the password for any required authentication.
+ * It is expected that this option's value will be held in
+ * non-volatile storage, rather than transmitted as part of a DHCP
+ * packet.
+ */
+#define DHCP_EB_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xbf )
+
+/** Reverse username
+ *
+ * This will be used as the reverse username (i.e. the username
+ * provided by the server) for any required authentication. It is
+ * expected that this option's value will be held in non-volatile
+ * storage, rather than transmitted as part of a DHCP packet.
+ */
+#define DHCP_EB_REVERSE_USERNAME DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc0 )
+
+/** Reverse password
+ *
+ * This will be used as the reverse password (i.e. the password
+ * provided by the server) for any required authentication. It is
+ * expected that this option's value will be held in non-volatile
+ * storage, rather than transmitted as part of a DHCP packet.
+ */
+#define DHCP_EB_REVERSE_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc1 )
+
+/** gPXE version number */
+#define DHCP_EB_VERSION DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xeb )
+
+/** iSCSI primary target IQN */
+#define DHCP_ISCSI_PRIMARY_TARGET_IQN 201
+
+/** iSCSI secondary target IQN */
+#define DHCP_ISCSI_SECONDARY_TARGET_IQN 202
+
+/** iSCSI initiator IQN */
+#define DHCP_ISCSI_INITIATOR_IQN 203
+
+/** Maximum normal DHCP option */
+#define DHCP_MAX_OPTION 254
+
+/** End of options
+ *
+ * This tag does not have a length field; it is always only a single
+ * byte in length.
+ */
+#define DHCP_END 255
+
+/** @} */
+
+/**
+ * Count number of arguments to a variadic macro
+ *
+ * This rather neat, non-iterative solution is courtesy of Laurent
+ * Deniau.
+ *
+ */
+#define _VA_ARG_COUNT( _1, _2, _3, _4, _5, _6, _7, _8, \
+ _9, _10, _11, _12, _13, _14, _15, _16, \
+ _17, _18, _19, _20, _21, _22, _23, _24, \
+ _25, _26, _27, _28, _29, _30, _31, _32, \
+ _33, _34, _35, _36, _37, _38, _39, _40, \
+ _41, _42, _43, _44, _45, _46, _47, _48, \
+ _49, _50, _51, _52, _53, _54, _55, _56, \
+ _57, _58, _59, _60, _61, _62, _63, N, ... ) N
+#define VA_ARG_COUNT( ... ) \
+ _VA_ARG_COUNT ( __VA_ARGS__, \
+ 63, 62, 61, 60, 59, 58, 57, 56, \
+ 55, 54, 53, 52, 51, 50, 49, 48, \
+ 47, 46, 45, 44, 43, 42, 41, 40, \
+ 39, 38, 37, 36, 35, 34, 33, 32, \
+ 31, 30, 29, 28, 27, 26, 25, 24, \
+ 23, 22, 21, 20, 19, 18, 17, 16, \
+ 15, 14, 13, 12, 11, 10, 9, 8, \
+ 7, 6, 5, 4, 3, 2, 1, 0 )
+
+/** Construct a DHCP option from a list of bytes */
+#define DHCP_OPTION( ... ) VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__
+
+/** Construct a DHCP option from a list of characters */
+#define DHCP_STRING( ... ) DHCP_OPTION ( __VA_ARGS__ )
+
+/** Construct a byte-valued DHCP option */
+#define DHCP_BYTE( value ) DHCP_OPTION ( value )
+
+/** Construct a word-valued DHCP option */
+#define DHCP_WORD( value ) DHCP_OPTION ( ( ( (value) >> 8 ) & 0xff ), \
+ ( ( (value) >> 0 ) & 0xff ) )
+
+/** Construct a dword-valued DHCP option */
+#define DHCP_DWORD( value ) DHCP_OPTION ( ( ( (value) >> 24 ) & 0xff ), \
+ ( ( (value) >> 16 ) & 0xff ), \
+ ( ( (value) >> 8 ) & 0xff ), \
+ ( ( (value) >> 0 ) & 0xff ) )
+
+/** Construct a DHCP encapsulated options field */
+#define DHCP_ENCAP( ... ) DHCP_OPTION ( __VA_ARGS__, DHCP_END )
+
+/**
+ * A DHCP option
+ *
+ * DHCP options consist of a mandatory tag, a length field that is
+ * mandatory for all options except @c DHCP_PAD and @c DHCP_END, and a
+ * payload.
+ */
+struct dhcp_option {
+ /** Tag
+ *
+ * Must be a @c DHCP_XXX value.
+ */
+ uint8_t tag;
+ /** Length
+ *
+ * This is the length of the data field (i.e. excluding the
+ * tag and length fields). For the two tags @c DHCP_PAD and
+ * @c DHCP_END, the length field is implicitly zero and is
+ * also missing, i.e. these DHCP options are only a single
+ * byte in length.
+ */
+ uint8_t len;
+ /** Option data */
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/**
+ * Length of a DHCP option header
+ *
+ * The header is the portion excluding the data, i.e. the tag and the
+ * length.
+ */
+#define DHCP_OPTION_HEADER_LEN ( offsetof ( struct dhcp_option, data ) )
+
+/** Maximum length for a single DHCP option */
+#define DHCP_MAX_LEN 0xff
+
+/**
+ * A DHCP header
+ *
+ */
+struct dhcphdr {
+ /** Operation
+ *
+ * This must be either @c BOOTP_REQUEST or @c BOOTP_REPLY.
+ */
+ uint8_t op;
+ /** Hardware address type
+ *
+ * This is an ARPHRD_XXX constant. Note that ARPHRD_XXX
+ * constants are nominally 16 bits wide; this could be
+ * considered to be a bug in the BOOTP/DHCP specification.
+ */
+ uint8_t htype;
+ /** Hardware address length */
+ uint8_t hlen;
+ /** Number of hops from server */
+ uint8_t hops;
+ /** Transaction ID */
+ uint32_t xid;
+ /** Seconds since start of acquisition */
+ uint16_t secs;
+ /** Flags */
+ uint16_t flags;
+ /** "Client" IP address
+ *
+ * This is filled in if the client already has an IP address
+ * assigned and can respond to ARP requests.
+ */
+ struct in_addr ciaddr;
+ /** "Your" IP address
+ *
+ * This is the IP address assigned by the server to the client.
+ */
+ struct in_addr yiaddr;
+ /** "Server" IP address
+ *
+ * This is the IP address of the next server to be used in the
+ * boot process.
+ */
+ struct in_addr siaddr;
+ /** "Gateway" IP address
+ *
+ * This is the IP address of the DHCP relay agent, if any.
+ */
+ struct in_addr giaddr;
+ /** Client hardware address */
+ uint8_t chaddr[16];
+ /** Server host name (null terminated)
+ *
+ * This field may be overridden and contain DHCP options
+ */
+ char sname[64];
+ /** Boot file name (null terminated)
+ *
+ * This field may be overridden and contain DHCP options
+ */
+ char file[128];
+ /** DHCP magic cookie
+ *
+ * Must have the value @c DHCP_MAGIC_COOKIE.
+ */
+ uint32_t magic;
+ /** DHCP options
+ *
+ * Variable length; extends to the end of the packet. Minimum
+ * length (for the sake of sanity) is 1, to allow for a single
+ * @c DHCP_END tag.
+ */
+ uint8_t options[0];
+};
+
+/** Opcode for a request from client to server */
+#define BOOTP_REQUEST 1
+
+/** Opcode for a reply from server to client */
+#define BOOTP_REPLY 2
+
+/** BOOTP reply must be broadcast
+ *
+ * Clients that cannot accept unicast BOOTP replies must set this
+ * flag.
+ */
+#define BOOTP_FL_BROADCAST 0x8000
+
+/** DHCP magic cookie */
+#define DHCP_MAGIC_COOKIE 0x63825363UL
+
+/** DHCP minimum packet length
+ *
+ * This is the mandated minimum packet length that a DHCP participant
+ * must be prepared to receive.
+ */
+#define DHCP_MIN_LEN 552
+
+/** Timeouts for sending DHCP packets */
+#define DHCP_MIN_TIMEOUT ( 1 * TICKS_PER_SEC )
+#define DHCP_MAX_TIMEOUT ( 10 * TICKS_PER_SEC )
+
+/** Maximum time that we will wait for ProxyDHCP responses */
+#define PROXYDHCP_MAX_TIMEOUT ( 2 * TICKS_PER_SEC )
+
+/** Maximum time that we will wait for Boot Server responses */
+#define PXEBS_MAX_TIMEOUT ( 3 * TICKS_PER_SEC )
+
+/** Settings block name used for DHCP responses */
+#define DHCP_SETTINGS_NAME "dhcp"
+
+/** Settings block name used for ProxyDHCP responses */
+#define PROXYDHCP_SETTINGS_NAME "proxydhcp"
+
+/** Setting block name used for BootServerDHCP responses */
+#define PXEBS_SETTINGS_NAME "pxebs"
+
+extern void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen,
+ uint16_t *flags );
+extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, uint8_t msgtype,
+ const void *options, size_t options_len,
+ void *data, size_t max_len );
+extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev,
+ unsigned int msgtype, struct in_addr ciaddr,
+ void *data, size_t max_len );
+extern int start_dhcp ( struct job_interface *job, struct net_device *netdev );
+extern int start_pxebs ( struct job_interface *job, struct net_device *netdev,
+ unsigned int pxe_type );
+
+#endif /* _GPXE_DHCP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcpopts.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcpopts.h
new file mode 100644
index 0000000..3d90f41
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcpopts.h
@@ -0,0 +1,34 @@
+#ifndef _GPXE_DHCPOPTS_H
+#define _GPXE_DHCPOPTS_H
+
+/** @file
+ *
+ * DHCP options
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A DHCP options block */
+struct dhcp_options {
+ /** Option block raw data */
+ void *data;
+ /** Option block length */
+ size_t len;
+ /** Option block maximum length */
+ size_t max_len;
+};
+
+extern int dhcpopt_store ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcpopt_extensible_store ( struct dhcp_options *options,
+ unsigned int tag,
+ const void *data, size_t len );
+extern int dhcpopt_fetch ( struct dhcp_options *options, unsigned int tag,
+ void *data, size_t len );
+extern void dhcpopt_init ( struct dhcp_options *options,
+ void *data, size_t max_len );
+
+#endif /* _GPXE_DHCPOPTS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcppkt.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcppkt.h
new file mode 100644
index 0000000..6007cca
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dhcppkt.h
@@ -0,0 +1,64 @@
+#ifndef _GPXE_DHCPPKT_H
+#define _GPXE_DHCPPKT_H
+
+/** @file
+ *
+ * DHCP packets
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/dhcp.h>
+#include <gpxe/dhcpopts.h>
+#include <gpxe/refcnt.h>
+
+/**
+ * A DHCP packet
+ *
+ */
+struct dhcp_packet {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** The DHCP packet contents */
+ struct dhcphdr *dhcphdr;
+ /** Maximum length of the DHCP packet buffer */
+ size_t max_len;
+ /** Used length of the DHCP packet buffer */
+ size_t len;
+ /** DHCP options */
+ struct dhcp_options options;
+ /** Settings interface */
+ struct settings settings;
+};
+
+/**
+ * Increment reference count on DHCP packet
+ *
+ * @v dhcppkt DHCP packet
+ * @ret dhcppkt DHCP packet
+ */
+static inline __attribute__ (( always_inline )) struct dhcp_packet *
+dhcppkt_get ( struct dhcp_packet *dhcppkt ) {
+ ref_get ( &dhcppkt->refcnt );
+ return dhcppkt;
+}
+
+/**
+ * Decrement reference count on DHCP packet
+ *
+ * @v dhcppkt DHCP packet
+ */
+static inline __attribute__ (( always_inline )) void
+dhcppkt_put ( struct dhcp_packet *dhcppkt ) {
+ ref_put ( &dhcppkt->refcnt );
+}
+
+extern int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len );
+extern void dhcppkt_init ( struct dhcp_packet *dhcppkt,
+ struct dhcphdr *data, size_t len );
+
+#endif /* _GPXE_DHCPPKT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/dns.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dns.h
new file mode 100644
index 0000000..9e5e874
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/dns.h
@@ -0,0 +1,92 @@
+#ifndef _GPXE_DNS_H
+#define _GPXE_DNS_H
+
+/** @file
+ *
+ * DNS protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/in.h>
+
+/*
+ * Constants
+ *
+ */
+
+#define DNS_TYPE_A 1
+#define DNS_TYPE_CNAME 5
+#define DNS_TYPE_ANY 255
+
+#define DNS_CLASS_IN 1
+#define DNS_CLASS_CS 2
+#define DNS_CLASS_CH 3
+#define DNS_CLASS_HS 4
+
+#define DNS_FLAG_QUERY ( 0x00 << 15 )
+#define DNS_FLAG_RESPONSE ( 0x01 << 15 )
+#define DNS_FLAG_QR(flags) ( (flags) & ( 0x01 << 15 ) )
+#define DNS_FLAG_OPCODE_QUERY ( 0x00 << 11 )
+#define DNS_FLAG_OPCODE_IQUERY ( 0x01 << 11 )
+#define DNS_FLAG_OPCODE_STATUS ( 0x02 << 11 )
+#define DNS_FLAG_OPCODE(flags) ( (flags) & ( 0x0f << 11 ) )
+#define DNS_FLAG_RD ( 0x01 << 8 )
+#define DNS_FLAG_RA ( 0x01 << 7 )
+#define DNS_FLAG_RCODE_OK ( 0x00 << 0 )
+#define DNS_FLAG_RCODE_NX ( 0x03 << 0 )
+#define DNS_FLAG_RCODE(flags) ( (flags) & ( 0x0f << 0 ) )
+
+#define DNS_PORT 53
+#define DNS_MAX_RETRIES 3
+#define DNS_MAX_CNAME_RECURSION 0x30
+
+/*
+ * DNS protocol structures
+ *
+ */
+struct dns_header {
+ uint16_t id;
+ uint16_t flags;
+ uint16_t qdcount;
+ uint16_t ancount;
+ uint16_t nscount;
+ uint16_t arcount;
+} __attribute__ (( packed ));
+
+struct dns_query_info {
+ uint16_t qtype;
+ uint16_t qclass;
+} __attribute__ (( packed ));
+
+struct dns_query {
+ struct dns_header dns;
+ char payload[ 256 + sizeof ( struct dns_query_info ) ];
+} __attribute__ (( packed ));
+
+struct dns_rr_info_common {
+ uint16_t type;
+ uint16_t class;
+ uint32_t ttl;
+ uint16_t rdlength;
+} __attribute__ (( packed ));
+
+struct dns_rr_info_a {
+ struct dns_rr_info_common common;
+ struct in_addr in_addr;
+} __attribute__ (( packed ));
+
+struct dns_rr_info_cname {
+ struct dns_rr_info_common common;
+ char cname[0];
+} __attribute__ (( packed ));
+
+union dns_rr_info {
+ struct dns_rr_info_common common;
+ struct dns_rr_info_a a;
+ struct dns_rr_info_cname cname;
+};
+
+#endif /* _GPXE_DNS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/downloader.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/downloader.h
new file mode 100644
index 0000000..7f21e07
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/downloader.h
@@ -0,0 +1,19 @@
+#ifndef _GPXE_DOWNLOADER_H
+#define _GPXE_DOWNLOADER_H
+
+/** @file
+ *
+ * Image downloader
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct job_interface;
+struct image;
+
+extern int create_downloader ( struct job_interface *job, struct image *image,
+ int ( * register_image ) ( struct image *image ),
+ int type, ... );
+
+#endif /* _GPXE_DOWNLOADER_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/editbox.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/editbox.h
new file mode 100644
index 0000000..b7cc411
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/editbox.h
@@ -0,0 +1,61 @@
+#ifndef _GPXE_EDITBOX_H
+#define _GPXE_EDITBOX_H
+
+/** @file
+ *
+ * Editable text box widget
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <curses.h>
+#include <gpxe/editstring.h>
+
+/** An editable text box widget */
+struct edit_box {
+ /** Editable string */
+ struct edit_string string;
+ /** Containing window */
+ WINDOW *win;
+ /** Row */
+ unsigned int row;
+ /** Starting column */
+ unsigned int col;
+ /** Width */
+ unsigned int width;
+ /** First displayed character */
+ unsigned int first;
+ /** Flags */
+ unsigned int flags;
+};
+
+/** Editable text box widget flags */
+enum edit_box_flags {
+ /** Show stars instead of contents (for password widgets) */
+ EDITBOX_STARS = 0x0001,
+};
+
+extern void init_editbox ( struct edit_box *box, char *buf, size_t len,
+ WINDOW *win, unsigned int row, unsigned int col,
+ unsigned int width, unsigned int flags )
+ __attribute__ (( nonnull (1, 2) ));
+extern void draw_editbox ( struct edit_box *box ) __nonnull;
+static inline int edit_editbox ( struct edit_box *box, int key ) __nonnull;
+
+/**
+ * Edit text box widget
+ *
+ * @v box Editable text box widget
+ * @v key Key pressed by user
+ * @ret key Key returned to application, or zero
+ *
+ * You must call draw_editbox() to update the display after calling
+ * edit_editbox().
+ *
+ */
+static inline int edit_editbox ( struct edit_box *box, int key ) {
+ return edit_string ( &box->string, key );
+}
+
+#endif /* _GPXE_EDITBOX_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/editstring.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/editstring.h
new file mode 100644
index 0000000..48c1baa
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/editstring.h
@@ -0,0 +1,33 @@
+#ifndef _GPXE_EDITSTRING_H
+#define _GPXE_EDITSTRING_H
+
+/** @file
+ *
+ * Editable strings
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** An editable string */
+struct edit_string {
+ /** Buffer for string */
+ char *buf;
+ /** Size of buffer (including terminating NUL) */
+ size_t len;
+ /** Cursor position */
+ unsigned int cursor;
+
+ /* The following items are the edit history */
+
+ /** Last cursor position */
+ unsigned int last_cursor;
+ /** Start of modified portion of string */
+ unsigned int mod_start;
+ /** End of modified portion of string */
+ unsigned int mod_end;
+};
+
+extern int edit_string ( struct edit_string *string, int key ) __nonnull;
+
+#endif /* _GPXE_EDITSTRING_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/eisa.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/eisa.h
new file mode 100644
index 0000000..f76e4b9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/eisa.h
@@ -0,0 +1,130 @@
+#ifndef EISA_H
+#define EISA_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/*
+ * EISA constants
+ *
+ */
+
+#define EISA_MIN_SLOT (0x1)
+#define EISA_MAX_SLOT (0xf) /* Must be 2^n - 1 */
+#define EISA_SLOT_BASE( n ) ( 0x1000 * (n) )
+
+#define EISA_VENDOR_ID ( 0xc80 )
+#define EISA_PROD_ID ( 0xc82 )
+#define EISA_GLOBAL_CONFIG ( 0xc84 )
+
+#define EISA_CMD_RESET ( 1 << 2 )
+#define EISA_CMD_ENABLE ( 1 << 0 )
+
+/** An EISA device ID list entry */
+struct eisa_device_id {
+ /** Name */
+ const char *name;
+ /** Manufacturer ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+};
+
+/** An EISA device */
+struct eisa_device {
+ /** Generic device */
+ struct device dev;
+ /** Slot number */
+ unsigned int slot;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Manufacturer ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Driver for this device */
+ struct eisa_driver *driver;
+ /** Driver-private data
+ *
+ * Use eisa_set_drvdata() and eisa_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/** An EISA driver */
+struct eisa_driver {
+ /** EISA ID table */
+ struct eisa_device_id *ids;
+ /** Number of entries in EISA ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v eisa EISA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct eisa_device *eisa,
+ const struct eisa_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v eisa EISA device
+ */
+ void ( * remove ) ( struct eisa_device *eisa );
+};
+
+/** EISA driver table */
+#define EISA_DRIVERS __table ( struct eisa_driver, "eisa_drivers" )
+
+/** Declare an EISA driver */
+#define __eisa_driver __table_entry ( EISA_DRIVERS, 01 )
+
+extern void eisa_device_enabled ( struct eisa_device *eisa, int enabled );
+
+/**
+ * Enable EISA device
+ *
+ * @v eisa EISA device
+ */
+static inline void enable_eisa_device ( struct eisa_device *eisa ) {
+ eisa_device_enabled ( eisa, 1 );
+}
+
+/**
+ * Disable EISA device
+ *
+ * @v eisa EISA device
+ */
+static inline void disable_eisa_device ( struct eisa_device *eisa ) {
+ eisa_device_enabled ( eisa, 0 );
+}
+
+/**
+ * Set EISA driver-private data
+ *
+ * @v eisa EISA device
+ * @v priv Private data
+ */
+static inline void eisa_set_drvdata ( struct eisa_device *eisa, void *priv ) {
+ eisa->priv = priv;
+}
+
+/**
+ * Get EISA driver-private data
+ *
+ * @v eisa EISA device
+ * @ret priv Private data
+ */
+static inline void * eisa_get_drvdata ( struct eisa_device *eisa ) {
+ return eisa->priv;
+}
+
+#endif /* EISA_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/elf.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/elf.h
new file mode 100644
index 0000000..da9d2fc
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/elf.h
@@ -0,0 +1,17 @@
+#ifndef _GPXE_ELF_H
+#define _GPXE_ELF_H
+
+/**
+ * @file
+ *
+ * ELF image format
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <elf.h>
+
+extern int elf_load ( struct image *image );
+
+#endif /* _GPXE_ELF_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/errfile.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/errfile.h
new file mode 100644
index 0000000..482aa78
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/errfile.h
@@ -0,0 +1,196 @@
+#ifndef _GPXE_ERRFILE_H
+#define _GPXE_ERRFILE_H
+
+/** @file
+ *
+ * Error file identifiers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <bits/errfile.h>
+
+/**
+ * @defgroup errfilecat Error file identifier categories
+ *
+ * @{
+ */
+
+#define ERRFILE_CORE 0x00002000 /**< Core code */
+#define ERRFILE_DRIVER 0x00004000 /**< Driver code */
+#define ERRFILE_NET 0x00006000 /**< Networking code */
+#define ERRFILE_IMAGE 0x00008000 /**< Image code */
+#define ERRFILE_OTHER 0x0000e000 /**< Any other code */
+
+/** @} */
+
+/** Flag for architecture-dependent error files */
+#define ERRFILE_ARCH 0x00800000
+
+/**
+ * @defgroup errfile Error file identifiers
+ *
+ * These values are automatically incorporated into the definitions
+ * for error numbers such as EINVAL.
+ *
+ * @{
+ */
+
+#define ERRFILE_asprintf ( ERRFILE_CORE | 0x00000000 )
+#define ERRFILE_downloader ( ERRFILE_CORE | 0x00010000 )
+#define ERRFILE_exec ( ERRFILE_CORE | 0x00020000 )
+#define ERRFILE_hw ( ERRFILE_CORE | 0x00030000 )
+#define ERRFILE_iobuf ( ERRFILE_CORE | 0x00040000 )
+#define ERRFILE_job ( ERRFILE_CORE | 0x00050000 )
+#define ERRFILE_linebuf ( ERRFILE_CORE | 0x00060000 )
+#define ERRFILE_monojob ( ERRFILE_CORE | 0x00070000 )
+#define ERRFILE_nvo ( ERRFILE_CORE | 0x00080000 )
+#define ERRFILE_open ( ERRFILE_CORE | 0x00090000 )
+#define ERRFILE_posix_io ( ERRFILE_CORE | 0x000a0000 )
+#define ERRFILE_resolv ( ERRFILE_CORE | 0x000b0000 )
+#define ERRFILE_settings ( ERRFILE_CORE | 0x000c0000 )
+#define ERRFILE_vsprintf ( ERRFILE_CORE | 0x000d0000 )
+#define ERRFILE_xfer ( ERRFILE_CORE | 0x000e0000 )
+#define ERRFILE_bitmap ( ERRFILE_CORE | 0x000f0000 )
+
+#define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 )
+#define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 )
+#define ERRFILE_isapnp ( ERRFILE_DRIVER | 0x00020000 )
+#define ERRFILE_mca ( ERRFILE_DRIVER | 0x00030000 )
+#define ERRFILE_pci ( ERRFILE_DRIVER | 0x00040000 )
+
+#define ERRFILE_nvs ( ERRFILE_DRIVER | 0x00100000 )
+#define ERRFILE_spi ( ERRFILE_DRIVER | 0x00110000 )
+#define ERRFILE_i2c_bit ( ERRFILE_DRIVER | 0x00120000 )
+#define ERRFILE_spi_bit ( ERRFILE_DRIVER | 0x00130000 )
+
+#define ERRFILE_3c509 ( ERRFILE_DRIVER | 0x00200000 )
+#define ERRFILE_bnx2 ( ERRFILE_DRIVER | 0x00210000 )
+#define ERRFILE_cs89x0 ( ERRFILE_DRIVER | 0x00220000 )
+#define ERRFILE_eepro ( ERRFILE_DRIVER | 0x00230000 )
+#define ERRFILE_etherfabric ( ERRFILE_DRIVER | 0x00240000 )
+#define ERRFILE_legacy ( ERRFILE_DRIVER | 0x00250000 )
+#define ERRFILE_natsemi ( ERRFILE_DRIVER | 0x00260000 )
+#define ERRFILE_pnic ( ERRFILE_DRIVER | 0x00270000 )
+#define ERRFILE_prism2_pci ( ERRFILE_DRIVER | 0x00280000 )
+#define ERRFILE_prism2_plx ( ERRFILE_DRIVER | 0x00290000 )
+#define ERRFILE_rtl8139 ( ERRFILE_DRIVER | 0x002a0000 )
+#define ERRFILE_smc9000 ( ERRFILE_DRIVER | 0x002b0000 )
+#define ERRFILE_tg3 ( ERRFILE_DRIVER | 0x002c0000 )
+#define ERRFILE_3c509_eisa ( ERRFILE_DRIVER | 0x002d0000 )
+#define ERRFILE_3c515 ( ERRFILE_DRIVER | 0x002e0000 )
+#define ERRFILE_3c529 ( ERRFILE_DRIVER | 0x002f0000 )
+#define ERRFILE_3c595 ( ERRFILE_DRIVER | 0x00300000 )
+#define ERRFILE_3c5x9 ( ERRFILE_DRIVER | 0x00310000 )
+#define ERRFILE_3c90x ( ERRFILE_DRIVER | 0x00320000 )
+#define ERRFILE_amd8111e ( ERRFILE_DRIVER | 0x00330000 )
+#define ERRFILE_davicom ( ERRFILE_DRIVER | 0x00340000 )
+#define ERRFILE_depca ( ERRFILE_DRIVER | 0x00350000 )
+#define ERRFILE_dmfe ( ERRFILE_DRIVER | 0x00360000 )
+#define ERRFILE_eepro100 ( ERRFILE_DRIVER | 0x00380000 )
+#define ERRFILE_epic100 ( ERRFILE_DRIVER | 0x00390000 )
+#define ERRFILE_forcedeth ( ERRFILE_DRIVER | 0x003a0000 )
+#define ERRFILE_mtd80x ( ERRFILE_DRIVER | 0x003b0000 )
+#define ERRFILE_ns83820 ( ERRFILE_DRIVER | 0x003c0000 )
+#define ERRFILE_ns8390 ( ERRFILE_DRIVER | 0x003d0000 )
+#define ERRFILE_pcnet32 ( ERRFILE_DRIVER | 0x003e0000 )
+#define ERRFILE_r8169 ( ERRFILE_DRIVER | 0x003f0000 )
+#define ERRFILE_sis900 ( ERRFILE_DRIVER | 0x00400000 )
+#define ERRFILE_sundance ( ERRFILE_DRIVER | 0x00410000 )
+#define ERRFILE_tlan ( ERRFILE_DRIVER | 0x00420000 )
+#define ERRFILE_tulip ( ERRFILE_DRIVER | 0x00430000 )
+#define ERRFILE_via_rhine ( ERRFILE_DRIVER | 0x00440000 )
+#define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 )
+#define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 )
+#define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 )
+#define ERRFILE_e1000 ( ERRFILE_DRIVER | 0x00480000 )
+#define ERRFILE_e1000_hw ( ERRFILE_DRIVER | 0x00490000 )
+#define ERRFILE_mtnic ( ERRFILE_DRIVER | 0x004a0000 )
+#define ERRFILE_phantom ( ERRFILE_DRIVER | 0x004b0000 )
+#define ERRFILE_ne2k_isa ( ERRFILE_DRIVER | 0x004c0000 )
+#define ERRFILE_b44 ( ERRFILE_DRIVER | 0x004d0000 )
+#define ERRFILE_rtl818x ( ERRFILE_DRIVER | 0x004e0000 )
+#define ERRFILE_sky2 ( ERRFILE_DRIVER | 0x004f0000 )
+#define ERRFILE_ath5k ( ERRFILE_DRIVER | 0x00500000 )
+#define ERRFILE_atl1e ( ERRFILE_DRIVER | 0x00510000 )
+
+#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
+#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
+#define ERRFILE_hermon ( ERRFILE_DRIVER | 0x00720000 )
+#define ERRFILE_linda ( ERRFILE_DRIVER | 0x00730000 )
+#define ERRFILE_ata ( ERRFILE_DRIVER | 0x00740000 )
+#define ERRFILE_srp ( ERRFILE_DRIVER | 0x00750000 )
+
+#define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 )
+#define ERRFILE_arp ( ERRFILE_NET | 0x00010000 )
+#define ERRFILE_dhcpopts ( ERRFILE_NET | 0x00020000 )
+#define ERRFILE_ethernet ( ERRFILE_NET | 0x00030000 )
+#define ERRFILE_icmpv6 ( ERRFILE_NET | 0x00040000 )
+#define ERRFILE_ipv4 ( ERRFILE_NET | 0x00050000 )
+#define ERRFILE_ipv6 ( ERRFILE_NET | 0x00060000 )
+#define ERRFILE_ndp ( ERRFILE_NET | 0x00070000 )
+#define ERRFILE_netdevice ( ERRFILE_NET | 0x00080000 )
+#define ERRFILE_nullnet ( ERRFILE_NET | 0x00090000 )
+#define ERRFILE_tcp ( ERRFILE_NET | 0x000a0000 )
+#define ERRFILE_ftp ( ERRFILE_NET | 0x000b0000 )
+#define ERRFILE_http ( ERRFILE_NET | 0x000c0000 )
+#define ERRFILE_iscsi ( ERRFILE_NET | 0x000d0000 )
+#define ERRFILE_tcpip ( ERRFILE_NET | 0x000e0000 )
+#define ERRFILE_udp ( ERRFILE_NET | 0x000f0000 )
+#define ERRFILE_dhcp ( ERRFILE_NET | 0x00100000 )
+#define ERRFILE_dns ( ERRFILE_NET | 0x00110000 )
+#define ERRFILE_tftp ( ERRFILE_NET | 0x00120000 )
+#define ERRFILE_infiniband ( ERRFILE_NET | 0x00130000 )
+#define ERRFILE_netdev_settings ( ERRFILE_NET | 0x00140000 )
+#define ERRFILE_dhcppkt ( ERRFILE_NET | 0x00150000 )
+#define ERRFILE_slam ( ERRFILE_NET | 0x00160000 )
+#define ERRFILE_ib_sma ( ERRFILE_NET | 0x00170000 )
+#define ERRFILE_ib_packet ( ERRFILE_NET | 0x00180000 )
+#define ERRFILE_icmp ( ERRFILE_NET | 0x00190000 )
+#define ERRFILE_ib_qset ( ERRFILE_NET | 0x001a0000 )
+#define ERRFILE_ib_gma ( ERRFILE_NET | 0x001b0000 )
+#define ERRFILE_ib_pathrec ( ERRFILE_NET | 0x001c0000 )
+#define ERRFILE_ib_mcast ( ERRFILE_NET | 0x001d0000 )
+#define ERRFILE_ib_cm ( ERRFILE_NET | 0x001e0000 )
+#define ERRFILE_net80211 ( ERRFILE_NET | 0x001f0000 )
+#define ERRFILE_ib_mi ( ERRFILE_NET | 0x00200000 )
+#define ERRFILE_ib_cmrc ( ERRFILE_NET | 0x00210000 )
+#define ERRFILE_ib_srp ( ERRFILE_NET | 0x00220000 )
+
+#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
+#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
+#define ERRFILE_script ( ERRFILE_IMAGE | 0x00020000 )
+#define ERRFILE_segment ( ERRFILE_IMAGE | 0x00030000 )
+#define ERRFILE_efi_image ( ERRFILE_IMAGE | 0x00040000 )
+#define ERRFILE_embedded ( ERRFILE_IMAGE | 0x00050000 )
+
+#define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 )
+#define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 )
+#define ERRFILE_aoeboot ( ERRFILE_OTHER | 0x00020000 )
+#define ERRFILE_autoboot ( ERRFILE_OTHER | 0x00030000 )
+#define ERRFILE_dhcpmgmt ( ERRFILE_OTHER | 0x00040000 )
+#define ERRFILE_imgmgmt ( ERRFILE_OTHER | 0x00050000 )
+#define ERRFILE_pxe_tftp ( ERRFILE_OTHER | 0x00060000 )
+#define ERRFILE_pxe_udp ( ERRFILE_OTHER | 0x00070000 )
+#define ERRFILE_axtls_aes ( ERRFILE_OTHER | 0x00080000 )
+#define ERRFILE_cipher ( ERRFILE_OTHER | 0x00090000 )
+#define ERRFILE_image_cmd ( ERRFILE_OTHER | 0x000a0000 )
+#define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 )
+#define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 )
+#define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 )
+#define ERRFILE_ifmgmt ( ERRFILE_OTHER | 0x000e0000 )
+#define ERRFILE_iscsiboot ( ERRFILE_OTHER | 0x000f0000 )
+#define ERRFILE_efi_pci ( ERRFILE_OTHER | 0x00100000 )
+#define ERRFILE_efi_snp ( ERRFILE_OTHER | 0x00110000 )
+#define ERRFILE_smbios ( ERRFILE_OTHER | 0x00120000 )
+#define ERRFILE_smbios_settings ( ERRFILE_OTHER | 0x00130000 )
+#define ERRFILE_efi_smbios ( ERRFILE_OTHER | 0x00140000 )
+#define ERRFILE_pxemenu ( ERRFILE_OTHER | 0x00150000 )
+#define ERRFILE_x509 ( ERRFILE_OTHER | 0x00160000 )
+#define ERRFILE_login_ui ( ERRFILE_OTHER | 0x00170000 )
+#define ERRFILE_ib_srpboot ( ERRFILE_OTHER | 0x00180000 )
+
+/** @} */
+
+#endif /* _GPXE_ERRFILE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/errortab.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/errortab.h
new file mode 100644
index 0000000..35765d4
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/errortab.h
@@ -0,0 +1,23 @@
+#ifndef _GPXE_ERRORTAB_H
+#define _GPXE_ERRORTAB_H
+
+/** @file
+ *
+ * Error message tables
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tables.h>
+
+struct errortab {
+ int errno;
+ const char *text;
+};
+
+#define ERRORTAB __table ( struct errortab, "errortab" )
+
+#define __errortab __table_entry ( ERRORTAB, 01 )
+
+#endif /* _GPXE_ERRORTAB_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ethernet.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ethernet.h
new file mode 100644
index 0000000..8cf6b1b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ethernet.h
@@ -0,0 +1,20 @@
+#ifndef _GPXE_ETHERNET_H
+#define _GPXE_ETHERNET_H
+
+/** @file
+ *
+ * Ethernet protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+extern void eth_init_addr ( const void *hw_addr, void *ll_addr );
+extern const char * eth_ntoa ( const void *ll_addr );
+extern int eth_mc_hash ( unsigned int af, const void *net_addr,
+ void *ll_addr );
+extern struct net_device * alloc_etherdev ( size_t priv_size );
+
+#endif /* _GPXE_ETHERNET_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/fakedhcp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/fakedhcp.h
new file mode 100644
index 0000000..c603bdc
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/fakedhcp.h
@@ -0,0 +1,23 @@
+#ifndef _GPXE_FAKEDHCP_H
+#define _GPXE_FAKEDHCP_H
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+struct net_device;
+
+extern int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakepxebsack ( struct net_device *netdev,
+ void *data, size_t max_len );
+
+#endif /* _GPXE_FAKEDHCP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/filter.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/filter.h
new file mode 100644
index 0000000..1f59fcc
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/filter.h
@@ -0,0 +1,75 @@
+#ifndef _GPXE_FILTER_H
+#define _GPXE_FILTER_H
+
+/** @file
+ *
+ * Data transfer filters
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <gpxe/xfer.h>
+
+/**
+ * Half of a data transfer filter
+ *
+ * Embed two of these structures within a structure implementing a
+ * data transfer filter, and intialise with filter_init(). You can
+ * then use the filter_xxx() methods as the data transfer interface
+ * methods as required.
+ */
+struct xfer_filter_half {
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+ /** Other half of the data transfer filter */
+ struct xfer_filter_half *other;
+};
+
+/**
+ * Get data transfer interface for the other half of a data transfer filter
+ *
+ * @v xfer Data transfer interface
+ * @ret other Other half's data transfer interface
+ */
+static inline __attribute__ (( always_inline )) struct xfer_interface *
+filter_other_half ( struct xfer_interface *xfer ) {
+ struct xfer_filter_half *half =
+ container_of ( xfer, struct xfer_filter_half, xfer );
+ return &half->other->xfer;
+}
+
+extern void filter_close ( struct xfer_interface *xfer, int rc );
+extern int filter_vredirect ( struct xfer_interface *xfer, int type,
+ va_list args );
+extern size_t filter_window ( struct xfer_interface *xfer );
+extern struct io_buffer * filter_alloc_iob ( struct xfer_interface *xfer,
+ size_t len );
+extern int filter_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+extern int filter_deliver_raw ( struct xfer_interface *xfer, const void *data,
+ size_t len );
+
+/**
+ * Initialise a data transfer filter
+ *
+ * @v left "Left" half of the filter
+ * @v left_op Data transfer interface operations for "left" half
+ * @v right "Right" half of the filter
+ * @v right_op Data transfer interface operations for "right" half
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void filter_init ( struct xfer_filter_half *left,
+ struct xfer_interface_operations *left_op,
+ struct xfer_filter_half *right,
+ struct xfer_interface_operations *right_op,
+ struct refcnt *refcnt ) {
+ xfer_init ( &left->xfer, left_op, refcnt );
+ xfer_init ( &right->xfer, right_op, refcnt );
+ left->other = right;
+ right->other = left;
+}
+
+#endif /* _GPXE_FILTER_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ftp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ftp.h
new file mode 100644
index 0000000..93194f6
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ftp.h
@@ -0,0 +1,15 @@
+#ifndef _GPXE_FTP_H
+#define _GPXE_FTP_H
+
+/** @file
+ *
+ * File transfer protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** FTP default port */
+#define FTP_PORT 21
+
+#endif /* _GPXE_FTP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbserial.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbserial.h
new file mode 100644
index 0000000..2613ab4
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbserial.h
@@ -0,0 +1,21 @@
+#ifndef _GPXE_GDBSERIAL_H
+#define _GPXE_GDBSERIAL_H
+
+/** @file
+ *
+ * GDB remote debugging over serial
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct gdb_transport;
+
+/**
+ * Set up the serial transport
+ *
+ * @ret transport suitable for starting the GDB stub or NULL on error
+ */
+struct gdb_transport *gdbserial_configure ( void );
+
+#endif /* _GPXE_GDBSERIAL_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbstub.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbstub.h
new file mode 100644
index 0000000..8f9b7c1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbstub.h
@@ -0,0 +1,77 @@
+#ifndef _GPXE_GDBSTUB_H
+#define _GPXE_GDBSTUB_H
+
+/** @file
+ *
+ * GDB remote debugging
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/tables.h>
+#include <gdbmach.h>
+
+/**
+ * A transport mechanism for the GDB protocol
+ *
+ */
+struct gdb_transport {
+ /** Transport name */
+ const char *name;
+ /**
+ * Set up the transport given a list of arguments
+ *
+ * @v argc Number of arguments
+ * @v argv Argument list
+ * @ret Return status code
+ *
+ * Note that arguments start at argv[0].
+ */
+ int ( * init ) ( int argc, char **argv );
+ /**
+ * Perform a blocking read
+ *
+ * @v buf Buffer
+ * @v len Size of buffer
+ * @ret Number of bytes read into buffer
+ */
+ size_t ( * recv ) ( char *buf, size_t len );
+ /**
+ * Write, may block
+ *
+ * @v buf Buffer
+ * @v len Size of buffer
+ */
+ void ( * send ) ( const char *buf, size_t len );
+};
+
+#define GDB_TRANSPORTS __table ( struct gdb_transport, "gdb_transports" )
+
+#define __gdb_transport __table_entry ( GDB_TRANSPORTS, 01 )
+
+/**
+ * Look up GDB transport by name
+ *
+ * @v name Name of transport
+ * @ret GDB transport or NULL
+ */
+extern struct gdb_transport *find_gdb_transport ( const char *name );
+
+/**
+ * Break into the debugger using the given transport
+ *
+ * @v trans GDB transport
+ */
+extern void gdbstub_start ( struct gdb_transport *trans );
+
+/**
+ * Interrupt handler
+ *
+ * @signo POSIX signal number
+ * @regs CPU register snapshot
+ **/
+extern void gdbstub_handler ( int signo, gdbreg_t *regs );
+
+#endif /* _GPXE_GDBSTUB_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbudp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbudp.h
new file mode 100644
index 0000000..5f02faa
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/gdbudp.h
@@ -0,0 +1,24 @@
+#ifndef _GPXE_GDBUDP_H
+#define _GPXE_GDBUDP_H
+
+/** @file
+ *
+ * GDB remote debugging over UDP
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct sockaddr_in;
+struct gdb_transport;
+
+/**
+ * Set up the UDP transport with network address
+ *
+ * @name network device name
+ * @addr IP address and UDP listen port, may be NULL and fields may be zero
+ * @ret transport suitable for starting the GDB stub or NULL on error
+ */
+struct gdb_transport *gdbudp_configure ( const char *name, struct sockaddr_in *addr );
+
+#endif /* _GPXE_GDBUDP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/hidemem.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/hidemem.h
new file mode 100644
index 0000000..01b3fc2
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/hidemem.h
@@ -0,0 +1,17 @@
+#ifndef _GPXE_HIDEMEM_H
+#define _GPXE_HIDEMEM_H
+
+/**
+ * @file
+ *
+ * Hidden memory regions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+extern void hide_umalloc ( physaddr_t start, physaddr_t end );
+
+#endif /* _GPXE_HIDEMEM_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/hmac.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/hmac.h
new file mode 100644
index 0000000..cb001b9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/hmac.h
@@ -0,0 +1,32 @@
+#ifndef _GPXE_HMAC_H
+#define _GPXE_HMAC_H
+
+/** @file
+ *
+ * Keyed-Hashing for Message Authentication
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crypto.h>
+
+/**
+ * Update HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v data Data
+ * @v len Length of data
+ */
+static inline void hmac_update ( struct digest_algorithm *digest,
+ void *digest_ctx, const void *data,
+ size_t len ) {
+ digest_update ( digest, digest_ctx, data, len );
+}
+
+extern void hmac_init ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len );
+extern void hmac_final ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len, void *hmac );
+
+#endif /* _GPXE_HMAC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/http.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/http.h
new file mode 100644
index 0000000..baa6d83
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/http.h
@@ -0,0 +1,23 @@
+#ifndef _GPXE_HTTP_H
+#define _GPXE_HTTP_H
+
+/** @file
+ *
+ * Hyper Text Transport Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** HTTP default port */
+#define HTTP_PORT 80
+
+/** HTTPS default port */
+#define HTTPS_PORT 443
+
+extern int http_open_filter ( struct xfer_interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ int ( * filter ) ( struct xfer_interface *,
+ struct xfer_interface ** ) );
+
+#endif /* _GPXE_HTTP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/i2c.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/i2c.h
new file mode 100644
index 0000000..87b89d4
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/i2c.h
@@ -0,0 +1,171 @@
+#ifndef _GPXE_I2C_H
+#define _GPXE_I2C_H
+
+/** @file
+ *
+ * I2C interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/bitbash.h>
+
+/** An I2C device
+ *
+ * An I2C device represents a specific slave device on an I2C bus. It
+ * is accessed via an I2C interface.
+ */
+struct i2c_device {
+ /** Address of this device
+ *
+ * The actual address sent on the bus will look like
+ *
+ * <start> <device address> <word address overflow> <r/w>
+ *
+ * The "word address overflow" is any excess bits from the
+ * word address, i.e. any portion that does not fit within the
+ * defined word address length.
+ */
+ unsigned int dev_addr;
+ /** Device address length, in bytes
+ *
+ * This is the number of bytes that comprise the device
+ * address, defined to be the portion that terminates with the
+ * read/write bit.
+ */
+ unsigned int dev_addr_len;
+ /** Word adddress length, in bytes
+ *
+ * This is the number of bytes that comprise the word address,
+ * defined to be the portion that starts after the read/write
+ * bit and ends before the first data byte.
+ *
+ * For some devices, this length will be zero (i.e. the word
+ * address is contained entirely within the "word address
+ * overflow").
+ */
+ unsigned int word_addr_len;
+};
+
+/** An I2C interface
+ *
+ * An I2C interface provides access to an I2C bus, via which I2C
+ * devices may be reached.
+ */
+struct i2c_interface {
+ /**
+ * Read data from I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+ int ( * read ) ( struct i2c_interface *i2c, struct i2c_device *i2cdev,
+ unsigned int offset, uint8_t *data,
+ unsigned int len );
+ /**
+ * Write data to I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @v offset Starting offset within the device
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+ int ( * write ) ( struct i2c_interface *i2c, struct i2c_device *i2cdev,
+ unsigned int offset, const uint8_t *data,
+ unsigned int len );
+};
+
+/** A bit-bashing I2C interface
+ *
+ * This provides a standardised way to construct I2C buses via a
+ * bit-bashing interface.
+ */
+struct i2c_bit_basher {
+ /** I2C interface */
+ struct i2c_interface i2c;
+ /** Bit-bashing interface */
+ struct bit_basher basher;
+};
+
+/** Ten-bit address marker
+ *
+ * This value is ORed with the I2C device address to indicate a
+ * ten-bit address format on the bus.
+ */
+#define I2C_TENBIT_ADDRESS 0x7800
+
+/** An I2C write command */
+#define I2C_WRITE 0
+
+/** An I2C read command */
+#define I2C_READ 1
+
+/** Bit indices used for I2C bit-bashing interface */
+enum {
+ /** Serial clock */
+ I2C_BIT_SCL = 0,
+ /** Serial data */
+ I2C_BIT_SDA,
+};
+
+/** Delay required for bit-bashing operation */
+#define I2C_UDELAY 5
+
+/** Maximum number of cycles to use when attempting a bus reset */
+#define I2C_RESET_MAX_CYCLES 32
+
+/**
+ * Check presence of I2C device
+ *
+ * @v i2c I2C interface
+ * @v i2cdev I2C device
+ * @ret rc Return status code
+ *
+ * Checks for the presence of the device on the I2C bus by attempting
+ * a zero-length write.
+ */
+static inline int i2c_check_presence ( struct i2c_interface *i2c,
+ struct i2c_device *i2cdev ) {
+ return i2c->write ( i2c, i2cdev, 0, NULL, 0 );
+}
+
+extern int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
+ struct bit_basher_operations *bash_op );
+
+/**
+ * Initialise generic I2C EEPROM device
+ *
+ * @v i2cdev I2C device
+ */
+static inline __always_inline void
+init_i2c_eeprom ( struct i2c_device *i2cdev, unsigned int dev_addr ) {
+ i2cdev->dev_addr = dev_addr;
+ i2cdev->dev_addr_len = 1;
+ i2cdev->word_addr_len = 1;
+}
+
+/**
+ * Initialise Atmel AT24C11
+ *
+ * @v i2cdev I2C device
+ */
+static inline __always_inline void
+init_at24c11 ( struct i2c_device *i2cdev ) {
+ /* This chip has no device address; it must be the only chip
+ * on the bus. The word address is contained entirely within
+ * the device address field.
+ */
+ i2cdev->dev_addr = 0;
+ i2cdev->dev_addr_len = 1;
+ i2cdev->word_addr_len = 0;
+}
+
+#endif /* _GPXE_I2C_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cm.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cm.h
new file mode 100644
index 0000000..670fffd
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cm.h
@@ -0,0 +1,72 @@
+#ifndef _GPXE_IB_CM_H
+#define _GPXE_IB_CM_H
+
+/** @file
+ *
+ * Infiniband communication management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/infiniband.h>
+#include <gpxe/retry.h>
+
+struct ib_mad_transaction;
+struct ib_connection;
+
+/** Infiniband connection operations */
+struct ib_connection_operations {
+ /** Handle change of connection status
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v conn Connection
+ * @v rc Connection status code
+ * @v private_data Private data, if available
+ * @v private_data_len Length of private data
+ */
+ void ( * changed ) ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_connection *conn, int rc,
+ void *private_data, size_t private_data_len );
+};
+
+/** An Infiniband connection */
+struct ib_connection {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Target service ID */
+ struct ib_gid_half service_id;
+ /** Connection operations */
+ struct ib_connection_operations *op;
+
+ /** List of connections */
+ struct list_head list;
+
+ /** Path to target */
+ struct ib_path *path;
+ /** Connection request management transaction */
+ struct ib_mad_transaction *madx;
+
+ /** Length of connection request private data */
+ size_t private_data_len;
+ /** Connection request private data */
+ uint8_t private_data[0];
+};
+
+extern struct ib_connection *
+ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *dgid, struct ib_gid_half *service_id,
+ void *req_private_data, size_t req_private_data_len,
+ struct ib_connection_operations *op );
+extern void ib_destroy_conn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_connection *conn );
+
+#endif /* _GPXE_IB_CM_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cmrc.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cmrc.h
new file mode 100644
index 0000000..efa741a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_cmrc.h
@@ -0,0 +1,20 @@
+#ifndef _GPXE_IB_CMRC_H
+#define _GPXE_IB_CMRC_H
+
+/** @file
+ *
+ * Infiniband Communication-managed Reliable Connections
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <gpxe/infiniband.h>
+#include <gpxe/xfer.h>
+
+extern int ib_cmrc_open ( struct xfer_interface *xfer,
+ struct ib_device *ibdev,
+ struct ib_gid *dgid,
+ struct ib_gid_half *service_id );
+
+#endif /* _GPXE_IB_CMRC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mad.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mad.h
new file mode 100644
index 0000000..8b49718
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mad.h
@@ -0,0 +1,561 @@
+#ifndef _GPXE_IB_MAD_H
+#define _GPXE_IB_MAD_H
+
+/** @file
+ *
+ * Infiniband management datagrams
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/ib_packet.h>
+
+/*****************************************************************************
+ *
+ * Subnet management MADs
+ *
+ *****************************************************************************
+ */
+
+/** A subnet management header
+ *
+ * Defined in sections 14.2.1.1 and 14.2.1.2 of the IBA.
+ */
+struct ib_smp_hdr {
+ uint64_t mkey;
+ uint16_t slid;
+ uint16_t dlid;
+ uint8_t reserved[28];
+} __attribute__ (( packed ));
+
+/** Subnet management class version */
+#define IB_SMP_CLASS_VERSION 1
+
+/** Subnet management direction bit
+ *
+ * This bit resides in the "status" field in the MAD header.
+ */
+#define IB_SMP_STATUS_D_INBOUND 0x8000
+
+/* Subnet management attributes */
+#define IB_SMP_ATTR_NOTICE 0x0002
+#define IB_SMP_ATTR_NODE_DESC 0x0010
+#define IB_SMP_ATTR_NODE_INFO 0x0011
+#define IB_SMP_ATTR_SWITCH_INFO 0x0012
+#define IB_SMP_ATTR_GUID_INFO 0x0014
+#define IB_SMP_ATTR_PORT_INFO 0x0015
+#define IB_SMP_ATTR_PKEY_TABLE 0x0016
+#define IB_SMP_ATTR_SL_TO_VL_TABLE 0x0017
+#define IB_SMP_ATTR_VL_ARB_TABLE 0x0018
+#define IB_SMP_ATTR_LINEAR_FORWARD_TABLE 0x0019
+#define IB_SMP_ATTR_RANDOM_FORWARD_TABLE 0x001A
+#define IB_SMP_ATTR_MCAST_FORWARD_TABLE 0x001B
+#define IB_SMP_ATTR_SM_INFO 0x0020
+#define IB_SMP_ATTR_VENDOR_DIAG 0x0030
+#define IB_SMP_ATTR_LED_INFO 0x0031
+#define IB_SMP_ATTR_VENDOR_MASK 0xFF00
+
+/**
+ * A Node Description attribute
+ *
+ * Defined in section 14.2.5.2 of the IBA
+ */
+struct ib_node_desc {
+ char node_string[64];
+} __attribute__ (( packed ));
+
+/** A Node Information attribute
+ *
+ * Defined in section 14.2.5.3 of the IBA.
+ */
+struct ib_node_info {
+ uint8_t base_version;
+ uint8_t class_version;
+ uint8_t node_type;
+ uint8_t num_ports;
+ struct ib_gid_half sys_guid;
+ struct ib_gid_half node_guid;
+ struct ib_gid_half port_guid;
+ uint16_t partition_cap;
+ uint16_t device_id;
+ uint32_t revision;
+ uint8_t local_port_num;
+ uint8_t vendor_id[3];
+} __attribute__ ((packed));
+
+#define IB_NODE_TYPE_HCA 0x01
+#define IB_NODE_TYPE_SWITCH 0x02
+#define IB_NODE_TYPE_ROUTER 0x03
+
+/** A GUID Information attribute
+ *
+ * Defined in section 14.2.5.5 of the IBA.
+ */
+struct ib_guid_info {
+ uint8_t guid[8][8];
+} __attribute__ (( packed ));
+
+/** A Port Information attribute
+ *
+ * Defined in section 14.2.5.6 of the IBA.
+ */
+struct ib_port_info {
+ uint64_t mkey;
+ uint8_t gid_prefix[8];
+ uint16_t lid;
+ uint16_t mastersm_lid;
+ uint32_t cap_mask;
+ uint16_t diag_code;
+ uint16_t mkey_lease_period;
+ uint8_t local_port_num;
+ uint8_t link_width_enabled;
+ uint8_t link_width_supported;
+ uint8_t link_width_active;
+ uint8_t link_speed_supported__port_state;
+ uint8_t port_phys_state__link_down_def_state;
+ uint8_t mkey_prot_bits__lmc;
+ uint8_t link_speed_active__link_speed_enabled;
+ uint8_t neighbour_mtu__mastersm_sl;
+ uint8_t vl_cap__init_type;
+ uint8_t vl_high_limit;
+ uint8_t vl_arbitration_high_cap;
+ uint8_t vl_arbitration_low_cap;
+ uint8_t init_type_reply__mtu_cap;
+ uint8_t vl_stall_count__hoq_life;
+ uint8_t operational_vls__enforcement;
+ uint16_t mkey_violations;
+ uint16_t pkey_violations;
+ uint16_t qkey_violations;
+ uint8_t guid_cap;
+ uint8_t client_reregister__subnet_timeout;
+ uint8_t resp_time_value;
+ uint8_t local_phy_errors__overrun_errors;
+ uint16_t max_credit_hint;
+ uint32_t link_round_trip_latency;
+} __attribute__ (( packed ));
+
+#define IB_LINK_WIDTH_1X 0x01
+#define IB_LINK_WIDTH_4X 0x02
+#define IB_LINK_WIDTH_8X 0x04
+#define IB_LINK_WIDTH_12X 0x08
+
+#define IB_LINK_SPEED_SDR 0x01
+#define IB_LINK_SPEED_DDR 0x02
+#define IB_LINK_SPEED_QDR 0x04
+
+#define IB_PORT_STATE_DOWN 0x01
+#define IB_PORT_STATE_INIT 0x02
+#define IB_PORT_STATE_ARMED 0x03
+#define IB_PORT_STATE_ACTIVE 0x04
+
+#define IB_PORT_PHYS_STATE_SLEEP 0x01
+#define IB_PORT_PHYS_STATE_POLLING 0x02
+
+#define IB_MTU_256 0x01
+#define IB_MTU_512 0x02
+#define IB_MTU_1024 0x03
+#define IB_MTU_2048 0x04
+#define IB_MTU_4096 0x05
+
+#define IB_VL_0 0x01
+#define IB_VL_0_1 0x02
+#define IB_VL_0_3 0x03
+#define IB_VL_0_7 0x04
+#define IB_VL_0_14 0x05
+
+/** A Partition Key Table attribute
+ *
+ * Defined in section 14.2.5.7 of the IBA.
+ */
+struct ib_pkey_table {
+ uint16_t pkey[32];
+} __attribute__ (( packed ));
+
+/** A subnet management attribute */
+union ib_smp_data {
+ struct ib_node_desc node_desc;
+ struct ib_node_info node_info;
+ struct ib_guid_info guid_info;
+ struct ib_port_info port_info;
+ struct ib_pkey_table pkey_table;
+ uint8_t bytes[64];
+} __attribute__ (( packed ));
+
+/** A subnet management directed route path */
+struct ib_smp_dr_path {
+ uint8_t hops[64];
+} __attribute__ (( packed ));
+
+/** Subnet management MAD class-specific data */
+struct ib_smp_class_specific {
+ uint8_t hop_pointer;
+ uint8_t hop_count;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * Subnet administration MADs
+ *
+ *****************************************************************************
+ */
+
+#define IB_SA_CLASS_VERSION 2
+
+#define IB_SA_METHOD_DELETE_RESP 0x95
+
+struct ib_rmpp_hdr {
+ uint32_t raw[3];
+} __attribute__ (( packed ));
+
+struct ib_sa_hdr {
+ uint32_t sm_key[2];
+ uint16_t reserved;
+ uint16_t attrib_offset;
+ uint32_t comp_mask[2];
+} __attribute__ (( packed ));
+
+#define IB_SA_ATTR_MC_MEMBER_REC 0x38
+#define IB_SA_ATTR_PATH_REC 0x35
+
+struct ib_path_record {
+ uint32_t reserved0[2];
+ struct ib_gid dgid;
+ struct ib_gid sgid;
+ uint16_t dlid;
+ uint16_t slid;
+ uint32_t hop_limit__flow_label__raw_traffic;
+ uint32_t pkey__numb_path__reversible__tclass;
+ uint8_t reserved1;
+ uint8_t reserved__sl;
+ uint8_t mtu_selector__mtu;
+ uint8_t rate_selector__rate;
+ uint32_t preference__packet_lifetime__packet_lifetime_selector;
+ uint32_t reserved2[35];
+} __attribute__ (( packed ));
+
+#define IB_SA_PATH_REC_DGID (1<<2)
+#define IB_SA_PATH_REC_SGID (1<<3)
+
+struct ib_mc_member_record {
+ struct ib_gid mgid;
+ struct ib_gid port_gid;
+ uint32_t qkey;
+ uint16_t mlid;
+ uint8_t mtu_selector__mtu;
+ uint8_t tclass;
+ uint16_t pkey;
+ uint8_t rate_selector__rate;
+ uint8_t packet_lifetime_selector__packet_lifetime;
+ uint32_t sl__flow_label__hop_limit;
+ uint8_t scope__join_state;
+ uint8_t proxy_join__reserved;
+ uint16_t reserved0;
+ uint32_t reserved1[37];
+} __attribute__ (( packed ));
+
+#define IB_SA_MCMEMBER_REC_MGID (1<<0)
+#define IB_SA_MCMEMBER_REC_PORT_GID (1<<1)
+#define IB_SA_MCMEMBER_REC_QKEY (1<<2)
+#define IB_SA_MCMEMBER_REC_MLID (1<<3)
+#define IB_SA_MCMEMBER_REC_MTU_SELECTOR (1<<4)
+#define IB_SA_MCMEMBER_REC_MTU (1<<5)
+#define IB_SA_MCMEMBER_REC_TRAFFIC_CLASS (1<<6)
+#define IB_SA_MCMEMBER_REC_PKEY (1<<7)
+#define IB_SA_MCMEMBER_REC_RATE_SELECTOR (1<<8)
+#define IB_SA_MCMEMBER_REC_RATE (1<<9)
+#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR (1<<10)
+#define IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME (1<<11)
+#define IB_SA_MCMEMBER_REC_SL (1<<12)
+#define IB_SA_MCMEMBER_REC_FLOW_LABEL (1<<13)
+#define IB_SA_MCMEMBER_REC_HOP_LIMIT (1<<14)
+#define IB_SA_MCMEMBER_REC_SCOPE (1<<15)
+#define IB_SA_MCMEMBER_REC_JOIN_STATE (1<<16)
+#define IB_SA_MCMEMBER_REC_PROXY_JOIN (1<<17)
+
+union ib_sa_data {
+ struct ib_path_record path_record;
+ struct ib_mc_member_record mc_member_record;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * Communication management MADs
+ *
+ *****************************************************************************
+ */
+
+/** Communication management class version */
+#define IB_CM_CLASS_VERSION 2
+
+/* Communication management attributes */
+#define IB_CM_ATTR_CLASS_PORT_INFO 0x0001
+#define IB_CM_ATTR_CONNECT_REQUEST 0x0010
+#define IB_CM_ATTR_MSG_RCPT_ACK 0x0011
+#define IB_CM_ATTR_CONNECT_REJECT 0x0012
+#define IB_CM_ATTR_CONNECT_REPLY 0x0013
+#define IB_CM_ATTR_READY_TO_USE 0x0014
+#define IB_CM_ATTR_DISCONNECT_REQUEST 0x0015
+#define IB_CM_ATTR_DISCONNECT_REPLY 0x0016
+#define IB_CM_ATTR_SERVICE_ID_RES_REQ 0x0016
+#define IB_CM_ATTR_SERVICE_ID_RES_REQ_RESP 0x0018
+#define IB_CM_ATTR_LOAD_ALTERNATE_PATH 0x0019
+#define IB_CM_ATTR_ALTERNATE_PATH_RESPONSE 0x001a
+
+/** Communication management common fields */
+struct ib_cm_common {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Reserved */
+ uint8_t reserved[224];
+} __attribute__ (( packed ));
+
+/** A communication management path */
+struct ib_cm_path {
+ /** Local port LID */
+ uint16_t local_lid;
+ /** Remote port LID */
+ uint16_t remote_lid;
+ /** Local port GID */
+ struct ib_gid local_gid;
+ /** Remote port GID */
+ struct ib_gid remote_gid;
+ /** Flow label and rate */
+ uint32_t flow_label__rate;
+ /** Traffic class */
+ uint8_t tc;
+ /** Hop limit */
+ uint8_t hop_limit;
+ /** SL and subnet local*/
+ uint8_t sl__subnet_local;
+ /** Local ACK timeout */
+ uint8_t local_ack_timeout;
+} __attribute__ (( packed ));
+
+/** A communication management connection request
+ *
+ * Defined in section 12.6.5 of the IBA.
+ */
+struct ib_cm_connect_request {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Reserved */
+ uint32_t reserved0[1];
+ /** Service ID */
+ struct ib_gid_half service_id;
+ /** Local CA GUID */
+ struct ib_gid_half local_ca;
+ /** Reserved */
+ uint32_t reserved1[1];
+ /** Local queue key */
+ uint32_t local_qkey;
+ /** Local QPN and responder resources*/
+ uint32_t local_qpn__responder_resources;
+ /** Local EECN and initiator depth */
+ uint32_t local_eecn__initiator_depth;
+ /** Remote EECN, remote CM response timeout, transport service
+ * type, EE flow control
+ */
+ uint32_t remote_eecn__remote_timeout__service_type__ee_flow_ctrl;
+ /** Starting PSN, local CM response timeout and retry count */
+ uint32_t starting_psn__local_timeout__retry_count;
+ /** Partition key */
+ uint16_t pkey;
+ /** Path packet payload MTU, RDC exists, RNR retry count */
+ uint8_t payload_mtu__rdc_exists__rnr_retry;
+ /** Max CM retries and SRQ */
+ uint8_t max_cm_retries__srq;
+ /** Primary path */
+ struct ib_cm_path primary;
+ /** Alternate path */
+ struct ib_cm_path alternate;
+ /** Private data */
+ uint8_t private_data[92];
+} __attribute__ (( packed ));
+
+/** CM transport types */
+#define IB_CM_TRANSPORT_RC 0
+#define IB_CM_TRANSPORT_UC 1
+#define IB_CM_TRANSPORT_RD 2
+
+/** A communication management connection rejection
+ *
+ * Defined in section 12.6.7 of the IBA.
+ */
+struct ib_cm_connect_reject {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Message rejected */
+ uint8_t message;
+ /** Reject information length */
+ uint8_t info_len;
+ /** Rejection reason */
+ uint16_t reason;
+ /** Additional rejection information */
+ uint8_t info[72];
+ /** Private data */
+ uint8_t private_data[148];
+} __attribute__ (( packed ));
+
+/** CM rejection reasons */
+#define IB_CM_REJECT_BAD_SERVICE_ID 8
+#define IB_CM_REJECT_STALE_CONN 10
+#define IB_CM_REJECT_CONSUMER 28
+
+/** A communication management connection reply
+ *
+ * Defined in section 12.6.8 of the IBA.
+ */
+struct ib_cm_connect_reply {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Local queue key */
+ uint32_t local_qkey;
+ /** Local QPN */
+ uint32_t local_qpn;
+ /** Local EECN */
+ uint32_t local_eecn;
+ /** Starting PSN */
+ uint32_t starting_psn;
+ /** Responder resources */
+ uint8_t responder_resources;
+ /** Initiator depth */
+ uint8_t initiator_depth;
+ /** Target ACK delay, failover accepted, and end-to-end flow control */
+ uint8_t target_ack_delay__failover_accepted__ee_flow_ctrl;
+ /** RNR retry count, SRQ */
+ uint8_t rnr_retry__srq;
+ /** Local CA GUID */
+ struct ib_gid_half local_ca;
+ /** Private data */
+ uint8_t private_data[196];
+} __attribute__ (( packed ));
+
+/** A communication management ready to use reply
+ *
+ * Defined in section 12.6.9 of the IBA.
+ */
+struct ib_cm_ready_to_use {
+ /** Local communication ID */
+ uint32_t local_id;
+ /** Remote communication ID */
+ uint32_t remote_id;
+ /** Private data */
+ uint8_t private_data[224];
+} __attribute__ (( packed ));
+
+/** A communication management attribute */
+union ib_cm_data {
+ struct ib_cm_common common;
+ struct ib_cm_connect_request connect_request;
+ struct ib_cm_connect_reject connect_reject;
+ struct ib_cm_connect_reply connect_reply;
+ struct ib_cm_ready_to_use ready_to_use;
+ uint8_t bytes[232];
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * MADs
+ *
+ *****************************************************************************
+ */
+
+/** Management datagram class_specific data */
+union ib_mad_class_specific {
+ uint16_t raw;
+ struct ib_smp_class_specific smp;
+} __attribute__ (( packed ));
+
+/** A management datagram common header
+ *
+ * Defined in section 13.4.2 of the IBA.
+ */
+struct ib_mad_hdr {
+ uint8_t base_version;
+ uint8_t mgmt_class;
+ uint8_t class_version;
+ uint8_t method;
+ uint16_t status;
+ union ib_mad_class_specific class_specific;
+ uint32_t tid[2];
+ uint16_t attr_id;
+ uint8_t reserved[2];
+ uint32_t attr_mod;
+} __attribute__ (( packed ));
+
+/* Management base version */
+#define IB_MGMT_BASE_VERSION 1
+
+/* Management classes */
+#define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01
+#define IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE 0x81
+#define IB_MGMT_CLASS_SUBN_ADM 0x03
+#define IB_MGMT_CLASS_PERF_MGMT 0x04
+#define IB_MGMT_CLASS_BM 0x05
+#define IB_MGMT_CLASS_DEVICE_MGMT 0x06
+#define IB_MGMT_CLASS_CM 0x07
+#define IB_MGMT_CLASS_SNMP 0x08
+#define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30
+#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4f
+
+#define IB_MGMT_CLASS_MASK 0x7f
+
+/* Management methods */
+#define IB_MGMT_METHOD_GET 0x01
+#define IB_MGMT_METHOD_SET 0x02
+#define IB_MGMT_METHOD_GET_RESP 0x81
+#define IB_MGMT_METHOD_SEND 0x03
+#define IB_MGMT_METHOD_TRAP 0x05
+#define IB_MGMT_METHOD_REPORT 0x06
+#define IB_MGMT_METHOD_REPORT_RESP 0x86
+#define IB_MGMT_METHOD_TRAP_REPRESS 0x07
+#define IB_MGMT_METHOD_DELETE 0x15
+
+/* Status codes */
+#define IB_MGMT_STATUS_OK 0x0000
+#define IB_MGMT_STATUS_BAD_VERSION 0x0001
+#define IB_MGMT_STATUS_UNSUPPORTED_METHOD 0x0002
+#define IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR 0x0003
+#define IB_MGMT_STATUS_INVALID_VALUE 0x0004
+
+/** A subnet management MAD */
+struct ib_mad_smp {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_smp_hdr smp_hdr;
+ union ib_smp_data smp_data;
+ struct ib_smp_dr_path initial_path;
+ struct ib_smp_dr_path return_path;
+} __attribute__ (( packed ));
+
+/** A subnet administration MAD */
+struct ib_mad_sa {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_rmpp_hdr rmpp_hdr;
+ struct ib_sa_hdr sa_hdr;
+ union ib_sa_data sa_data;
+} __attribute__ (( packed ));
+
+/** A communication management MAD */
+struct ib_mad_cm {
+ struct ib_mad_hdr mad_hdr;
+ union ib_cm_data cm_data;
+} __attribute__ (( packed ));
+
+/** A management datagram */
+union ib_mad {
+ struct ib_mad_hdr hdr;
+ struct ib_mad_smp smp;
+ struct ib_mad_sa sa;
+ struct ib_mad_cm cm;
+ uint8_t bytes[256];
+} __attribute__ (( packed ));
+
+#endif /* _GPXE_IB_MAD_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mcast.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mcast.h
new file mode 100644
index 0000000..74eccd0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mcast.h
@@ -0,0 +1,48 @@
+#ifndef _GPXE_IB_MCAST_H
+#define _GPXE_IB_MCAST_H
+
+/** @file
+ *
+ * Infiniband multicast groups
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/infiniband.h>
+
+struct ib_mad_transaction;
+
+/** An Infiniband multicast group membership */
+struct ib_mc_membership {
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Multicast GID */
+ struct ib_gid gid;
+ /** Multicast group join transaction */
+ struct ib_mad_transaction *madx;
+ /** Handle join success/failure
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ * @v rc Status code
+ * @v mad Response MAD (or NULL on error)
+ */
+ void ( * complete ) ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership, int rc,
+ union ib_mad *mad );
+};
+
+extern int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership,
+ struct ib_gid *gid,
+ void ( * joined ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_mc_membership *memb,
+ int rc, union ib_mad *mad ) );
+
+extern void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership );
+
+#endif /* _GPXE_IB_MCAST_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mi.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mi.h
new file mode 100644
index 0000000..b1cf686
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_mi.h
@@ -0,0 +1,135 @@
+#ifndef _GPXE_IB_MI_H
+#define _GPXE_IB_MI_H
+
+/** @file
+ *
+ * Infiniband management interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/list.h>
+#include <gpxe/retry.h>
+#include <gpxe/tables.h>
+#include <gpxe/infiniband.h>
+
+struct ib_mad_interface;
+struct ib_mad_transaction;
+
+/** An Infiniband management agent */
+struct ib_mad_agent {
+ /** Management class */
+ uint8_t mgmt_class;
+ /** Class version */
+ uint8_t class_version;
+ /** Attribute (in network byte order) */
+ uint16_t attr_id;
+ /** Handle MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ */
+ void ( * handle ) ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av );
+};
+
+/** Infiniband management agents */
+#define IB_MAD_AGENTS __table ( struct ib_mad_agent, "ib_mad_agents" )
+
+/** Declare an Infiniband management agent */
+#define __ib_mad_agent __table_entry ( IB_MAD_AGENTS, 01 )
+
+/** Infiniband management transaction operations */
+struct ib_mad_transaction_operations {
+ /** Handle transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ *
+ * The completion handler should in most cases call
+ * ib_destroy_madx() to free up the completed transaction.
+ */
+ void ( * complete ) ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av );
+};
+
+/** An Infiniband management transaction */
+struct ib_mad_transaction {
+ /** Associated management interface */
+ struct ib_mad_interface *mi;
+ /** List of transactions */
+ struct list_head list;
+ /** Retry timer */
+ struct retry_timer timer;
+ /** Destination address vector */
+ struct ib_address_vector av;
+ /** MAD being sent */
+ union ib_mad mad;
+ /** Transaction operations */
+ struct ib_mad_transaction_operations *op;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+/** An Infiniband management interface */
+struct ib_mad_interface {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Completion queue */
+ struct ib_completion_queue *cq;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** List of management transactions */
+ struct list_head madx;
+};
+
+/**
+ * Set Infiniband management transaction owner-private data
+ *
+ * @v madx Management transaction
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_madx_set_ownerdata ( struct ib_mad_transaction *madx, void *priv ) {
+ madx->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband management transaction owner-private data
+ *
+ * @v madx Management transaction
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_madx_get_ownerdata ( struct ib_mad_transaction *madx ) {
+ return madx->owner_priv;
+}
+
+extern int ib_mi_send ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av );
+extern struct ib_mad_transaction *
+ib_create_madx ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av,
+ struct ib_mad_transaction_operations *op );
+extern void ib_destroy_madx ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx );
+extern struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev,
+ enum ib_queue_pair_type type );
+extern void ib_destroy_mi ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi );
+
+#endif /* _GPXE_IB_MI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_packet.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_packet.h
new file mode 100644
index 0000000..d468859
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_packet.h
@@ -0,0 +1,147 @@
+#ifndef _GPXE_IB_PACKET_H
+#define _GPXE_IB_PACKET_H
+
+/** @file
+ *
+ * Infiniband packet format
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct ib_device;
+struct ib_queue_pair;
+struct ib_address_vector;
+struct io_buffer;
+
+/** Half of an Infiniband Global Identifier */
+struct ib_gid_half {
+ union {
+ uint8_t bytes[8];
+ uint16_t words[4];
+ uint32_t dwords[2];
+ } u;
+};
+
+/** An Infiniband Global Identifier */
+struct ib_gid {
+ union {
+ uint8_t bytes[16];
+ uint16_t words[8];
+ uint32_t dwords[4];
+ struct ib_gid_half half[2];
+ } u;
+};
+
+/** An Infiniband Local Route Header */
+struct ib_local_route_header {
+ /** Virtual lane and link version */
+ uint8_t vl__lver;
+ /** Service level and next link header */
+ uint8_t sl__lnh;
+ /** Destination LID */
+ uint16_t dlid;
+ /** Packet length */
+ uint16_t length;
+ /** Source LID */
+ uint16_t slid;
+} __attribute__ (( packed ));
+
+/** Infiniband virtual lanes */
+enum ib_vl {
+ IB_VL_DEFAULT = 0,
+ IB_VL_SMP = 15,
+};
+
+/** An Infiniband Link Next Header value */
+enum ib_lnh {
+ IB_LNH_RAW = 0,
+ IB_LNH_IPv6 = 1,
+ IB_LNH_BTH = 2,
+ IB_LNH_GRH = 3
+};
+
+/** Default Infiniband LID */
+#define IB_LID_NONE 0xffff
+
+/** Test for multicast LID */
+#define IB_LID_MULTICAST( lid ) ( ( (lid) >= 0xc000 ) && ( (lid) <= 0xfffe ) )
+
+/** An Infiniband Global Route Header */
+struct ib_global_route_header {
+ /** IP version, traffic class, and flow label
+ *
+ * 4 bits : Version of the GRH
+ * 8 bits : Traffic class
+ * 20 bits : Flow label
+ */
+ uint32_t ipver__tclass__flowlabel;
+ /** Payload length */
+ uint16_t paylen;
+ /** Next header */
+ uint8_t nxthdr;
+ /** Hop limit */
+ uint8_t hoplmt;
+ /** Source GID */
+ struct ib_gid sgid;
+ /** Destiniation GID */
+ struct ib_gid dgid;
+} __attribute__ (( packed ));
+
+#define IB_GRH_IPVER_IPv6 0x06
+#define IB_GRH_NXTHDR_IBA 0x1b
+
+/** An Infiniband Base Transport Header */
+struct ib_base_transport_header {
+ /** Opcode */
+ uint8_t opcode;
+ /** Transport header version, pad count, migration and solicitation */
+ uint8_t se__m__padcnt__tver;
+ /** Partition key */
+ uint16_t pkey;
+ /** Destination queue pair */
+ uint32_t dest_qp;
+ /** Packet sequence number and acknowledge request */
+ uint32_t ack__psn;
+} __attribute__ (( packed ));
+
+/** An Infiniband BTH opcode */
+enum ib_bth_opcode {
+ BTH_OPCODE_UD_SEND = 0x64,
+};
+
+/** An Infiniband Datagram Extended Transport Header */
+struct ib_datagram_extended_transport_header {
+ /** Queue key */
+ uint32_t qkey;
+ /** Source queue pair */
+ uint32_t src_qp;
+} __attribute__ (( packed ));
+
+/** All known IB header formats */
+union ib_headers {
+ struct ib_local_route_header lrh;
+ struct {
+ struct ib_local_route_header lrh;
+ struct ib_global_route_header grh;
+ struct ib_base_transport_header bth;
+ struct ib_datagram_extended_transport_header deth;
+ } __attribute__ (( packed )) lrh__grh__bth__deth;
+ struct {
+ struct ib_local_route_header lrh;
+ struct ib_base_transport_header bth;
+ struct ib_datagram_extended_transport_header deth;
+ } __attribute__ (( packed )) lrh__bth__deth;
+} __attribute__ (( packed ));
+
+/** Maximum size required for IB headers */
+#define IB_MAX_HEADER_SIZE sizeof ( union ib_headers )
+
+extern int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair *qp, size_t payload_len,
+ const struct ib_address_vector *av );
+extern int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair **qp, size_t *payload_len,
+ struct ib_address_vector *av );
+
+#endif /* _GPXE_IB_PACKET_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_pathrec.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_pathrec.h
new file mode 100644
index 0000000..5884d53
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_pathrec.h
@@ -0,0 +1,76 @@
+#ifndef _GPXE_IB_PATHREC_H
+#define _GPXE_IB_PATHREC_H
+
+/** @file
+ *
+ * Infiniband path records
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/infiniband.h>
+
+struct ib_mad_transaction;
+struct ib_path;
+
+/** Infiniband path operations */
+struct ib_path_operations {
+ /** Handle path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ * @v rc Status code
+ * @v av Address vector, or NULL on error
+ */
+ void ( * complete ) ( struct ib_device *ibdev,
+ struct ib_path *path, int rc,
+ struct ib_address_vector *av );
+};
+
+/** An Infiniband path */
+struct ib_path {
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Address vector */
+ struct ib_address_vector av;
+ /** Management transaction */
+ struct ib_mad_transaction *madx;
+ /** Path operations */
+ struct ib_path_operations *op;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+/**
+ * Set Infiniband path owner-private data
+ *
+ * @v path Path
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_path_set_ownerdata ( struct ib_path *path, void *priv ) {
+ path->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband path owner-private data
+ *
+ * @v path Path
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_path_get_ownerdata ( struct ib_path *path ) {
+ return path->owner_priv;
+}
+
+extern struct ib_path *
+ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
+ struct ib_path_operations *op );
+extern void ib_destroy_path ( struct ib_device *ibdev,
+ struct ib_path *path );
+
+extern int ib_resolve_path ( struct ib_device *ibdev,
+ struct ib_address_vector *av );
+
+#endif /* _GPXE_IB_PATHREC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_sma.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_sma.h
new file mode 100644
index 0000000..78fc672
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_sma.h
@@ -0,0 +1,20 @@
+#ifndef _GPXE_IB_SMA_H
+#define _GPXE_IB_SMA_H
+
+/** @file
+ *
+ * Infiniband subnet management agent
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct ib_device;
+struct ib_mad_interface;
+
+extern int ib_create_sma ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi );
+extern void ib_destroy_sma ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi );
+
+#endif /* _GPXE_IB_SMA_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_smc.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_smc.h
new file mode 100644
index 0000000..fdd1c9c
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_smc.h
@@ -0,0 +1,20 @@
+#ifndef _GPXE_IB_SMC_H
+#define _GPXE_IB_SMC_H
+
+/** @file
+ *
+ * Infiniband Subnet Management Client
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/infiniband.h>
+
+typedef int ( * ib_local_mad_t ) ( struct ib_device *ibdev,
+ union ib_mad *mad );
+
+extern int ib_smc_update ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad );
+
+#endif /* _GPXE_IB_SMC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_srp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_srp.h
new file mode 100644
index 0000000..cf705b3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ib_srp.h
@@ -0,0 +1,79 @@
+#ifndef _GPXE_IB_SRP_H
+#define _GPXE_IB_SRP_H
+
+/** @file
+ *
+ * SCSI RDMA Protocol over Infiniband
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/srp.h>
+
+/** SRP initiator port identifier for Infiniband */
+struct ib_srp_initiator_port_id {
+ /** Identifier extension */
+ struct ib_gid_half id_ext;
+ /** IB channel adapter GUID */
+ struct ib_gid_half hca_guid;
+} __attribute__ (( packed ));
+
+/** SRP target port identifier for Infiniband */
+struct ib_srp_target_port_id {
+ /** Identifier extension */
+ struct ib_gid_half id_ext;
+ /** I/O controller GUID */
+ struct ib_gid_half ioc_guid;
+} __attribute__ (( packed ));
+
+/**
+ * Get Infiniband-specific initiator port ID
+ *
+ * @v port_ids SRP port IDs
+ * @ret initiator_port_id Infiniband-specific initiator port ID
+ */
+static inline __always_inline struct ib_srp_initiator_port_id *
+ib_srp_initiator_port_id ( struct srp_port_ids *port_ids ) {
+ return ( ( struct ib_srp_initiator_port_id * ) &port_ids->initiator );
+}
+
+/**
+ * Get Infiniband-specific target port ID
+ *
+ * @v port_ids SRP port IDs
+ * @ret target_port_id Infiniband-specific target port ID
+ */
+static inline __always_inline struct ib_srp_target_port_id *
+ib_srp_target_port_id ( struct srp_port_ids *port_ids ) {
+ return ( ( struct ib_srp_target_port_id * ) &port_ids->target );
+}
+
+/** Infiniband-specific SRP parameters */
+struct ib_srp_parameters {
+ /** Source GID */
+ struct ib_gid sgid;
+ /** Destination GID */
+ struct ib_gid dgid;
+ /** Service ID */
+ struct ib_gid_half service_id;
+ /** Partition key */
+ uint16_t pkey;
+};
+
+/**
+ * Get Infiniband-specific transport parameters
+ *
+ * @v srp SRP device
+ * @ret ib_params Infiniband-specific transport parameters
+ */
+static inline __always_inline struct ib_srp_parameters *
+ib_srp_params ( struct srp_device *srp ) {
+ return srp_transport_priv ( srp );
+}
+
+extern struct srp_transport_type ib_srp_transport;
+
+#endif /* _GPXE_IB_SRP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp.h
new file mode 100644
index 0000000..bb8fce8
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp.h
@@ -0,0 +1,25 @@
+#ifndef _GPXE_ICMP_H
+#define _GPXE_ICMP_H
+
+/** @file
+ *
+ * ICMP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** An ICMP header */
+struct icmp_header {
+ /** Type */
+ uint8_t type;
+ /** Code */
+ uint8_t code;
+ /** Checksum */
+ uint16_t chksum;
+} __attribute__ (( packed ));
+
+#define ICMP_ECHO_RESPONSE 0
+#define ICMP_ECHO_REQUEST 8
+
+#endif /* _GPXE_ICMP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp6.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp6.h
new file mode 100644
index 0000000..e8fd1eb
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/icmp6.h
@@ -0,0 +1,59 @@
+#ifndef _GPXE_ICMP6_H
+#define _GPXE_ICMP6_H
+
+/** @file
+ *
+ * ICMP6 protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/ip6.h>
+#include <gpxe/ndp.h>
+
+#define ICMP6_NSOLICIT 135
+#define ICMP6_NADVERT 136
+
+extern struct tcpip_protocol icmp6_protocol;
+
+struct icmp6_header {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ /* Message body */
+};
+
+struct neighbour_solicit {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ uint32_t reserved;
+ struct in6_addr target;
+ /* "Compulsory" options */
+ uint8_t opt_type;
+ uint8_t opt_len;
+ /* FIXME: hack alert */
+ uint8_t opt_ll_addr[6];
+};
+
+struct neighbour_advert {
+ uint8_t type;
+ uint8_t code;
+ uint16_t csum;
+ uint8_t flags;
+ uint8_t reserved;
+ struct in6_addr target;
+ uint8_t opt_type;
+ uint8_t opt_len;
+ /* FIXME: hack alert */
+ uint8_t opt_ll_addr[6];
+};
+
+#define ICMP6_FLAGS_ROUTER 0x80
+#define ICMP6_FLAGS_SOLICITED 0x40
+#define ICMP6_FLAGS_OVERRIDE 0x20
+
+int icmp6_send_solicit ( struct net_device *netdev, struct in6_addr *src, struct in6_addr *dest );
+
+#endif /* _GPXE_ICMP6_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ieee80211.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ieee80211.h
new file mode 100644
index 0000000..0403f92
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ieee80211.h
@@ -0,0 +1,1182 @@
+#ifndef _GPXE_IEEE80211_H
+#define _GPXE_IEEE80211_H
+
+#include <gpxe/if_ether.h> /* for ETH_ALEN */
+
+/** @file
+ * Constants and data structures defined in IEEE 802.11, subsetted
+ * according to what gPXE knows how to use.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/* ---------- Maximum lengths of things ---------- */
+
+/**
+ * @defgroup ieee80211_maxlen Maximum lengths in the 802.11 protocol
+ * @{
+ */
+
+/** Maximum length of frame payload
+ *
+ * This does not include cryptographic overhead, which can be up to 20
+ * bytes, but it DOES include the 802.2 LLC/SNAP headers that are used
+ * on data frames (but not management frames).
+ */
+#define IEEE80211_MAX_DATA_LEN 2304
+
+/** Length of LLC/SNAP headers on data frames */
+#define IEEE80211_LLC_HEADER_LEN 8
+
+/** Maximum cryptographic overhead before encrypted data */
+#define IEEE80211_MAX_CRYPTO_HEADER 8
+
+/** Maximum cryptographic overhead after encrypted data
+ *
+ * This does not count the MIC in TKIP frames, since that is
+ * considered to be part of the MSDU and thus contributes to the size
+ * of the data field.
+ *
+ * It @e does count the MIC in CCMP frames, which is considered part
+ * of the MPDU (outside the data field).
+ */
+#define IEEE80211_MAX_CRYPTO_TRAILER 8
+
+/** Total maximum cryptographic overhead */
+#define IEEE80211_MAX_CRYPTO_OVERHEAD 16
+
+/** Bytes of network-layer data that can go into a regular data frame */
+#define IEEE80211_MAX_FRAME_DATA 2296
+
+/** Frame header length for frames we might work with
+ *
+ * QoS adds a two-byte field on top of this, and APs communicating
+ * with each other in Wireless Distribution System (WDS) mode add an
+ * extra 6-byte MAC address field, but we do not work with such
+ * frames.
+ */
+#define IEEE80211_TYP_FRAME_HEADER_LEN 24
+
+/** Theoretical maximum frame header length
+ *
+ * This includes the QoS and WDS Addr4 fields that we should never
+ * see.
+ */
+#define IEEE80211_MAX_FRAME_HEADER_LEN 32
+
+/** Maximum combined frame length
+ *
+ * The biggest frame will include 32 frame header bytes, 16 bytes of
+ * crypto overhead, and 2304 data bytes.
+ */
+#define IEEE80211_MAX_FRAME_LEN 2352
+
+/** Maximum length of an ESSID */
+#define IEEE80211_MAX_SSID_LEN 32
+
+/** @} */
+
+
+/* ---------- Frame Control defines ---------- */
+
+/**
+ * @defgroup ieee80211_fc 802.11 Frame Control field bits
+ * @{
+ */
+
+/** 802.11 Frame Control field, Version bitmask */
+#define IEEE80211_FC_VERSION 0x0003
+
+/** Expected value of Version bits in Frame Control */
+#define IEEE80211_THIS_VERSION 0x0000
+
+
+/** 802.11 Frame Control field, Frame Type bitmask */
+#define IEEE80211_FC_TYPE 0x000C
+
+/** Type value for management (layer-2) frames */
+#define IEEE80211_TYPE_MGMT 0x0000
+
+/** Type value for control (layer-1, hardware-managed) frames */
+#define IEEE80211_TYPE_CTRL 0x0004
+
+/** Type value for data frames */
+#define IEEE80211_TYPE_DATA 0x0008
+
+
+/** 802.11 Frame Control field, Frame Subtype bitmask */
+#define IEEE80211_FC_SUBTYPE 0x00F0
+
+/** Subtype value for association-request management frames
+ *
+ * Association request frames are sent after authentication from the
+ * client to the Access Point to establish the client as part of the
+ * Access Point's network.
+ */
+#define IEEE80211_STYPE_ASSOC_REQ 0x0000
+
+/** Subtype value for association-response management frames
+ *
+ * Association response frames are sent by the Access Point to confirm
+ * or deny the association requested in an association request frame.
+ */
+#define IEEE80211_STYPE_ASSOC_RESP 0x0010
+
+/** Subtype value for reassociation-request management frames
+ *
+ * Reassociation request frames are sent by clients wishing to change
+ * from one Access Point to another while roaming within the same
+ * extended network (same ESSID).
+ */
+#define IEEE80211_STYPE_REASSOC_REQ 0x0020
+
+/** Subtype value for reassociation-response management frames
+ *
+ * Reassociation response frames are sent by the Access Point to
+ * confirm or deny the swap requested in a reassociation request
+ * frame.
+ */
+#define IEEE80211_STYPE_REASSOC_RESP 0x0030
+
+/** Subtype value for probe-request management frames
+ *
+ * Probe request frames are sent by clients to request that all Access
+ * Points on the sending channel, or all belonging to a particular
+ * ESSID, identify themselves by BSSID, supported transfer rates, RF
+ * configuration, and other capabilities.
+ */
+#define IEEE80211_STYPE_PROBE_REQ 0x0040
+
+/** Subtype value for probe-response management frames
+ *
+ * Probe response frames are sent by Access Points in response to
+ * probe request frames, providing the requested information.
+ */
+#define IEEE80211_STYPE_PROBE_RESP 0x0050
+
+/** Subtype value for beacon management frames
+ *
+ * Beacon frames are sent by Access Points at regular intervals,
+ * usually ten per second, on the channel on which they communicate.
+ * They can be used to probe passively for access points on a channel
+ * where local regulatory restrictions prohibit active scanning, or
+ * due to their regularity as a mechanism to determine the fraction of
+ * packets that are being dropped.
+ */
+#define IEEE80211_STYPE_BEACON 0x0080
+
+/** Subtype value for disassociation management frames
+ *
+ * Disassociation frames are sent by either a client or an Access
+ * Point to unequivocally terminate the association between the two.
+ * They may be sent by clients upon leaving the network, or by an
+ * Access Point upon reconfiguration, among other reasons; they are
+ * usually more "polite" than deauthentication frames.
+ */
+#define IEEE80211_STYPE_DISASSOC 0x00A0
+
+/** Subtype value for authentication management frames
+ *
+ * Authentication frames are exchanged between a client and an Access
+ * Point before association may be performed. Confusingly, in the most
+ * common authentication method (Open System) no security tokens are
+ * exchanged at all. Modern 802.11 security handshaking takes place
+ * after association.
+ */
+#define IEEE80211_STYPE_AUTH 0x00B0
+
+/** Subtype value for deauthentication management frames
+ *
+ * Deauthentication frames are sent by either a client or an Access
+ * Point to terminate the authentication (and therefore also the
+ * association) between the two. They are generally more forceful than
+ * disassociation frames, sent for such reasons as a failure to
+ * set up security properly after associating.
+ */
+#define IEEE80211_STYPE_DEAUTH 0x00C0
+
+/** Subtype value for action management frames
+ *
+ * Action frames are used to implement spectrum management and QoS
+ * features that gPXE currently does not support.
+ */
+#define IEEE80211_STYPE_ACTION 0x00D0
+
+
+/** Subtype value for RTS (request to send) control frames */
+#define IEEE80211_STYPE_RTS 0x00B0
+
+/** Subtype value for CTS (clear to send) control frames */
+#define IEEE80211_STYPE_CTS 0x00C0
+
+/** Subtype value for ACK (acknowledgement) control frames */
+#define IEEE80211_STYPE_ACK 0x00D0
+
+
+/** Subtype value for ordinary data frames, with no QoS or CF add-ons */
+#define IEEE80211_STYPE_DATA 0x0000
+
+/** Subtype value for data frames containing no data */
+#define IEEE80211_STYPE_NODATA 0x0040
+
+
+/** 802.11 Frame Control field: To Data System flag
+ *
+ * This is set on data frames sent to an Access Point.
+ */
+#define IEEE80211_FC_TODS 0x0100
+
+/** 802.11 Frame Control field: From Data System flag
+ *
+ * This is set on data frames sent from an Access Point. If both TODS
+ * and FROMDS are set, the frame header is a 4-address format used for
+ * inter-Access Point communication.
+ */
+#define IEEE80211_FC_FROMDS 0x0200
+
+/** 802.11 Frame Control field: More Fragments flag */
+#define IEEE80211_FC_MORE_FRAG 0x0400
+
+/** 802.11 Frame Control field: Retransmission flag */
+#define IEEE80211_FC_RETRY 0x0800
+
+/** 802.11 Frame Control field: Power Managed flag
+ *
+ * This is set on any frame sent by a low-power station that will go
+ * into a power-saving mode immediately after this frame. Access
+ * Points are not allowed to act as low-power stations.
+ */
+#define IEEE80211_FC_PWR_MGMT 0x1000
+
+/** 802.11 Frame Control field: More Data flag
+ *
+ * This is set on any frame sent by a station that has more data
+ * queued to be sent than is in the frame.
+ */
+#define IEEE80211_FC_MORE_DATA 0x2000
+
+/** 802.11 Frame Control field: Protected flag
+ *
+ * This is set on frames in which data is encrypted (by any method).
+ */
+#define IEEE80211_FC_PROTECTED 0x4000
+
+/** 802.11 Frame Control field: Ordered flag [?] */
+#define IEEE80211_FC_ORDER 0x8000
+
+/** @} */
+
+
+/* ---------- Sequence Control defines ---------- */
+
+/**
+ * @defgroup ieee80211_seq 802.11 Sequence Control field handling
+ * @{
+ */
+
+/** Extract sequence number from 802.11 Sequence Control field */
+#define IEEE80211_SEQNR( seq ) ( ( seq ) >> 4 )
+
+/** Extract fragment number from 802.11 Sequence Control field */
+#define IEEE80211_FRAG( seq ) ( ( seq ) & 0x000F )
+
+/** Make 802.11 Sequence Control field from sequence and fragment numbers */
+#define IEEE80211_MAKESEQ( seqnr, frag ) \
+ ( ( ( ( seqnr ) & 0xFFF ) << 4 ) | ( ( frag ) & 0xF ) )
+
+/** @} */
+
+
+/* ---------- Frame header formats ---------- */
+
+/**
+ * @defgroup ieee80211_hdr 802.11 frame header formats
+ * @{
+ */
+
+/** An 802.11 data or management frame without QoS or WDS header fields */
+struct ieee80211_frame
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+ u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */
+ u8 addr3[ETH_ALEN]; /**< Address 3 (often "forward to") */
+ u16 seq; /**< 802.11 Sequence Control field */
+ u8 data[0]; /**< Beginning of frame data */
+} __attribute__((packed));
+
+/** The 802.2 LLC/SNAP header sent before actual data in a data frame
+ *
+ * This header is not acknowledged in the 802.11 standard at all; it
+ * is treated just like data for MAC-layer purposes, including
+ * fragmentation and encryption. It is actually two headers
+ * concatenated: a three-byte 802.2 LLC header indicating Subnetwork
+ * Accesss Protocol (SNAP) in both source and destination Service
+ * Access Point (SAP) fields, and a five-byte SNAP header indicating a
+ * zero OUI and two-byte Ethernet protocol type field.
+ *
+ * Thus, an eight-byte header in which six of the bytes are redundant.
+ * Lovely, isn't it?
+ */
+struct ieee80211_llc_snap_header
+{
+ /* LLC part: */
+ u8 dsap; /**< Destination SAP ID */
+ u8 ssap; /**< Source SAP ID */
+ u8 ctrl; /**< Control information */
+
+ /* SNAP part: */
+ u8 oui[3]; /**< Organization code, usually 0 */
+ u16 ethertype; /**< Ethernet Type field */
+} __attribute__((packed));
+
+/** Value for DSAP field in 802.2 LLC header for 802.11 frames: SNAP */
+#define IEEE80211_LLC_DSAP 0xAA
+
+/** Value for SSAP field in 802.2 LLC header for 802.11 frames: SNAP */
+#define IEEE80211_LLC_SSAP 0xAA
+
+/** Value for control field in 802.2 LLC header for 802.11 frames
+ *
+ * "Unnumbered Information".
+ */
+#define IEEE80211_LLC_CTRL 0x03
+
+
+/** 16-byte RTS frame format, with abbreviated header */
+struct ieee80211_rts
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+ u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */
+} __attribute__((packed));
+
+/** Length of 802.11 RTS control frame */
+#define IEEE80211_RTS_LEN 16
+
+/** 10-byte CTS or ACK frame format, with abbreviated header */
+struct ieee80211_cts_or_ack
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+} __attribute__((packed));
+
+#define ieee80211_cts ieee80211_cts_or_ack
+#define ieee80211_ack ieee80211_cts_or_ack
+
+/** Length of 802.11 CTS control frame */
+#define IEEE80211_CTS_LEN 10
+
+/** Length of 802.11 ACK control frame */
+#define IEEE80211_ACK_LEN 10
+
+/** @} */
+
+
+/* ---------- Capability bits, status and reason codes ---------- */
+
+/**
+ * @defgroup ieee80211_capab 802.11 management frame capability field bits
+ * @{
+ */
+
+/** Set if using an Access Point (managed mode) */
+#define IEEE80211_CAPAB_MANAGED 0x0001
+
+/** Set if operating in IBSS (no-AP, "Ad-Hoc") mode */
+#define IEEE80211_CAPAB_ADHOC 0x0002
+
+/** Set if we support Contention-Free Period operation */
+#define IEEE80211_CAPAB_CFPOLL 0x0004
+
+/** Set if we wish to be polled for Contention-Free operation */
+#define IEEE80211_CAPAB_CFPR 0x0008
+
+/** Set if the network is encrypted (by any method) */
+#define IEEE80211_CAPAB_PRIVACY 0x0010
+
+/** Set if PHY supports short preambles on 802.11b */
+#define IEEE80211_CAPAB_SHORT_PMBL 0x0020
+
+/** Set if PHY supports PBCC modulation */
+#define IEEE80211_CAPAB_PBCC 0x0040
+
+/** Set if we support Channel Agility */
+#define IEEE80211_CAPAB_CHAN_AGILITY 0x0080
+
+/** Set if we support spectrum management (DFS and TPC) on the 5GHz band */
+#define IEEE80211_CAPAB_SPECTRUM_MGMT 0x0100
+
+/** Set if we support Quality of Service enhancements */
+#define IEEE80211_CAPAB_QOS 0x0200
+
+/** Set if PHY supports short slot time on 802.11g */
+#define IEEE80211_CAPAB_SHORT_SLOT 0x0400
+
+/** Set if PHY supports APSD option */
+#define IEEE80211_CAPAB_APSD 0x0800
+
+/** Set if PHY supports DSSS/OFDM modulation (one way of 802.11 b/g mixing) */
+#define IEEE80211_CAPAB_DSSS_OFDM 0x2000
+
+/** Set if we support delayed block ACK */
+#define IEEE80211_CAPAB_DELAYED_BACK 0x4000
+
+/** Set if we support immediate block ACK */
+#define IEEE80211_CAPAB_IMMED_BACK 0x8000
+
+/** @} */
+
+
+/**
+ * @defgroup ieee80211_status 802.11 status codes
+ *
+ * These are returned to indicate an immediate denial of
+ * authentication or association. In gPXE, the lower 5 bits of the
+ * status code are encoded into the file-unique portion of an error
+ * code, the ERRFILE portion is always @c ERRFILE_net80211, and the
+ * POSIX error code is @c ECONNREFUSED for status 0-31 or @c
+ * EHOSTUNREACH for status 32-63.
+ *
+ * For a complete table with non-abbreviated error messages, see IEEE
+ * Std 802.11-2007, Table 7-23, p.94.
+ *
+ * @{
+ */
+
+#define IEEE80211_STATUS_SUCCESS 0
+#define IEEE80211_STATUS_FAILURE 1
+#define IEEE80211_STATUS_CAPAB_UNSUPP 10
+#define IEEE80211_STATUS_REASSOC_INVALID 11
+#define IEEE80211_STATUS_ASSOC_DENIED 12
+#define IEEE80211_STATUS_AUTH_ALGO_UNSUPP 13
+#define IEEE80211_STATUS_AUTH_SEQ_INVALID 14
+#define IEEE80211_STATUS_AUTH_CHALL_INVALID 15
+#define IEEE80211_STATUS_AUTH_TIMEOUT 16
+#define IEEE80211_STATUS_ASSOC_NO_ROOM 17
+#define IEEE80211_STATUS_ASSOC_NEED_RATE 18
+#define IEEE80211_STATUS_ASSOC_NEED_SHORT_PMBL 19
+#define IEEE80211_STATUS_ASSOC_NEED_PBCC 20
+#define IEEE80211_STATUS_ASSOC_NEED_CHAN_AGILITY 21
+#define IEEE80211_STATUS_ASSOC_NEED_SPECTRUM_MGMT 22
+#define IEEE80211_STATUS_ASSOC_BAD_POWER 23
+#define IEEE80211_STATUS_ASSOC_BAD_CHANNELS 24
+#define IEEE80211_STATUS_ASSOC_NEED_SHORT_SLOT 25
+#define IEEE80211_STATUS_ASSOC_NEED_DSSS_OFDM 26
+#define IEEE80211_STATUS_QOS_FAILURE 32
+#define IEEE80211_STATUS_QOS_NO_ROOM 33
+#define IEEE80211_STATUS_LINK_IS_HORRIBLE 34
+#define IEEE80211_STATUS_ASSOC_NEED_QOS 35
+#define IEEE80211_STATUS_REQUEST_DECLINED 37
+#define IEEE80211_STATUS_REQUEST_INVALID 38
+#define IEEE80211_STATUS_TS_NOT_CREATED_AGAIN 39
+#define IEEE80211_STATUS_INVALID_IE 40
+#define IEEE80211_STATUS_GROUP_CIPHER_INVALID 41
+#define IEEE80211_STATUS_PAIR_CIPHER_INVALID 42
+#define IEEE80211_STATUS_AKMP_INVALID 43
+#define IEEE80211_STATUS_RSN_VERSION_UNSUPP 44
+#define IEEE80211_STATUS_RSN_CAPAB_INVALID 45
+#define IEEE80211_STATUS_CIPHER_REJECTED 46
+#define IEEE80211_STATUS_TS_NOT_CREATED_WAIT 47
+#define IEEE80211_STATUS_DIRECT_LINK_FORBIDDEN 48
+#define IEEE80211_STATUS_DEST_NOT_PRESENT 49
+#define IEEE80211_STATUS_DEST_NOT_QOS 50
+#define IEEE80211_STATUS_ASSOC_LISTEN_TOO_HIGH 51
+
+/** @} */
+
+
+
+/**
+ * @defgroup ieee80211_reason 802.11 reason codes
+ *
+ * These are returned to indicate the reason for a deauthentication or
+ * disassociation sent (usually) after authentication or association
+ * had succeeded. In gPXE, the lower 5 bits of the reason code are
+ * encoded into the file-unique portion of an error code, the ERRFILE
+ * portion is always @c ERRFILE_net80211, and the POSIX error code is
+ * @c ECONNRESET for reason 0-31 or @c ENETRESET for reason 32-63.
+ *
+ * For a complete table with non-abbreviated error messages, see IEEE
+ * Std 802.11-2007, Table 7-22, p.92.
+ *
+ * @{
+ */
+
+#define IEEE80211_REASON_NONE 0
+#define IEEE80211_REASON_UNSPECIFIED 1
+#define IEEE80211_REASON_AUTH_NO_LONGER_VALID 2
+#define IEEE80211_REASON_LEAVING 3
+#define IEEE80211_REASON_INACTIVITY 4
+#define IEEE80211_REASON_OUT_OF_RESOURCES 5
+#define IEEE80211_REASON_NEED_AUTH 6
+#define IEEE80211_REASON_NEED_ASSOC 7
+#define IEEE80211_REASON_LEAVING_TO_ROAM 8
+#define IEEE80211_REASON_REASSOC_INVALID 9
+#define IEEE80211_REASON_BAD_POWER 10
+#define IEEE80211_REASON_BAD_CHANNELS 11
+#define IEEE80211_REASON_INVALID_IE 13
+#define IEEE80211_REASON_MIC_FAILURE 14
+#define IEEE80211_REASON_4WAY_TIMEOUT 15
+#define IEEE80211_REASON_GROUPKEY_TIMEOUT 16
+#define IEEE80211_REASON_4WAY_INVALID 17
+#define IEEE80211_REASON_GROUP_CIPHER_INVALID 18
+#define IEEE80211_REASON_PAIR_CIPHER_INVALID 19
+#define IEEE80211_REASON_AKMP_INVALID 20
+#define IEEE80211_REASON_RSN_VERSION_INVALID 21
+#define IEEE80211_REASON_RSN_CAPAB_INVALID 22
+#define IEEE80211_REASON_8021X_FAILURE 23
+#define IEEE80211_REASON_CIPHER_REJECTED 24
+#define IEEE80211_REASON_QOS_UNSPECIFIED 32
+#define IEEE80211_REASON_QOS_OUT_OF_RESOURCES 33
+#define IEEE80211_REASON_LINK_IS_HORRIBLE 34
+#define IEEE80211_REASON_INVALID_TXOP 35
+#define IEEE80211_REASON_REQUESTED_LEAVING 36
+#define IEEE80211_REASON_REQUESTED_NO_USE 37
+#define IEEE80211_REASON_REQUESTED_NEED_SETUP 38
+#define IEEE80211_REASON_REQUESTED_TIMEOUT 39
+#define IEEE80211_REASON_CIPHER_UNSUPPORTED 45
+
+/** @} */
+
+/* ---------- Information element declarations ---------- */
+
+/**
+ * @defgroup ieee80211_ie 802.11 information elements
+ *
+ * Many management frames include a section that amounts to a
+ * concatenation of these information elements, so that the sender can
+ * choose which information to send and the receiver can ignore the
+ * parts it doesn't understand. Each IE contains a two-byte header,
+ * one byte ID and one byte length, followed by IE-specific data. The
+ * length does not include the two-byte header. Information elements
+ * are required to be sorted by ID, but gPXE does not require that in
+ * those it receives.
+ *
+ * This group also includes a few inline functions to simplify common
+ * tasks in IE processing.
+ *
+ * @{
+ */
+
+/** Generic 802.11 information element header */
+struct ieee80211_ie_header {
+ u8 id; /**< Information element ID */
+ u8 len; /**< Information element length */
+} __attribute__ ((packed));
+
+
+/** 802.11 SSID information element */
+struct ieee80211_ie_ssid {
+ u8 id; /**< SSID ID: 0 */
+ u8 len; /**< SSID length */
+ char ssid[0]; /**< SSID data, not NUL-terminated */
+} __attribute__ ((packed));
+
+/** Information element ID for SSID information element */
+#define IEEE80211_IE_SSID 0
+
+
+/** 802.11 rates information element
+ *
+ * The first 8 rates go in an IE of type RATES (1), and any more rates
+ * go in one of type EXT_RATES (50). Each rate is a byte with the low
+ * 7 bits equal to the rate in units of 500 kbps, and the high bit set
+ * if and only if the rate is "basic" (must be supported by all
+ * connected stations).
+ */
+struct ieee80211_ie_rates {
+ u8 id; /**< Rates ID: 1 or 50 */
+ u8 len; /**< Number of rates */
+ u8 rates[0]; /**< Rates data, one rate per byte */
+} __attribute__ ((packed));
+
+/** Information element ID for rates information element */
+#define IEEE80211_IE_RATES 1
+
+/** Information element ID for extended rates information element */
+#define IEEE80211_IE_EXT_RATES 50
+
+
+/** 802.11 Direct Spectrum parameter information element
+ *
+ * This just contains the channel number. It has the fancy name
+ * because IEEE 802.11 also defines a frequency-hopping PHY that
+ * changes channels at regular intervals following a predetermined
+ * pattern; in practice nobody uses the FH PHY.
+ */
+struct ieee80211_ie_ds_param {
+ u8 id; /**< DS parameter ID: 3 */
+ u8 len; /**< DS parameter length: 1 */
+ u8 current_channel; /**< Current channel number, 1-14 */
+} __attribute__ ((packed));
+
+/** Information element ID for Direct Spectrum parameter information element */
+#define IEEE80211_IE_DS_PARAM 3
+
+
+/** 802.11 Country information element regulatory extension triplet */
+struct ieee80211_ie_country_ext_triplet {
+ u8 reg_ext_id; /**< Regulatory extension ID */
+ u8 reg_class_id; /**< Regulatory class ID */
+ u8 coverage_class; /**< Coverage class */
+} __attribute__ ((packed));
+
+/** 802.11 Country information element regulatory band triplet */
+struct ieee80211_ie_country_band_triplet {
+ u8 first_channel; /**< Channel number for first channel in band */
+ u8 nr_channels; /**< Number of contiguous channels in band */
+ u8 max_txpower; /**< Maximum TX power in dBm */
+} __attribute__ ((packed));
+
+/** 802.11 Country information element regulatory triplet
+ *
+ * It is a band triplet if the first byte is 200 or less, and a
+ * regulatory extension triplet otherwise.
+ */
+union ieee80211_ie_country_triplet {
+ /** Differentiator between band and ext triplets */
+ u8 first;
+
+ /** Information about a band of channels */
+ struct ieee80211_ie_country_band_triplet band;
+
+ /** Regulatory extension information */
+ struct ieee80211_ie_country_ext_triplet ext;
+};
+
+/** 802.11 Country information element
+ *
+ * This contains some data about RF regulations.
+ */
+struct ieee80211_ie_country {
+ u8 id; /**< Country information ID: 7 */
+ u8 len; /**< Country information length: varies */
+ char name[2]; /**< ISO Alpha2 country code */
+ char in_out; /**< 'I' for indoor, 'O' for outdoor */
+
+ /** List of regulatory triplets */
+ union ieee80211_ie_country_triplet triplet[0];
+} __attribute__ ((packed));
+
+/** Information element ID for Country information element */
+#define IEEE80211_IE_COUNTRY 7
+
+
+/** 802.11 Request information element
+ *
+ * This contains a list of information element types we would like to
+ * be included in probe response frames.
+ */
+struct ieee80211_ie_request {
+ u8 id; /**< Request ID: 10 */
+ u8 len; /**< Number of IEs requested */
+ u8 request[0]; /**< List of IEs requested */
+} __attribute__ ((packed));
+
+/** Information element ID for Request information element */
+#define IEEE80211_IE_REQUEST 10
+
+
+/** 802.11 Challenge Text information element
+ *
+ * This is used in authentication frames under Shared Key
+ * authentication.
+ */
+struct ieee80211_ie_challenge_text {
+ u8 id; /**< Challenge Text ID: 16 */
+ u8 len; /**< Challenge Text length: usually 128 */
+ u8 challenge_text[0]; /**< Challenge Text data */
+} __attribute__ ((packed));
+
+/** Information element ID for Challenge Text information element */
+#define IEEE80211_IE_CHALLENGE_TEXT 16
+
+
+/** 802.11 Power Constraint information element
+ *
+ * This is used to specify an additional power limitation on top of
+ * the Country requirements.
+ */
+struct ieee80211_ie_power_constraint {
+ u8 id; /**< Power Constraint ID: 52 */
+ u8 len; /**< Power Constraint length: 1 */
+ u8 power_constraint; /**< Decrease in allowed TX power, dBm */
+} __attribute__ ((packed));
+
+/** Information element ID for Power Constraint information element */
+#define IEEE80211_IE_POWER_CONSTRAINT 52
+
+
+/** 802.11 Power Capability information element
+ *
+ * This is used in association request frames to indicate the extremes
+ * of our TX power abilities. It is required only if we indicate
+ * support for spectrum management.
+ */
+struct ieee80211_ie_power_capab {
+ u8 id; /**< Power Capability ID: 33 */
+ u8 len; /**< Power Capability length: 2 */
+ u8 min_txpower; /**< Minimum possible TX power, dBm */
+ u8 max_txpower; /**< Maximum possible TX power, dBm */
+} __attribute__ ((packed));
+
+/** Information element ID for Power Capability information element */
+#define IEEE80211_IE_POWER_CAPAB 33
+
+
+/** 802.11 Channels information element channel band tuple */
+struct ieee80211_ie_channels_channel_band {
+ u8 first_channel; /**< Channel number of first channel in band */
+ u8 nr_channels; /**< Number of channels in band */
+} __attribute__ ((packed));
+
+/** 802.11 Channels information element
+ *
+ * This is used in association frames to indicate the channels we can
+ * use. It is required only if we indicate support for spectrum
+ * management.
+ */
+struct ieee80211_ie_channels {
+ u8 id; /**< Channels ID: 36 */
+ u8 len; /**< Channels length: 2 */
+
+ /** List of (start, length) channel bands we can use */
+ struct ieee80211_ie_channels_channel_band channels[0];
+} __attribute__ ((packed));
+
+/** Information element ID for Channels information element */
+#define IEEE80211_IE_CHANNELS 36
+
+
+/** 802.11 ERP Information information element
+ *
+ * This is used to communicate some PHY-level flags.
+ */
+struct ieee80211_ie_erp_info {
+ u8 id; /**< ERP Information ID: 42 */
+ u8 len; /**< ERP Information length: 1 */
+ u8 erp_info; /**< ERP flags */
+} __attribute__ ((packed));
+
+/** Information element ID for ERP Information information element */
+#define IEEE80211_IE_ERP_INFO 42
+
+/** ERP information element: Flag set if 802.11b stations are present */
+#define IEEE80211_ERP_NONERP_PRESENT 0x01
+
+/** ERP information element: Flag set if CTS protection must be used */
+#define IEEE80211_ERP_USE_PROTECTION 0x02
+
+/** ERP information element: Flag set if long preambles must be used */
+#define IEEE80211_ERP_BARKER_LONG 0x04
+
+
+/** 802.11 Robust Security Network ("WPA") information element
+ *
+ * Showing once again a striking clarity of design, the IEEE folks put
+ * dynamically-sized data in the middle of this structure. As such,
+ * the below structure definition is only a guideline; the
+ * @c IEEE80211_RSN_FIELD, @c IEEE80211_RSN_CIPHER, and
+ * @c IEEE80211_RSN_AUTHTYPE macros should be used to access any
+ * data.
+ *
+ * Also inspired was IEEE's choice of 16-bit fields to count the
+ * number of 4-byte elements in a structure with a maximum length of
+ * 255 bytes.
+ *
+ * Many fields reference a cipher or authentication-type ID; this is a
+ * three-byte OUI followed by one byte identifying the cipher with
+ * respect to that OUI. For all standard ciphers the OUI is 00:0F:AC.
+ *
+ * The authentication types referenced in this structure have nothing
+ * to do with 802.11 authentication frames or the @c algorithm field
+ * within them.
+ */
+struct ieee80211_ie_rsn {
+ /** Information element ID */
+ u8 id;
+
+ /** Information element length */
+ u8 len;
+
+ /** RSN information element version */
+ u16 version;
+
+ /** Cipher ID for the cipher used in multicast/broadcast frames */
+ u8 group_cipher[4];
+
+ /** Number of unicast ciphers supported */
+ u16 pairwise_count;
+
+ /** List of cipher IDs for supported unicast frame ciphers */
+ u8 pairwise_cipher[4];
+
+ /** Number of authentication types supported */
+ u16 akm_count;
+
+ /** List of authentication type IDs for supported types */
+ u8 akm_list[4];
+
+ /** Security capabilities field. */
+ u16 rsn_capab;
+
+ /** Number of PMKIDs included (present only in association frames) */
+ u16 pmkid_count;
+
+ /** List of PMKIDs included, each a 16-byte SHA1 hash */
+ u8 pmkid_list[0];
+} __attribute__((packed));
+
+/** Information element ID for Robust Security Network information element */
+#define IEEE80211_IE_RSN 48
+
+/** OUI for standard ciphers in RSN information element */
+#define IEEE80211_RSN_OUI "\x00\x0F\xAC"
+
+/** Extract RSN IE version field */
+#define IEEE80211_RSN_FIELD_version( rsnp ) ( (rsnp)->version )
+
+/** Extract RSN IE group_cipher field */
+#define IEEE80211_RSN_FIELD_group_cipher( rsnp ) ( (rsnp)->group_cipher )
+
+/** Extract RSN IE pairwise_count field */
+#define IEEE80211_RSN_FIELD_pairwise_count( rsnp ) ( (rsnp)->pairwise_count )
+
+/** Extract RSN IE akm_count field */
+#define IEEE80211_RSN_FIELD_akm_count( rsnp ) \
+ ( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
+ 4*( ( rsnp )->pairwise_count - 1 ) ) )->akm_count )
+
+/** Extract RSN IE rsn_capab field */
+#define IEEE80211_RSN_FIELD_rsn_capab( rsnp ) \
+ ( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
+ 4*( ( rsnp )->pairwise_count - 1 ) + \
+ 4*( ( rsnp )->akm_count - 1 ) ) )->rsn_capab )
+
+/** Extract RSN IE pmkid_count field */
+#define IEEE80211_RSN_FIELD_pmkid_count( rsnp ) \
+ ( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
+ 4*( ( rsnp )->pairwise_count - 1 ) + \
+ 4*( ( rsnp )->akm_count - 1 ) ) )->pmkid_count )
+
+/** Extract field from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v field Name of field to extract
+ * @ret val Lvalue of the requested field
+ *
+ * You must fill the fields of the structure in order for this to work
+ * properly.
+ */
+#define IEEE80211_RSN_FIELD( rsnp, field ) \
+ IEEE80211_RSN_FIELD_ ## field ( rsnp )
+
+/** Get pointer to pairwise cipher from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v cipher Index of pairwise cipher to extract
+ * @ret ptr Pointer to requested cipher
+ */
+#define IEEE80211_RSN_CIPHER( rsnp, cipher ) \
+ ( ( rsnp )->pairwise_cipher + 4 * ( cipher ) )
+
+/** Get pointer to authentication type from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v akm Index of authentication type to extract
+ * @ret ptr Pointer to requested authentication type
+ *
+ * The @c pairwise_count field must be correct.
+ */
+#define IEEE80211_RSN_AUTHTYPE( rsnp, akm ) \
+ ( ( rsnp )->akm_list + 4 * ( ( rsnp )->pairwise_count - 1 ) + 4 * ( akm ) )
+
+/** Get pointer to PMKID from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v idx Index of PMKID to extract
+ * @ret ptr Pointer to requested PMKID
+ *
+ * The @c pairwise_count and @c akm_count fields must be correct.
+ */
+#define IEEE80211_RSN_PMKID( rsnp, idx ) \
+ ( ( rsnp )->pmkid_list + 4 * ( ( rsnp )->pairwise_count - 1 ) + \
+ 4 * ( ( rsnp )->akm_count - 1 ) + 16 * ( idx ) )
+
+/** Verify size of RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @ret ok TRUE if count fields are consistent with length field
+ *
+ * It is important to drop any RSN IE that does not pass this function
+ * before using the @c IEEE80211_RSN_FIELD, @c IEEE80211_RSN_CIPHER,
+ * and @c IEEE80211_RSN_AUTHTYPE macros, to avoid potential security
+ * compromise due to a malformed RSN IE.
+ *
+ * This function does not consider the possibility of some PMKIDs
+ * included in the RSN IE, because PMKIDs are only included in RSN IEs
+ * sent in association request frames, and we should never receive an
+ * association request frame. An RSN IE that includes PMKIDs will
+ * always fail this check.
+ */
+static inline int ieee80211_rsn_check ( struct ieee80211_ie_rsn *rsnp ) {
+ if ( rsnp->len < 12 + 4 * rsnp->pairwise_count )
+ return 0;
+ return ( rsnp->len == 12 + 4 * ( rsnp->pairwise_count +
+ IEEE80211_RSN_FIELD ( rsnp, akm_count ) ) );
+}
+
+/** Calculate necessary size of RSN information element
+ *
+ * @v npair Number of pairwise ciphers supported
+ * @v nauth Number of authentication types supported
+ * @v npmkid Number of PMKIDs to include
+ * @ret size Necessary size of RSN IE, including header bytes
+ */
+static inline size_t ieee80211_rsn_size ( int npair, int nauth, int npmkid ) {
+ return 16 + 4 * ( npair + nauth ) + 16 * npmkid;
+}
+
+/** 802.11 RSN IE: expected version number */
+#define IEEE80211_RSN_VERSION 1
+
+/** 802.11 RSN IE: fourth byte of cipher type for 40-bit WEP */
+#define IEEE80211_RSN_CTYPE_WEP40 1
+
+/** 802.11 RSN IE: fourth byte of cipher type for 104-bit WEP */
+#define IEEE80211_RSN_CTYPE_WEP104 5
+
+/** 802.11 RSN IE: fourth byte of cipher type for TKIP ("WPA") */
+#define IEEE80211_RSN_CTYPE_TKIP 2
+
+/** 802.11 RSN IE: fourth byte of cipher type for CCMP ("WPA2") */
+#define IEEE80211_RSN_CTYPE_CCMP 4
+
+/** 802.11 RSN IE: fourth byte of cipher type for "use group"
+ *
+ * This can only appear as a pairwise cipher, and means unicast frames
+ * should be encrypted in the same way as broadcast/multicast frames.
+ */
+#define IEEE80211_RSN_CTYPE_USEGROUP 0
+
+/** 802.11 RSN IE: fourth byte of auth method type for using an 802.1X server */
+#define IEEE80211_RSN_ATYPE_8021X 1
+
+/** 802.11 RSN IE: fourth byte of auth method type for using a pre-shared key */
+#define IEEE80211_RSN_ATYPE_PSK 2
+
+/** 802.11 RSN IE capabilities: AP supports pre-authentication */
+#define IEEE80211_RSN_CAPAB_PREAUTH 0x001
+
+/** 802.11 RSN IE capabilities: Node has conflict between TKIP and WEP
+ *
+ * This is a legacy issue; APs always set it to 0, and gPXE sets it to
+ * 0.
+ */
+#define IEEE80211_RSN_CAPAB_NO_PAIRWISE 0x002
+
+/** 802.11 RSN IE capabilities: Number of PTKSA replay counters
+ *
+ * A value of 0 means one replay counter, 1 means two, 2 means four,
+ * and 3 means sixteen.
+ */
+#define IEEE80211_RSN_CAPAB_PTKSA_REPLAY 0x00C
+
+/** 802.11 RSN IE capabilities: Number of GTKSA replay counters
+ *
+ * A value of 0 means one replay counter, 1 means two, 2 means four,
+ * and 3 means sixteen.
+ */
+#define IEEE80211_RSN_CAPAB_GTKSA_REPLAY 0x030
+
+/** 802.11 RSN IE capabilities: PeerKey Handshaking is suported */
+#define IEEE80211_RSN_CAPAB_PEERKEY 0x200
+
+
+
+/** Any 802.11 information element
+ *
+ * This is formatted for ease of use, so IEs with complex structures
+ * get referenced in full, while those with only one byte of data or a
+ * simple array are pulled in to avoid a layer of indirection like
+ * ie->channels.channels[0].
+ */
+union ieee80211_ie
+{
+ /** Generic and simple information element info */
+ struct {
+ u8 id; /**< Information element ID */
+ u8 len; /**< Information element data length */
+ union {
+ char ssid[0]; /**< SSID text */
+ u8 rates[0]; /**< Rates data */
+ u8 request[0]; /**< Request list */
+ u8 challenge_text[0]; /**< Challenge text data */
+ u8 power_constraint; /**< Power constraint, dBm */
+ u8 erp_info; /**< ERP information flags */
+ /** List of channels */
+ struct ieee80211_ie_channels_channel_band channels[0];
+ };
+ };
+
+ /** DS parameter set */
+ struct ieee80211_ie_ds_param ds_param;
+
+ /** Country information */
+ struct ieee80211_ie_country country;
+
+ /** Power capability */
+ struct ieee80211_ie_power_capab power_capab;
+
+ /** Security information */
+ struct ieee80211_ie_rsn rsn;
+};
+
+/** Advance to next 802.11 information element
+ *
+ * @v ie Current information element pointer
+ * @v end Pointer to first byte not in information element space
+ * @ret next Pointer to next information element, or NULL if no more
+ *
+ * When processing received IEs, @a end should be set to the I/O
+ * buffer tail pointer; when marshalling IEs for sending, @a end
+ * should be NULL.
+ */
+static inline union ieee80211_ie * ieee80211_next_ie ( union ieee80211_ie *ie,
+ void *end )
+{
+ void *next_ie_byte = ( void * ) ie + ie->len + 2;
+ union ieee80211_ie *next_ie = next_ie_byte;
+
+ if ( ! end )
+ return next_ie;
+
+ if ( next_ie_byte < end && next_ie_byte + next_ie->len <= end )
+ return next_ie;
+
+ return NULL;
+}
+
+/** @} */
+
+
+/* ---------- Management frame data formats ---------- */
+
+/**
+ * @defgroup ieee80211_mgmt_data Management frame data payloads
+ * @{
+ */
+
+/** Beacon or probe response frame data */
+struct ieee80211_beacon_or_probe_resp
+{
+ /** 802.11 TSFT value at frame send */
+ u64 timestamp;
+
+ /** Interval at which beacons are sent, in units of 1024 us */
+ u16 beacon_interval;
+
+ /** Capability flags */
+ u16 capability;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+#define ieee80211_beacon ieee80211_beacon_or_probe_resp
+#define ieee80211_probe_resp ieee80211_beacon_or_probe_resp
+
+/** Disassociation or deauthentication frame data */
+struct ieee80211_disassoc_or_deauth
+{
+ /** Reason code */
+ u16 reason;
+} __attribute__((packed));
+
+#define ieee80211_disassoc ieee80211_disassoc_or_deauth
+#define ieee80211_deauth ieee80211_disassoc_or_deauth
+
+/** Association request frame data */
+struct ieee80211_assoc_req
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Interval at which we wake up, in units of the beacon interval */
+ u16 listen_interval;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Association or reassociation response frame data */
+struct ieee80211_assoc_or_reassoc_resp
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Status code */
+ u16 status;
+
+ /** Association ID */
+ u16 aid;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+#define ieee80211_assoc_resp ieee80211_assoc_or_reassoc_resp
+#define ieee80211_reassoc_resp ieee80211_assoc_or_reassoc_resp
+
+/** Reassociation request frame data */
+struct ieee80211_reassoc_req
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Interval at which we wake up, in units of the beacon interval */
+ u16 listen_interval;
+
+ /** MAC address of current Access Point */
+ u8 current_addr[ETH_ALEN];
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Probe request frame data */
+struct ieee80211_probe_req
+{
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Authentication frame data */
+struct ieee80211_auth
+{
+ /** Authentication algorithm (Open System or Shared Key) */
+ u16 algorithm;
+
+ /** Sequence number of this frame; first from client to AP is 1 */
+ u16 tx_seq;
+
+ /** Status code */
+ u16 status;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Open System authentication algorithm */
+#define IEEE80211_AUTH_OPEN_SYSTEM 0
+
+/** Shared Key authentication algorithm */
+#define IEEE80211_AUTH_SHARED_KEY 1
+
+/** @} */
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/if_arp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/if_arp.h
new file mode 100644
index 0000000..932bb3b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/if_arp.h
@@ -0,0 +1,102 @@
+#ifndef _GPXE_IF_ARP_H
+#define _GPXE_IF_ARP_H
+
+/** @file
+ *
+ * Address Resolution Protocol constants and types
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/* ARP protocol HARDWARE identifiers. */
+#define ARPHRD_NETROM 0 /**< from KA9Q: NET/ROM pseudo */
+#define ARPHRD_ETHER 1 /**< Ethernet 10Mbps */
+#define ARPHRD_EETHER 2 /**< Experimental Ethernet */
+#define ARPHRD_AX25 3 /**< AX.25 Level 2 */
+#define ARPHRD_PRONET 4 /**< PROnet token ring */
+#define ARPHRD_CHAOS 5 /**< Chaosnet */
+#define ARPHRD_IEEE802 6 /**< IEEE 802.2 Ethernet/TR/TB */
+#define ARPHRD_ARCNET 7 /**< ARCnet */
+#define ARPHRD_APPLETLK 8 /**< APPLEtalk */
+#define ARPHRD_DLCI 15 /**< Frame Relay DLCI */
+#define ARPHRD_ATM 19 /**< ATM */
+#define ARPHRD_METRICOM 23 /**< Metricom STRIP (new IANA id) */
+#define ARPHRD_IEEE1394 24 /**< IEEE 1394 IPv4 - RFC 2734 */
+#define ARPHRD_EUI64 27 /**< EUI-64 */
+#define ARPHRD_INFINIBAND 32 /**< InfiniBand */
+
+/* ARP protocol opcodes. */
+#define ARPOP_REQUEST 1 /**< ARP request */
+#define ARPOP_REPLY 2 /**< ARP reply */
+#define ARPOP_RREQUEST 3 /**< RARP request */
+#define ARPOP_RREPLY 4 /**< RARP reply */
+#define ARPOP_InREQUEST 8 /**< InARP request */
+#define ARPOP_InREPLY 9 /**< InARP reply */
+#define ARPOP_NAK 10 /**< (ATM)ARP NAK */
+
+/**
+ * An ARP header
+ *
+ * This contains only the fixed-size portions of an ARP header; for
+ * other fields use the arp_{sender,target}_{ha,pa} family of
+ * functions.
+ */
+struct arphdr {
+ /** Link-layer protocol
+ *
+ * This is an ARPHRD_XXX constant
+ */
+ uint16_t ar_hrd;
+ /** Network-layer protocol
+ *
+ * This is, for Ethernet, an ETH_P_XXX constant.
+ */
+ uint16_t ar_pro;
+ /** Link-layer address length */
+ uint8_t ar_hln;
+ /** Network-layer address length */
+ uint8_t ar_pln;
+ /** ARP opcode */
+ uint16_t ar_op;
+} __attribute__ (( packed ));
+
+/** ARP packet sender hardware address
+ *
+ * @v arphdr ARP header
+ * @ret ar_sha Sender hardware address
+ */
+static inline void * arp_sender_ha ( struct arphdr *arphdr ) {
+ return ( ( ( void * ) arphdr ) + sizeof ( *arphdr ) );
+}
+
+/** ARP packet sender protocol address
+ *
+ * @v arphdr ARP header
+ * @ret ar_spa Sender protocol address
+ */
+static inline void * arp_sender_pa ( struct arphdr *arphdr ) {
+ return ( arp_sender_ha ( arphdr ) + arphdr->ar_hln );
+}
+
+/** ARP packet target hardware address
+ *
+ * @v arphdr ARP header
+ * @ret ar_tha Target hardware address
+ */
+static inline void * arp_target_ha ( struct arphdr *arphdr ) {
+ return ( arp_sender_pa ( arphdr ) + arphdr->ar_pln );
+}
+
+/** ARP packet target protocol address
+ *
+ * @v arphdr ARP header
+ * @ret ar_tpa Target protocol address
+ */
+static inline void * arp_target_pa ( struct arphdr *arphdr ) {
+ return ( arp_target_ha ( arphdr ) + arphdr->ar_hln );
+}
+
+#endif /* _GPXE_IF_ARP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/if_ether.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/if_ether.h
new file mode 100644
index 0000000..57f8e12
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/if_ether.h
@@ -0,0 +1,35 @@
+#ifndef _GPXE_IF_ETHER_H
+#define _GPXE_IF_ETHER_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+#define ETH_ALEN 6 /* Size of Ethernet address */
+#define ETH_HLEN 14 /* Size of ethernet header */
+#define ETH_ZLEN 60 /* Minimum packet */
+#define ETH_FRAME_LEN 1514 /* Maximum packet */
+#define ETH_DATA_ALIGN 2 /* Amount needed to align the data after an ethernet header */
+#ifndef ETH_MAX_MTU
+#define ETH_MAX_MTU (ETH_FRAME_LEN-ETH_HLEN)
+#endif
+
+#define ETH_P_RAW 0x0000 /* Raw packet */
+#define ETH_P_IP 0x0800 /* Internet Protocl Packet */
+#define ETH_P_ARP 0x0806 /* Address Resolution Protocol */
+#define ETH_P_RARP 0x8035 /* Reverse Address resolution Protocol */
+#define ETH_P_IPV6 0x86DD /* IPv6 over blueblook */
+#define ETH_P_SLOW 0x8809 /* Ethernet slow protocols */
+#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
+
+/** An Ethernet link-layer header */
+struct ethhdr {
+ /** Destination MAC address */
+ uint8_t h_dest[ETH_ALEN];
+ /** Source MAC address */
+ uint8_t h_source[ETH_ALEN];
+ /** Protocol ID */
+ uint16_t h_protocol;
+} __attribute__ ((packed));
+
+#endif /* _GPXE_IF_ETHER_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/image.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/image.h
new file mode 100644
index 0000000..10db8af
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/image.h
@@ -0,0 +1,194 @@
+#ifndef _GPXE_IMAGE_H
+#define _GPXE_IMAGE_H
+
+/**
+ * @file
+ *
+ * Executable/loadable images
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tables.h>
+#include <gpxe/list.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
+
+struct uri;
+struct image_type;
+
+/** An executable or loadable image */
+struct image {
+ /** Reference count */
+ struct refcnt refcnt;
+
+ /** List of registered images */
+ struct list_head list;
+
+ /** URI of image */
+ struct uri *uri;
+ /** Name */
+ char name[16];
+ /** Flags */
+ unsigned int flags;
+
+ /** Command line to pass to image */
+ char *cmdline;
+ /** Raw file image */
+ userptr_t data;
+ /** Length of raw file image */
+ size_t len;
+
+ /** Image type, if known */
+ struct image_type *type;
+ /** Image type private data */
+ union {
+ physaddr_t phys;
+ userptr_t user;
+ unsigned long ul;
+ } priv;
+
+ /** Replacement image
+ *
+ * An image wishing to replace itself with another image (in a
+ * style similar to a Unix exec() call) should return from its
+ * exec() method with the replacement image set to point to
+ * the new image. The new image must already be in a suitable
+ * state for execution (i.e. loaded).
+ *
+ * If an image unregisters itself as a result of being
+ * executed, it must make sure that its replacement image (if
+ * any) is registered, otherwise the replacement is likely to
+ * be freed before it can be executed.
+ */
+ struct image *replacement;
+};
+
+/** Image is loaded */
+#define IMAGE_LOADED 0x0001
+
+/** An executable or loadable image type */
+struct image_type {
+ /** Name of this image type */
+ char *name;
+ /**
+ * Load image into memory
+ *
+ * @v image Executable/loadable image
+ * @ret rc Return status code
+ *
+ * Load the image into memory at the correct location as
+ * determined by the file format.
+ *
+ * If the file image is in the correct format, the method must
+ * update @c image->type to point to its own type (unless @c
+ * image->type is already set). This allows the autoloading
+ * code to disambiguate between "this is not my image format"
+ * and "there is something wrong with this image". In
+ * particular, setting @c image->type and then returning an
+ * error will cause image_autoload() to abort and return an
+ * error, rather than continuing to the next image type.
+ */
+ int ( * load ) ( struct image *image );
+ /**
+ * Execute loaded image
+ *
+ * @v image Loaded image
+ * @ret rc Return status code
+ *
+ * Note that the image may be invalidated by the act of
+ * execution, i.e. an image is allowed to choose to unregister
+ * (and so potentially free) itself.
+ */
+ int ( * exec ) ( struct image *image );
+};
+
+/**
+ * Multiboot image probe priority
+ *
+ * Multiboot images are also valid executables in another format
+ * (e.g. ELF), so we must perform the multiboot probe first.
+ */
+#define PROBE_MULTIBOOT 01
+
+/**
+ * Normal image probe priority
+ */
+#define PROBE_NORMAL 02
+
+/**
+ * PXE image probe priority
+ *
+ * PXE images have no signature checks, so will claim all image files.
+ * They must therefore be tried last in the probe order list.
+ */
+#define PROBE_PXE 03
+
+/** Executable or loadable image type table */
+#define IMAGE_TYPES __table ( struct image_type, "image_types" )
+
+/** An executable or loadable image type */
+#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
+
+extern struct list_head images;
+
+/** Iterate over all registered images */
+#define for_each_image( image ) \
+ list_for_each_entry ( (image), &images, list )
+
+/**
+ * Test for existence of images
+ *
+ * @ret existence Some images exist
+ */
+static inline int have_images ( void ) {
+ return ( ! list_empty ( &images ) );
+}
+
+extern struct image * alloc_image ( void );
+extern int image_set_uri ( struct image *image, struct uri *uri );
+extern int image_set_cmdline ( struct image *image, const char *cmdline );
+extern int register_image ( struct image *image );
+extern void unregister_image ( struct image *image );
+extern void promote_image ( struct image *image );
+struct image * find_image ( const char *name );
+extern int image_load ( struct image *image );
+extern int image_autoload ( struct image *image );
+extern int image_exec ( struct image *image );
+extern int register_and_autoload_image ( struct image *image );
+extern int register_and_autoexec_image ( struct image *image );
+
+/**
+ * Increment reference count on an image
+ *
+ * @v image Image
+ * @ret image Image
+ */
+static inline struct image * image_get ( struct image *image ) {
+ ref_get ( &image->refcnt );
+ return image;
+}
+
+/**
+ * Decrement reference count on an image
+ *
+ * @v image Image
+ */
+static inline void image_put ( struct image *image ) {
+ ref_put ( &image->refcnt );
+}
+
+/**
+ * Set image name
+ *
+ * @v image Image
+ * @v name New image name
+ * @ret rc Return status code
+ */
+static inline int image_set_name ( struct image *image, const char *name ) {
+ strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) );
+ return 0;
+}
+
+#endif /* _GPXE_IMAGE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/in.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/in.h
new file mode 100644
index 0000000..7027114
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/in.h
@@ -0,0 +1,105 @@
+#ifndef _GPXE_IN_H
+#define _GPXE_IN_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/socket.h>
+
+/* Protocol numbers */
+
+#define IP_ICMP 1
+#define IP_IGMP 2
+#define IP_TCP 6
+#define IP_UDP 17
+#define IP_ICMP6 58
+
+/* IP address constants */
+
+#define INADDR_NONE 0xffffffff
+
+#define INADDR_BROADCAST 0xffffffff
+
+#define IN_CLASSA(addr) ( ( (addr) & 0x80000000 ) == 0x00000000 )
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSB(addr) ( ( (addr) & 0xc0000000 ) == 0x80000000 )
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSC(addr) ( ( (addr) & 0xe0000000 ) == 0xc0000000 )
+#define IN_CLASSC_NET 0xffffff00
+#define IN_MULTICAST(addr) ( ( (addr) & 0xf0000000 ) == 0xe0000000 )
+
+/**
+ * IP address structure
+ */
+struct in_addr {
+ uint32_t s_addr;
+};
+
+typedef struct in_addr in_addr;
+
+/**
+ * IP6 address structure
+ */
+struct in6_addr {
+ union {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+};
+
+/**
+ * IPv4 socket address
+ */
+struct sockaddr_in {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_INET for IPv4 addresses
+ */
+ sa_family_t sin_family;
+ /** TCP/IP port (part of struct @c sockaddr_tcpip) */
+ uint16_t sin_port;
+ /** IPv4 address */
+ struct in_addr sin_addr;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
+ - sizeof ( uint16_t )
+ - sizeof ( struct in_addr ) ];
+} __attribute__ (( may_alias ));
+
+/**
+ * IPv6 socket address
+ */
+struct sockaddr_in6 {
+ /** Socket address family (part of struct @c sockaddr)
+ *
+ * Always set to @c AF_INET6 for IPv6 addresses
+ */
+ sa_family_t sin_family;
+ /** TCP/IP port (part of struct @c sockaddr_tcpip) */
+ uint16_t sin_port;
+ uint32_t sin6_flowinfo; /* Flow number */
+ struct in6_addr sin6_addr; /* 128-bit destination address */
+ uint32_t sin6_scope_id; /* Scope ID */
+} __attribute__ (( may_alias ));
+
+extern int inet_aton ( const char *cp, struct in_addr *inp );
+extern char * inet_ntoa ( struct in_addr in );
+
+/* Adding the following for IP6 support
+ *
+
+extern int inet6_aton ( const char *cp, struct in6_addr *inp );
+extern char * inet6_ntoa ( struct in_addr in );
+
+ */
+
+#endif /* _GPXE_IN_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/infiniband.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/infiniband.h
new file mode 100644
index 0000000..69bc69b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/infiniband.h
@@ -0,0 +1,652 @@
+#ifndef _GPXE_INFINIBAND_H
+#define _GPXE_INFINIBAND_H
+
+/** @file
+ *
+ * Infiniband protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/device.h>
+#include <gpxe/ib_packet.h>
+#include <gpxe/ib_mad.h>
+
+/** Subnet management interface QPN */
+#define IB_QPN_SMI 0
+
+/** Subnet management interface queue key */
+#define IB_QKEY_SMI 0
+
+/** General service interface QPN */
+#define IB_QPN_GSI 1
+
+/** General service interface queue key */
+#define IB_QKEY_GSI 0x80010000UL
+
+/** Broadcast QPN */
+#define IB_QPN_BROADCAST 0xffffffUL
+
+/** Default Infiniband partition key */
+#define IB_PKEY_NONE 0xffff
+
+/**
+ * Maximum payload size
+ *
+ * This is currently hard-coded in various places (drivers, subnet
+ * management agent, etc.) to 2048.
+ */
+#define IB_MAX_PAYLOAD_SIZE 2048
+
+struct ib_device;
+struct ib_queue_pair;
+struct ib_address_vector;
+struct ib_completion_queue;
+struct ib_mad_interface;
+
+/** Infiniband transmission rates */
+enum ib_rate {
+ IB_RATE_2_5 = 2,
+ IB_RATE_10 = 3,
+ IB_RATE_30 = 4,
+ IB_RATE_5 = 5,
+ IB_RATE_20 = 6,
+ IB_RATE_40 = 7,
+ IB_RATE_60 = 8,
+ IB_RATE_80 = 9,
+ IB_RATE_120 = 10,
+};
+
+/** An Infiniband Address Vector */
+struct ib_address_vector {
+ /** Queue Pair Number */
+ unsigned long qpn;
+ /** Queue key
+ *
+ * Not specified for received packets.
+ */
+ unsigned long qkey;
+ /** Local ID */
+ unsigned int lid;
+ /** Rate
+ *
+ * Not specified for received packets.
+ */
+ enum ib_rate rate;
+ /** Service level */
+ unsigned int sl;
+ /** GID is present */
+ unsigned int gid_present;
+ /** GID, if present */
+ struct ib_gid gid;
+};
+
+/** An Infiniband Work Queue */
+struct ib_work_queue {
+ /** Containing queue pair */
+ struct ib_queue_pair *qp;
+ /** "Is a send queue" flag */
+ int is_send;
+ /** Associated completion queue */
+ struct ib_completion_queue *cq;
+ /** List of work queues on this completion queue */
+ struct list_head list;
+ /** Packet sequence number */
+ uint32_t psn;
+ /** Number of work queue entries */
+ unsigned int num_wqes;
+ /** Number of occupied work queue entries */
+ unsigned int fill;
+ /** Next work queue entry index
+ *
+ * This is the index of the next entry to be filled (i.e. the
+ * first empty entry). This value is not bounded by num_wqes;
+ * users must logical-AND with (num_wqes-1) to generate an
+ * array index.
+ */
+ unsigned long next_idx;
+ /** I/O buffers assigned to work queue */
+ struct io_buffer **iobufs;
+ /** Driver private data */
+ void *drv_priv;
+};
+
+/** An Infiniband multicast GID */
+struct ib_multicast_gid {
+ /** List of multicast GIDs on this QP */
+ struct list_head list;
+ /** Multicast GID */
+ struct ib_gid gid;
+};
+
+/** An Infiniband queue pair type */
+enum ib_queue_pair_type {
+ IB_QPT_SMI,
+ IB_QPT_GSI,
+ IB_QPT_UD,
+ IB_QPT_RC,
+};
+
+/** An Infiniband Queue Pair */
+struct ib_queue_pair {
+ /** Containing Infiniband device */
+ struct ib_device *ibdev;
+ /** List of queue pairs on this Infiniband device */
+ struct list_head list;
+ /** Queue pair number */
+ unsigned long qpn;
+ /** Externally-visible queue pair number
+ *
+ * This may differ from the real queue pair number (e.g. when
+ * the HCA cannot use the management QPNs 0 and 1 as hardware
+ * QPNs and needs to remap them).
+ */
+ unsigned long ext_qpn;
+ /** Queue pair type */
+ enum ib_queue_pair_type type;
+ /** Queue key */
+ unsigned long qkey;
+ /** Send queue */
+ struct ib_work_queue send;
+ /** Receive queue */
+ struct ib_work_queue recv;
+ /** List of multicast GIDs */
+ struct list_head mgids;
+ /** Address vector */
+ struct ib_address_vector av;
+ /** Driver private data */
+ void *drv_priv;
+ /** Queue owner private data */
+ void *owner_priv;
+};
+
+/** Infiniband completion queue operations */
+struct ib_completion_queue_operations {
+ /**
+ * Complete Send WQE
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+ void ( * complete_send ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc );
+ /**
+ * Complete Receive WQE
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+ void ( * complete_recv ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc );
+};
+
+/** An Infiniband Completion Queue */
+struct ib_completion_queue {
+ /** Containing Infiniband device */
+ struct ib_device *ibdev;
+ /** List of completion queues on this Infiniband device */
+ struct list_head list;
+ /** Completion queue number */
+ unsigned long cqn;
+ /** Number of completion queue entries */
+ unsigned int num_cqes;
+ /** Next completion queue entry index
+ *
+ * This is the index of the next entry to be filled (i.e. the
+ * first empty entry). This value is not bounded by num_wqes;
+ * users must logical-AND with (num_wqes-1) to generate an
+ * array index.
+ */
+ unsigned long next_idx;
+ /** List of work queues completing to this queue */
+ struct list_head work_queues;
+ /** Completion queue operations */
+ struct ib_completion_queue_operations *op;
+ /** Driver private data */
+ void *drv_priv;
+};
+
+/**
+ * Infiniband device operations
+ *
+ * These represent a subset of the Infiniband Verbs.
+ */
+struct ib_device_operations {
+ /** Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ * @ret rc Return status code
+ */
+ int ( * create_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /** Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+ void ( * destroy_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /** Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+ int ( * create_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @ret rc Return status code
+ */
+ int ( * modify_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+ void ( * destroy_qp ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+ /** Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the queue pair. If this method returns failure,
+ * the I/O buffer is immediately released; the failure is
+ * interpreted as "failure to enqueue buffer".
+ */
+ int ( * post_send ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf );
+ /** Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the queue pair. If this method returns failure,
+ * the I/O buffer is immediately released; the failure is
+ * interpreted as "failure to enqueue buffer".
+ */
+ int ( * post_recv ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf );
+ /** Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ *
+ * The relevant completion handler (specified at completion
+ * queue creation time) takes ownership of the I/O buffer.
+ */
+ void ( * poll_cq ) ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+ /**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * poll_eq ) ( struct ib_device *ibdev );
+ /**
+ * Open port
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct ib_device *ibdev );
+ /**
+ * Close port
+ *
+ * @v ibdev Infiniband device
+ */
+ void ( * close ) ( struct ib_device *ibdev );
+ /** Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ */
+ int ( * mcast_attach ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_gid *gid );
+ /** Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+ void ( * mcast_detach ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_gid *gid );
+ /** Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set port information MAD
+ *
+ * This method is required only by adapters that do not have
+ * an embedded SMA.
+ */
+ int ( * set_port_info ) ( struct ib_device *ibdev, union ib_mad *mad );
+ /** Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ *
+ * This method is required only by adapters that do not have
+ * an embedded SMA.
+ */
+ int ( * set_pkey_table ) ( struct ib_device *ibdev,
+ union ib_mad *mad );
+};
+
+/** An Infiniband device */
+struct ib_device {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of Infiniband devices */
+ struct list_head list;
+ /** List of open Infiniband devices */
+ struct list_head open_list;
+ /** Underlying device */
+ struct device *dev;
+ /** List of completion queues */
+ struct list_head cqs;
+ /** List of queue pairs */
+ struct list_head qps;
+ /** Infiniband operations */
+ struct ib_device_operations *op;
+ /** Port number */
+ unsigned int port;
+ /** Port open request counter */
+ unsigned int open_count;
+
+ /** Port state */
+ uint8_t port_state;
+ /** Link width supported */
+ uint8_t link_width_supported;
+ /** Link width enabled */
+ uint8_t link_width_enabled;
+ /** Link width active */
+ uint8_t link_width_active;
+ /** Link speed supported */
+ uint8_t link_speed_supported;
+ /** Link speed enabled */
+ uint8_t link_speed_enabled;
+ /** Link speed active */
+ uint8_t link_speed_active;
+ /** Port GID */
+ struct ib_gid gid;
+ /** Port LID */
+ uint16_t lid;
+ /** Subnet manager LID */
+ uint16_t sm_lid;
+ /** Subnet manager SL */
+ uint8_t sm_sl;
+ /** Partition key */
+ uint16_t pkey;
+
+ /** RDMA key
+ *
+ * This is a single key allowing unrestricted access to
+ * memory.
+ */
+ uint32_t rdma_key;
+
+ /** Subnet management interface */
+ struct ib_mad_interface *smi;
+ /** General services interface */
+ struct ib_mad_interface *gsi;
+
+ /** Driver private data */
+ void *drv_priv;
+ /** Owner private data */
+ void *owner_priv;
+};
+
+extern struct ib_completion_queue *
+ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
+ struct ib_completion_queue_operations *op );
+extern void ib_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+extern void ib_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq );
+extern struct ib_queue_pair *
+ib_create_qp ( struct ib_device *ibdev, enum ib_queue_pair_type type,
+ unsigned int num_send_wqes, struct ib_completion_queue *send_cq,
+ unsigned int num_recv_wqes,
+ struct ib_completion_queue *recv_cq );
+extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp );
+extern void ib_destroy_qp ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+extern struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
+ unsigned long qpn );
+extern struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
+ struct ib_gid *gid );
+extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
+ unsigned long qpn, int is_send );
+extern int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf );
+extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf );
+extern void ib_complete_send ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc );
+extern void ib_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc );
+extern void ib_refill_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp );
+extern int ib_open ( struct ib_device *ibdev );
+extern void ib_close ( struct ib_device *ibdev );
+extern int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *gid );
+extern void ib_mcast_detach ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp, struct ib_gid *gid );
+extern int ib_get_hca_info ( struct ib_device *ibdev,
+ struct ib_gid_half *hca_guid );
+extern int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad );
+extern int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad );
+extern struct ib_device * alloc_ibdev ( size_t priv_size );
+extern int register_ibdev ( struct ib_device *ibdev );
+extern void unregister_ibdev ( struct ib_device *ibdev );
+extern struct ib_device * find_ibdev ( struct ib_gid *gid );
+extern struct ib_device * last_opened_ibdev ( void );
+extern void ib_link_state_changed ( struct ib_device *ibdev );
+extern void ib_poll_eq ( struct ib_device *ibdev );
+extern struct list_head ib_devices;
+
+/** Iterate over all network devices */
+#define for_each_ibdev( ibdev ) \
+ list_for_each_entry ( (ibdev), &ib_devices, list )
+
+/**
+ * Check link state
+ *
+ * @v ibdev Infiniband device
+ * @ret link_up Link is up
+ */
+static inline __always_inline int
+ib_link_ok ( struct ib_device *ibdev ) {
+ return ( ibdev->port_state == IB_PORT_STATE_ACTIVE );
+}
+
+/**
+ * Get reference to Infiniband device
+ *
+ * @v ibdev Infiniband device
+ * @ret ibdev Infiniband device
+ */
+static inline __always_inline struct ib_device *
+ibdev_get ( struct ib_device *ibdev ) {
+ ref_get ( &ibdev->refcnt );
+ return ibdev;
+}
+
+/**
+ * Drop reference to Infiniband device
+ *
+ * @v ibdev Infiniband device
+ */
+static inline __always_inline void
+ibdev_put ( struct ib_device *ibdev ) {
+ ref_put ( &ibdev->refcnt );
+}
+
+/**
+ * Set Infiniband work queue driver-private data
+ *
+ * @v wq Work queue
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_wq_set_drvdata ( struct ib_work_queue *wq, void *priv ) {
+ wq->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband work queue driver-private data
+ *
+ * @v wq Work queue
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_wq_get_drvdata ( struct ib_work_queue *wq ) {
+ return wq->drv_priv;
+}
+
+/**
+ * Set Infiniband queue pair driver-private data
+ *
+ * @v qp Queue pair
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_qp_set_drvdata ( struct ib_queue_pair *qp, void *priv ) {
+ qp->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband queue pair driver-private data
+ *
+ * @v qp Queue pair
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_qp_get_drvdata ( struct ib_queue_pair *qp ) {
+ return qp->drv_priv;
+}
+
+/**
+ * Set Infiniband queue pair owner-private data
+ *
+ * @v qp Queue pair
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_qp_set_ownerdata ( struct ib_queue_pair *qp, void *priv ) {
+ qp->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband queue pair owner-private data
+ *
+ * @v qp Queue pair
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_qp_get_ownerdata ( struct ib_queue_pair *qp ) {
+ return qp->owner_priv;
+}
+
+/**
+ * Set Infiniband completion queue driver-private data
+ *
+ * @v cq Completion queue
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_cq_set_drvdata ( struct ib_completion_queue *cq, void *priv ) {
+ cq->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband completion queue driver-private data
+ *
+ * @v cq Completion queue
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_cq_get_drvdata ( struct ib_completion_queue *cq ) {
+ return cq->drv_priv;
+}
+
+/**
+ * Set Infiniband device driver-private data
+ *
+ * @v ibdev Infiniband device
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_set_drvdata ( struct ib_device *ibdev, void *priv ) {
+ ibdev->drv_priv = priv;
+}
+
+/**
+ * Get Infiniband device driver-private data
+ *
+ * @v ibdev Infiniband device
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_get_drvdata ( struct ib_device *ibdev ) {
+ return ibdev->drv_priv;
+}
+
+/**
+ * Set Infiniband device owner-private data
+ *
+ * @v ibdev Infiniband device
+ * @v priv Private data
+ */
+static inline __always_inline void
+ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) {
+ ibdev->owner_priv = priv;
+}
+
+/**
+ * Get Infiniband device owner-private data
+ *
+ * @v ibdev Infiniband device
+ * @ret priv Private data
+ */
+static inline __always_inline void *
+ib_get_ownerdata ( struct ib_device *ibdev ) {
+ return ibdev->owner_priv;
+}
+
+#endif /* _GPXE_INFINIBAND_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/init.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/init.h
new file mode 100644
index 0000000..a72cba7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/init.h
@@ -0,0 +1,81 @@
+#ifndef _GPXE_INIT_H
+#define _GPXE_INIT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tables.h>
+
+/**
+ * An initialisation function
+ *
+ * Initialisation functions are called exactly once, as part of the
+ * call to initialise().
+ */
+struct init_fn {
+ void ( * initialise ) ( void );
+};
+
+/** Initialisation function table */
+#define INIT_FNS __table ( struct init_fn, "init_fns" )
+
+/** Declare an initialisation functon */
+#define __init_fn( init_order ) __table_entry ( INIT_FNS, init_order )
+
+/** @defgroup initfn_order Initialisation function ordering
+ * @{
+ */
+
+#define INIT_EARLY 01 /**< Early initialisation */
+#define INIT_SERIAL 02 /**< Serial driver initialisation */
+#define INIT_CONSOLE 03 /**< Console initialisation */
+#define INIT_NORMAL 04 /**< Normal initialisation */
+
+/** @} */
+
+/** Shutdown flags */
+enum shutdown_flags {
+ /** Shutdown is in order to exit (return to gPXE's caller) */
+ SHUTDOWN_EXIT = 0x0001,
+ /** Shutdown is in order to boot an OS */
+ SHUTDOWN_BOOT = 0x0002,
+ /** Do not remove devices */
+ SHUTDOWN_KEEP_DEVICES = 0x0004,
+};
+
+/**
+ * A startup/shutdown function
+ *
+ * Startup and shutdown functions may be called multiple times, as
+ * part of the calls to startup() and shutdown().
+ */
+struct startup_fn {
+ void ( * startup ) ( void );
+ void ( * shutdown ) ( int flags );
+};
+
+/** Startup/shutdown function table */
+#define STARTUP_FNS __table ( struct startup_fn, "startup_fns" )
+
+/** Declare a startup/shutdown function */
+#define __startup_fn( startup_order ) \
+ __table_entry ( STARTUP_FNS, startup_order )
+
+/** @defgroup startfn_order Startup/shutdown function ordering
+ *
+ * Shutdown functions are called in the reverse order to startup
+ * functions.
+ *
+ * @{
+ */
+
+#define STARTUP_EARLY 01 /**< Early startup */
+#define STARTUP_NORMAL 02 /**< Normal startup */
+#define STARTUP_LATE 03 /**< Late startup */
+
+/** @} */
+
+extern void initialise ( void );
+extern void startup ( void );
+extern void shutdown ( int flags );
+
+#endif /* _GPXE_INIT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/interface.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/interface.h
new file mode 100644
index 0000000..114ebf3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/interface.h
@@ -0,0 +1,58 @@
+#ifndef _GPXE_INTERFACE_H
+#define _GPXE_INTERFACE_H
+
+/** @file
+ *
+ * Object communication interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/refcnt.h>
+
+/** An object communication interface */
+struct interface {
+ /** Destination interface
+ *
+ * When messages are sent via this interface, they will be
+ * delivered to the destination interface.
+ *
+ * This pointer may never be NULL. When the interface is
+ * unplugged, it should point to a null interface.
+ */
+ struct interface *dest;
+ /** Reference counter
+ *
+ * If this interface is not part of a reference-counted
+ * object, this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+/**
+ * Increment reference count on an interface
+ *
+ * @v intf Interface
+ * @ret intf Interface
+ */
+static inline __attribute__ (( always_inline )) struct interface *
+intf_get ( struct interface *intf ) {
+ ref_get ( intf->refcnt );
+ return intf;
+}
+
+/**
+ * Decrement reference count on an interface
+ *
+ * @v intf Interface
+ */
+static inline __attribute__ (( always_inline )) void
+intf_put ( struct interface *intf ) {
+ ref_put ( intf->refcnt );
+}
+
+extern void plug ( struct interface *intf, struct interface *dest );
+extern void plug_plug ( struct interface *a, struct interface *b );
+
+#endif /* _GPXE_INTERFACE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/iobuf.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/iobuf.h
new file mode 100644
index 0000000..8f05f9e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/iobuf.h
@@ -0,0 +1,229 @@
+#ifndef _GPXE_IOBUF_H
+#define _GPXE_IOBUF_H
+
+/** @file
+ *
+ * I/O buffers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <assert.h>
+#include <gpxe/list.h>
+
+/**
+ * I/O buffer alignment
+ *
+ * I/O buffers allocated via alloc_iob() are guaranteed to be
+ * physically aligned to this boundary. Some cards cannot DMA across
+ * a 4kB boundary. With a standard Ethernet MTU, aligning to a 2kB
+ * boundary is sufficient to guarantee no 4kB boundary crossings. For
+ * a jumbo Ethernet MTU, a packet may be larger than 4kB anyway.
+ */
+#define IOB_ALIGN 2048
+
+/**
+ * Minimum I/O buffer length
+ *
+ * alloc_iob() will round up the allocated length to this size if
+ * necessary. This is used on behalf of hardware that is not capable
+ * of auto-padding.
+ */
+#define IOB_ZLEN 64
+
+/**
+ * A persistent I/O buffer
+ *
+ * This data structure encapsulates a long-lived I/O buffer. The
+ * buffer may be passed between multiple owners, queued for possible
+ * retransmission, etc.
+ */
+struct io_buffer {
+ /** List of which this buffer is a member
+ *
+ * The list must belong to the current owner of the buffer.
+ * Different owners may maintain different lists (e.g. a
+ * retransmission list for TCP).
+ */
+ struct list_head list;
+
+ /** Start of the buffer */
+ void *head;
+ /** Start of data */
+ void *data;
+ /** End of data */
+ void *tail;
+ /** End of the buffer */
+ void *end;
+};
+
+/**
+ * Reserve space at start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to reserve
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data += len;
+ iobuf->tail += len;
+ return iobuf->data;
+}
+#define iob_reserve( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_reserve ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail <= (iobuf)->end ); \
+ __result; } )
+
+/**
+ * Add data to start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to add
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data -= len;
+ return iobuf->data;
+}
+#define iob_push( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_push ( (iobuf), (len) ); \
+ assert ( (iobuf)->data >= (iobuf)->head ); \
+ __result; } )
+
+/**
+ * Remove data from start of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to remove
+ * @ret data Pointer to new start of buffer
+ */
+static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->data += len;
+ assert ( iobuf->data <= iobuf->tail );
+ return iobuf->data;
+}
+#define iob_pull( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_pull ( (iobuf), (len) ); \
+ assert ( (iobuf)->data <= (iobuf)->tail ); \
+ __result; } )
+
+/**
+ * Add data to end of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to add
+ * @ret data Pointer to newly added space
+ */
+static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
+ void *old_tail = iobuf->tail;
+ iobuf->tail += len;
+ return old_tail;
+}
+#define iob_put( iobuf, len ) ( { \
+ void *__result; \
+ __result = iob_put ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail <= (iobuf)->end ); \
+ __result; } )
+
+/**
+ * Remove data from end of I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v len Length to remove
+ */
+static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
+ iobuf->tail -= len;
+}
+#define iob_unput( iobuf, len ) do { \
+ iob_unput ( (iobuf), (len) ); \
+ assert ( (iobuf)->tail >= (iobuf)->data ); \
+ } while ( 0 )
+
+/**
+ * Empty an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ */
+static inline void iob_empty ( struct io_buffer *iobuf ) {
+ iobuf->tail = iobuf->data;
+}
+
+/**
+ * Calculate length of data in an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data in buffer
+ */
+static inline size_t iob_len ( struct io_buffer *iobuf ) {
+ return ( iobuf->tail - iobuf->data );
+}
+
+/**
+ * Calculate available space at start of an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data available at start of buffer
+ */
+static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
+ return ( iobuf->data - iobuf->head );
+}
+
+/**
+ * Calculate available space at end of an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @ret len Length of data available at end of buffer
+ */
+static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
+ return ( iobuf->end - iobuf->tail );
+}
+
+/**
+ * Create a temporary I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v data Data buffer
+ * @v len Length of data
+ * @v max_len Length of buffer
+ *
+ * It is sometimes useful to use the iob_xxx() methods on temporary
+ * data buffers.
+ */
+static inline void iob_populate ( struct io_buffer *iobuf,
+ void *data, size_t len, size_t max_len ) {
+ iobuf->head = iobuf->data = data;
+ iobuf->tail = ( data + len );
+ iobuf->end = ( data + max_len );
+}
+
+/**
+ * Disown an I/O buffer
+ *
+ * @v iobuf I/O buffer
+ *
+ * There are many functions that take ownership of the I/O buffer they
+ * are passed as a parameter. The caller should not retain a pointer
+ * to the I/O buffer. Use iob_disown() to automatically nullify the
+ * caller's pointer, e.g.:
+ *
+ * xfer_deliver_iob ( xfer, iob_disown ( iobuf ) );
+ *
+ * This will ensure that iobuf is set to NULL for any code after the
+ * call to xfer_deliver_iob().
+ */
+#define iob_disown( iobuf ) ( { \
+ struct io_buffer *__iobuf = (iobuf); \
+ (iobuf) = NULL; \
+ __iobuf; } )
+
+extern struct io_buffer * __malloc alloc_iob ( size_t len );
+extern void free_iob ( struct io_buffer *iobuf );
+extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
+extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len );
+
+#endif /* _GPXE_IOBUF_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ip.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ip.h
new file mode 100644
index 0000000..4342a0c
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ip.h
@@ -0,0 +1,97 @@
+#ifndef _GPXE_IP_H
+#define _GPXE_IP_H
+
+/** @file
+ *
+ * IP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/in.h>
+#include <gpxe/list.h>
+#include <gpxe/retry.h>
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+
+/* IP constants */
+
+#define IP_VER 0x40U
+#define IP_MASK_VER 0xf0U
+#define IP_MASK_HLEN 0x0fU
+#define IP_MASK_OFFSET 0x1fffU
+#define IP_MASK_DONOTFRAG 0x4000U
+#define IP_MASK_MOREFRAGS 0x2000U
+#define IP_PSHLEN 12
+
+/* IP header defaults */
+#define IP_TOS 0
+#define IP_TTL 64
+
+#define IP_FRAG_IOB_SIZE 1500
+#define IP_FRAG_TIMEOUT 50
+
+/** An IPv4 packet header */
+struct iphdr {
+ uint8_t verhdrlen;
+ uint8_t service;
+ uint16_t len;
+ uint16_t ident;
+ uint16_t frags;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t chksum;
+ struct in_addr src;
+ struct in_addr dest;
+} __attribute__ (( packed ));
+
+/** An IPv4 pseudo header */
+struct ipv4_pseudo_header {
+ struct in_addr src;
+ struct in_addr dest;
+ uint8_t zero_padding;
+ uint8_t protocol;
+ uint16_t len;
+};
+
+/** An IPv4 address/routing table entry */
+struct ipv4_miniroute {
+ /** List of miniroutes */
+ struct list_head list;
+
+ /** Network device */
+ struct net_device *netdev;
+
+ /** IPv4 address */
+ struct in_addr address;
+ /** Subnet mask */
+ struct in_addr netmask;
+ /** Gateway address */
+ struct in_addr gateway;
+};
+
+/* Fragment reassembly buffer */
+struct frag_buffer {
+ /* Identification number */
+ uint16_t ident;
+ /* Source network address */
+ struct in_addr src;
+ /* Destination network address */
+ struct in_addr dest;
+ /* Reassembled I/O buffer */
+ struct io_buffer *frag_iob;
+ /* Reassembly timer */
+ struct retry_timer frag_timer;
+ /* List of fragment reassembly buffers */
+ struct list_head list;
+};
+
+extern struct list_head ipv4_miniroutes;
+
+extern struct net_protocol ipv4_protocol;
+
+#endif /* _GPXE_IP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ip6.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ip6.h
new file mode 100644
index 0000000..edb2863
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ip6.h
@@ -0,0 +1,80 @@
+#ifndef _GPXE_IP6_H
+#define _GPXE_IP6_H
+
+/** @file
+ *
+ * IP6 protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/in.h>
+
+/* IP6 constants */
+
+#define IP6_VERSION 0x6
+#define IP6_HOP_LIMIT 255
+
+/**
+ * I/O buffer contents
+ * This is duplicated in tcp.h and here. Ideally it should go into iobuf.h
+ */
+#define MAX_HDR_LEN 100
+#define MAX_IOB_LEN 1500
+#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
+
+#define IP6_EQUAL( in6_addr1, in6_addr2 ) \
+ ( memcmp ( ( char* ) &( in6_addr1 ), ( char* ) &( in6_addr2 ),\
+ sizeof ( struct in6_addr ) ) == 0 )
+
+#define IS_UNSPECIFIED( addr ) \
+ ( ( (addr).in6_u.u6_addr32[0] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[1] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[2] == 0x00000000 ) && \
+ ( (addr).in6_u.u6_addr32[3] == 0x00000000 ) )
+/* IP6 header */
+struct ip6_header {
+ uint32_t ver_traffic_class_flow_label;
+ uint16_t payload_len;
+ uint8_t nxt_hdr;
+ uint8_t hop_limit;
+ struct in6_addr src;
+ struct in6_addr dest;
+};
+
+/* IP6 pseudo header */
+struct ipv6_pseudo_header {
+ struct in6_addr src;
+ struct in6_addr dest;
+ uint8_t zero_padding;
+ uint8_t nxt_hdr;
+ uint16_t len;
+};
+
+/* Next header numbers */
+#define IP6_HOPBYHOP 0x00
+#define IP6_ROUTING 0x43
+#define IP6_FRAGMENT 0x44
+#define IP6_AUTHENTICATION 0x51
+#define IP6_DEST_OPTS 0x60
+#define IP6_ESP 0x50
+#define IP6_ICMP6 0x58
+#define IP6_NO_HEADER 0x59
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+
+extern struct net_protocol ipv6_protocol;
+extern struct tcpip_net_protocol ipv6_tcpip_protocol;
+extern char * inet6_ntoa ( struct in6_addr in6 );
+
+extern int add_ipv6_address ( struct net_device *netdev,
+ struct in6_addr prefix, int prefix_len,
+ struct in6_addr address,
+ struct in6_addr gateway );
+extern void del_ipv6_address ( struct net_device *netdev );
+
+#endif /* _GPXE_IP6_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ipoib.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ipoib.h
new file mode 100644
index 0000000..f8231db
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ipoib.h
@@ -0,0 +1,60 @@
+#ifndef _GPXE_IPOIB_H
+#define _GPXE_IPOIB_H
+
+/** @file
+ *
+ * IP over Infiniband
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/infiniband.h>
+
+/** IPoIB MAC address length */
+#define IPOIB_ALEN 20
+
+/** An IPoIB MAC address */
+struct ipoib_mac {
+ /** Queue pair number
+ *
+ * MSB must be zero; QPNs are only 24-bit.
+ */
+ uint32_t qpn;
+ /** Port GID */
+ struct ib_gid gid;
+} __attribute__ (( packed ));
+
+/** IPoIB link-layer header length */
+#define IPOIB_HLEN 4
+
+/** IPoIB link-layer header */
+struct ipoib_hdr {
+ /** Network-layer protocol */
+ uint16_t proto;
+ /** Reserved, must be zero */
+ union {
+ /** Reserved, must be zero */
+ uint16_t reserved;
+ /** Peer addresses
+ *
+ * We use these fields internally to represent the
+ * peer addresses using a lookup key. There simply
+ * isn't enough room in the IPoIB header to store
+ * literal source or destination MAC addresses.
+ */
+ struct {
+ /** Destination address key */
+ uint8_t dest;
+ /** Source address key */
+ uint8_t src;
+ } __attribute__ (( packed )) peer;
+ } __attribute__ (( packed )) u;
+} __attribute__ (( packed ));
+
+extern const char * ipoib_ntoa ( const void *ll_addr );
+extern void ipoib_link_state_changed ( struct ib_device *ibdev );
+extern int ipoib_probe ( struct ib_device *ibdev );
+extern void ipoib_remove ( struct ib_device *ibdev );
+extern struct net_device * alloc_ipoibdev ( size_t priv_size );
+
+#endif /* _GPXE_IPOIB_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/isa.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/isa.h
new file mode 100644
index 0000000..63027a5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/isa.h
@@ -0,0 +1,97 @@
+#ifndef ISA_H
+#define ISA_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/** An ISA device */
+struct isa_device {
+ /** Generic device */
+ struct device dev;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Driver for this device */
+ struct isa_driver *driver;
+ /** Driver-private data
+ *
+ * Use isa_set_drvdata() and isa_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/*
+ * An individual ISA device, identified by probe address
+ *
+ */
+typedef uint16_t isa_probe_addr_t;
+
+/** An ISA driver */
+struct isa_driver {
+ /** Name */
+ const char *name;
+ /** Probe address list */
+ isa_probe_addr_t *probe_addrs;
+ /** Number of entries in probe address list */
+ unsigned int addr_count;
+ /** Manufacturer ID to be assumed for this device */
+ uint16_t vendor_id;
+ /** Product ID to be assumed for this device */
+ uint16_t prod_id;
+ /**
+ * Probe device
+ *
+ * @v isa ISA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct isa_device *isa );
+ /**
+ * Remove device
+ *
+ * @v isa ISA device
+ */
+ void ( * remove ) ( struct isa_device *isa );
+};
+
+/** ISA driver table */
+#define ISA_DRIVERS __table ( struct isa_driver, "isa_drivers" )
+
+/** Declare an ISA driver */
+#define __isa_driver __table_entry ( ISA_DRIVERS, 01 )
+
+/**
+ * Set ISA driver-private data
+ *
+ * @v isa ISA device
+ * @v priv Private data
+ */
+static inline void isa_set_drvdata ( struct isa_device *isa, void *priv ) {
+ isa->priv = priv;
+}
+
+/**
+ * Get ISA driver-private data
+ *
+ * @v isa ISA device
+ * @ret priv Private data
+ */
+static inline void * isa_get_drvdata ( struct isa_device *isa ) {
+ return isa->priv;
+}
+
+/*
+ * ISA_ROM is parsed by parserom.pl to generate Makefile rules and
+ * files for rom-o-matic.
+ *
+ */
+#define ISA_ROM( IMAGE, DESCRIPTION )
+
+#endif /* ISA_H */
+
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/isa_ids.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/isa_ids.h
new file mode 100644
index 0000000..1faf114
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/isa_ids.h
@@ -0,0 +1,51 @@
+#ifndef ISA_IDS_H
+#define ISA_IDS_H
+
+/*
+ * This file defines IDs as used by ISAPnP and EISA devices. These
+ * IDs have the format:
+ *
+ * vendor byte 0 bit 7 must be zero
+ * bits 6-2 first vendor char in compressed ASCII
+ * bits 1-0 second vendor char in compressed ASCII (bits 4-3)
+ * byte 1 bits 7-5 second vendor char in compressed ASCII (bits 2-0)
+ * bits 4-0 third vendor char in compressed ASCII
+ * product byte 0 bits 7-4 first hex digit of product number
+ * bits 3-0 second hex digit of product number
+ * byte 1 bits 7-4 third hex digit of product number
+ * bits 3-0 hex digit of revision level
+ *
+ * ISA IDs are always expressed in little-endian order, even though
+ * the underlying "meaning" is big-endian.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <byteswap.h>
+
+/*
+ * Construct a vendor ID from three ASCII characters
+ *
+ */
+#define ISA_VENDOR( a, b, c ) \
+ bswap_16 ( ( ( ( (a) - 'A' + 1 ) & 0x1f ) << 10 ) | \
+ ( ( ( (b) - 'A' + 1 ) & 0x1f ) << 5 ) | \
+ ( ( ( (c) - 'A' + 1 ) & 0x1f ) << 0 ) )
+
+#define ISAPNP_VENDOR( a, b, c ) ISA_VENDOR ( a, b, c )
+#define EISA_VENDOR( a, b, c ) ISA_VENDOR ( a, b, c )
+
+#define GENERIC_ISAPNP_VENDOR ISAPNP_VENDOR ( 'P','N','P' )
+
+/*
+ * Extract product ID and revision from combined product field
+ *
+ */
+#define ISA_PROD_ID_MASK ( 0xf0ff )
+#define ISA_PROD_ID(product) ( (product) & ISA_PROD_ID_MASK )
+#define ISA_PROD_REV(product) ( ( (product) & ~ISA_PROD_ID_MASK ) >> 8 )
+
+/* Functions in isa_ids.c */
+extern char * isa_id_string ( unsigned int vendor, unsigned int product );
+
+#endif /* ISA_IDS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/isapnp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/isapnp.h
new file mode 100644
index 0000000..b58a87e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/isapnp.h
@@ -0,0 +1,278 @@
+/**************************************************************************
+*
+* isapnp.h -- Etherboot isapnp support for the 3Com 3c515
+* Written 2002-2003 by Timothy Legge <tlegge@rogers.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Portions of this code:
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
+*
+*
+*
+* REVISION HISTORY:
+* ================
+* Version 0.1 April 26, 2002 TJL
+* Version 0.2 01/08/2003 TJL Renamed from 3c515_isapnp.h
+*
+*
+* Generalised into an ISAPnP bus that can be used by more than just
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
+*
+***************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef ISAPNP_H
+#define ISAPNP_H
+
+#include <stdint.h>
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/*
+ * ISAPnP constants
+ *
+ */
+
+/* Port addresses */
+#define ISAPNP_ADDRESS 0x279
+#define ISAPNP_WRITE_DATA 0xa79
+#define ISAPNP_READ_PORT_MIN 0x203
+#define ISAPNP_READ_PORT_START 0x213 /* ISAPnP spec says 0x203, but
+ * Linux ISAPnP starts at
+ * 0x213 with no explanatory
+ * comment. 0x203 probably
+ * clashes with something. */
+#define ISAPNP_READ_PORT_MAX 0x3ff
+#define ISAPNP_READ_PORT_STEP 0x10 /* Can be any multiple of 4
+ * according to the spec, but
+ * since ISA I/O addresses are
+ * allocated in blocks of 16,
+ * it makes no sense to use
+ * any value less than 16.
+ */
+
+/* Card select numbers */
+#define ISAPNP_CSN_MIN 0x01
+#define ISAPNP_CSN_MAX 0x0f
+
+/* Registers */
+#define ISAPNP_READPORT 0x00
+#define ISAPNP_SERIALISOLATION 0x01
+#define ISAPNP_CONFIGCONTROL 0x02
+#define ISAPNP_WAKE 0x03
+#define ISAPNP_RESOURCEDATA 0x04
+#define ISAPNP_STATUS 0x05
+#define ISAPNP_CARDSELECTNUMBER 0x06
+#define ISAPNP_LOGICALDEVICENUMBER 0x07
+#define ISAPNP_ACTIVATE 0x30
+#define ISAPNP_IORANGECHECK 0x31
+#define ISAPNP_IOBASE(n) ( 0x60 + ( (n) * 2 ) )
+#define ISAPNP_IRQNO(n) ( 0x70 + ( (n) * 2 ) )
+#define ISAPNP_IRQTYPE(n) ( 0x71 + ( (n) * 2 ) )
+
+/* Bits in the CONFIGCONTROL register */
+#define ISAPNP_CONFIG_RESET ( 1 << 0 )
+#define ISAPNP_CONFIG_WAIT_FOR_KEY ( 1 << 1 )
+#define ISAPNP_CONFIG_RESET_CSN ( 1 << 2 )
+#define ISAPNP_CONFIG_RESET_DRV ( ISAPNP_CONFIG_RESET | \
+ ISAPNP_CONFIG_WAIT_FOR_KEY | \
+ ISAPNP_CONFIG_RESET_CSN )
+
+/* The LFSR used for the initiation key and for checksumming */
+#define ISAPNP_LFSR_SEED 0x6a
+
+/* Small tags */
+#define ISAPNP_IS_SMALL_TAG(tag) ( ! ( (tag) & 0x80 ) )
+#define ISAPNP_SMALL_TAG_NAME(tag) ( ( (tag) >> 3 ) & 0xf )
+#define ISAPNP_SMALL_TAG_LEN(tag) ( ( (tag) & 0x7 ) )
+#define ISAPNP_TAG_PNPVERNO 0x01
+#define ISAPNP_TAG_LOGDEVID 0x02
+#define ISAPNP_TAG_COMPATDEVID 0x03
+#define ISAPNP_TAG_IRQ 0x04
+#define ISAPNP_TAG_DMA 0x05
+#define ISAPNP_TAG_STARTDEP 0x06
+#define ISAPNP_TAG_ENDDEP 0x07
+#define ISAPNP_TAG_IOPORT 0x08
+#define ISAPNP_TAG_FIXEDIO 0x09
+#define ISAPNP_TAG_RSVDSHORTA 0x0A
+#define ISAPNP_TAG_RSVDSHORTB 0x0B
+#define ISAPNP_TAG_RSVDSHORTC 0x0C
+#define ISAPNP_TAG_RSVDSHORTD 0x0D
+#define ISAPNP_TAG_VENDORSHORT 0x0E
+#define ISAPNP_TAG_END 0x0F
+/* Large tags */
+#define ISAPNP_IS_LARGE_TAG(tag) ( ( (tag) & 0x80 ) )
+#define ISAPNP_LARGE_TAG_NAME(tag) (tag)
+#define ISAPNP_TAG_MEMRANGE 0x81
+#define ISAPNP_TAG_ANSISTR 0x82
+#define ISAPNP_TAG_UNICODESTR 0x83
+#define ISAPNP_TAG_VENDORLONG 0x84
+#define ISAPNP_TAG_MEM32RANGE 0x85
+#define ISAPNP_TAG_FIXEDMEM32RANGE 0x86
+#define ISAPNP_TAG_RSVDLONG0 0xF0
+#define ISAPNP_TAG_RSVDLONG1 0xF1
+#define ISAPNP_TAG_RSVDLONG2 0xF2
+#define ISAPNP_TAG_RSVDLONG3 0xF3
+#define ISAPNP_TAG_RSVDLONG4 0xF4
+#define ISAPNP_TAG_RSVDLONG5 0xF5
+#define ISAPNP_TAG_RSVDLONG6 0xF6
+#define ISAPNP_TAG_RSVDLONG7 0xF7
+#define ISAPNP_TAG_RSVDLONG8 0xF8
+#define ISAPNP_TAG_RSVDLONG9 0xF9
+#define ISAPNP_TAG_RSVDLONGA 0xFA
+#define ISAPNP_TAG_RSVDLONGB 0xFB
+#define ISAPNP_TAG_RSVDLONGC 0xFC
+#define ISAPNP_TAG_RSVDLONGD 0xFD
+#define ISAPNP_TAG_RSVDLONGE 0xFE
+#define ISAPNP_TAG_RSVDLONGF 0xFF
+#define ISAPNP_TAG_PSEUDO_NEWBOARD 0x100
+
+/** An ISAPnP serial identifier */
+struct isapnp_identifier {
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Serial number */
+ uint32_t serial;
+ /** Checksum */
+ uint8_t checksum;
+} __attribute__ (( packed ));
+
+/** An ISAPnP logical device ID structure */
+struct isapnp_logdevid {
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** Flags */
+ uint16_t flags;
+} __attribute__ (( packed ));
+
+/** An ISAPnP device ID list entry */
+struct isapnp_device_id {
+ /** Name */
+ const char *name;
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+};
+
+/** An ISAPnP device */
+struct isapnp_device {
+ /** Generic device */
+ struct device dev;
+ /** Vendor ID */
+ uint16_t vendor_id;
+ /** Product ID */
+ uint16_t prod_id;
+ /** I/O address */
+ uint16_t ioaddr;
+ /** Interrupt number */
+ uint8_t irqno;
+ /** Card Select Number */
+ uint8_t csn;
+ /** Logical Device ID */
+ uint8_t logdev;
+ /** Driver for this device */
+ struct isapnp_driver *driver;
+ /** Driver-private data
+ *
+ * Use isapnp_set_drvdata() and isapnp_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+/** An ISAPnP driver */
+struct isapnp_driver {
+ /** ISAPnP ID table */
+ struct isapnp_device_id *ids;
+ /** Number of entries in ISAPnP ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v isapnp ISAPnP device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct isapnp_device *isapnp,
+ const struct isapnp_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v isapnp ISAPnP device
+ */
+ void ( * remove ) ( struct isapnp_device *isapnp );
+};
+
+/** ISAPnP driver table */
+#define ISAPNP_DRIVERS __table ( struct isapnp_driver, "isapnp_drivers" )
+
+/** Declare an ISAPnP driver */
+#define __isapnp_driver __table_entry ( ISAPNP_DRIVERS, 01 )
+
+extern uint16_t isapnp_read_port;
+
+extern void isapnp_device_activation ( struct isapnp_device *isapnp,
+ int activation );
+
+/**
+ * Activate ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static inline void activate_isapnp_device ( struct isapnp_device *isapnp ) {
+ isapnp_device_activation ( isapnp, 1 );
+}
+
+/**
+ * Deactivate ISAPnP device
+ *
+ * @v isapnp ISAPnP device
+ */
+static inline void deactivate_isapnp_device ( struct isapnp_device *isapnp ) {
+ isapnp_device_activation ( isapnp, 0 );
+}
+
+/**
+ * Set ISAPnP driver-private data
+ *
+ * @v isapnp ISAPnP device
+ * @v priv Private data
+ */
+static inline void isapnp_set_drvdata ( struct isapnp_device *isapnp,
+ void *priv ) {
+ isapnp->priv = priv;
+}
+
+/**
+ * Get ISAPnP driver-private data
+ *
+ * @v isapnp ISAPnP device
+ * @ret priv Private data
+ */
+static inline void * isapnp_get_drvdata ( struct isapnp_device *isapnp ) {
+ return isapnp->priv;
+}
+
+#endif /* ISAPNP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/iscsi.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/iscsi.h
new file mode 100644
index 0000000..00717d2
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/iscsi.h
@@ -0,0 +1,678 @@
+#ifndef _GPXE_ISCSI_H
+#define _GPXE_ISCSI_H
+
+/** @file
+ *
+ * iSCSI protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/socket.h>
+#include <gpxe/scsi.h>
+#include <gpxe/chap.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/process.h>
+
+/** Default iSCSI port */
+#define ISCSI_PORT 3260
+
+/**
+ * iSCSI segment lengths
+ *
+ * iSCSI uses an icky structure with one one-byte field (a dword
+ * count) and one three-byte field (a byte count). This structure,
+ * and the accompanying macros, relieve some of the pain.
+ */
+union iscsi_segment_lengths {
+ struct {
+ /** The AHS length (measured in dwords) */
+ uint8_t ahs_len;
+ /** The data length (measured in bytes), in network
+ * byte order
+ */
+ uint8_t data_len[3];
+ } bytes;
+ /** Ths data length (measured in bytes), in network byte
+ * order, with ahs_len as the first byte.
+ */
+ uint32_t ahs_and_data_len;
+};
+
+/** The length of the additional header segment, in dwords */
+#define ISCSI_AHS_LEN( segment_lengths ) \
+ ( (segment_lengths).bytes.ahs_len )
+
+/** The length of the data segment, in bytes, excluding any padding */
+#define ISCSI_DATA_LEN( segment_lengths ) \
+ ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
+
+/** The padding of the data segment, in bytes */
+#define ISCSI_DATA_PAD_LEN( segment_lengths ) \
+ ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
+
+/** Set additional header and data segment lengths */
+#define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
+ (segment_lengths).ahs_and_data_len = \
+ htonl ( data_len | ( ahs_len << 24 ) ); \
+ } while ( 0 )
+
+/**
+ * iSCSI basic header segment common fields
+ *
+ */
+struct iscsi_bhs_common {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Fields specific to the PDU type */
+ uint8_t other_a[2];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Fields specific to the PDU type */
+ uint8_t other_b[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Fields specific to the PDU type */
+ uint8_t other_c[28];
+};
+
+/** Opcode mask */
+#define ISCSI_OPCODE_MASK 0x3f
+
+/** Immediate delivery */
+#define ISCSI_FLAG_IMMEDIATE 0x40
+
+/** Final PDU of a sequence */
+#define ISCSI_FLAG_FINAL 0x80
+
+/**
+ * iSCSI basic header segment common request fields
+ *
+ */
+struct iscsi_bhs_common_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Fields specific to the PDU type */
+ uint8_t other_a[2];
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Fields specific to the PDU type */
+ uint8_t other_b[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Fields specific to the PDU type */
+ uint8_t other_c[4];
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Fields specific to the PDU type */
+ uint8_t other_d[16];
+};
+
+/**
+ * iSCSI login request basic header segment
+ *
+ */
+struct iscsi_bhs_login_request {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Maximum supported version number */
+ uint8_t version_max;
+ /** Minimum supported version number */
+ uint8_t version_min;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Initiator session ID (IANA format) enterprise number and flags */
+ uint32_t isid_iana_en;
+ /** Initiator session ID (IANA format) qualifier */
+ uint16_t isid_iana_qual;
+ /** Target session identifying handle */
+ uint16_t tsih;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Connection ID */
+ uint16_t cid;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Command sequence number */
+ uint32_t cmdsn;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** Reserved */
+ uint8_t reserved_b[16];
+};
+
+/** Login request opcode */
+#define ISCSI_OPCODE_LOGIN_REQUEST 0x03
+
+/** Willingness to transition to next stage */
+#define ISCSI_LOGIN_FLAG_TRANSITION 0x80
+
+/** Key=value pairs continued in subsequent request */
+#define ISCSI_LOGIN_FLAG_CONTINUE 0x40
+
+/* Current stage values and mask */
+#define ISCSI_LOGIN_CSG_MASK 0x0c
+#define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
+#define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
+#define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
+
+/* Next stage values and mask */
+#define ISCSI_LOGIN_NSG_MASK 0x03
+#define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
+#define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
+#define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
+
+/** ISID IANA format marker */
+#define ISCSI_ISID_IANA 0x40000000
+
+/** Fen Systems Ltd. IANA enterprise number
+ *
+ * Permission is hereby granted to use Fen Systems Ltd.'s IANA
+ * enterprise number with this iSCSI implementation.
+ */
+#define IANA_EN_FEN_SYSTEMS 10019
+
+/**
+ * iSCSI login response basic header segment
+ *
+ */
+struct iscsi_bhs_login_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Maximum supported version number */
+ uint8_t version_max;
+ /** Minimum supported version number */
+ uint8_t version_min;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Initiator session ID (IANA format) enterprise number and flags */
+ uint32_t isid_iana_en;
+ /** Initiator session ID (IANA format) qualifier */
+ uint16_t isid_iana_qual;
+ /** Target session identifying handle */
+ uint16_t tsih;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Reserved */
+ uint32_t reserved_a;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Status class */
+ uint8_t status_class;
+ /** Status detail */
+ uint8_t status_detail;
+ /** Reserved */
+ uint8_t reserved_b[10];
+};
+
+/** Login response opcode */
+#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
+
+/* Login response status codes */
+#define ISCSI_STATUS_SUCCESS 0x00
+#define ISCSI_STATUS_REDIRECT 0x01
+#define ISCSI_STATUS_INITIATOR_ERROR 0x02
+#define ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION 0x01
+#define ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION 0x02
+#define ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND 0x03
+#define ISCSI_STATUS_INITIATOR_ERROR_REMOVED 0x04
+#define ISCSI_STATUS_TARGET_ERROR 0x03
+
+/**
+ * iSCSI SCSI command basic header segment
+ *
+ */
+struct iscsi_bhs_scsi_command {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** SCSI Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Expected data transfer length */
+ uint32_t exp_len;
+ /** Command sequence number */
+ uint32_t cmdsn;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** SCSI Command Descriptor Block (CDB) */
+ union scsi_cdb cdb;
+};
+
+/** SCSI command opcode */
+#define ISCSI_OPCODE_SCSI_COMMAND 0x01
+
+/** Command will read data */
+#define ISCSI_COMMAND_FLAG_READ 0x40
+
+/** Command will write data */
+#define ISCSI_COMMAND_FLAG_WRITE 0x20
+
+/* Task attributes */
+#define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
+#define ISCSI_COMMAND_ATTR_SIMPLE 0x01
+#define ISCSI_COMMAND_ATTR_ORDERED 0x02
+#define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
+#define ISCSI_COMMAND_ATTR_ACA 0x04
+
+/**
+ * iSCSI SCSI response basic header segment
+ *
+ */
+struct iscsi_bhs_scsi_response {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Response code */
+ uint8_t response;
+ /** SCSI status code */
+ uint8_t status;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Reserved */
+ uint8_t reserved_a[8];
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** SNACK tag */
+ uint32_t snack;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Expected data sequence number */
+ uint32_t expdatasn;
+ /** Reserved */
+ uint8_t reserved_b[8];
+};
+
+/** SCSI response opcode */
+#define ISCSI_OPCODE_SCSI_RESPONSE 0x21
+
+/** SCSI command completed at target */
+#define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
+
+/** SCSI target failure */
+#define ISCSI_RESPONSE_TARGET_FAILURE 0x01
+
+/** SCSI sense response code offset
+ *
+ * The SCSI response may contain unsolicited sense data in the data
+ * segment. If it does, this is the offset to the sense response code
+ * byte, which is the only byte we care about.
+ */
+#define ISCSI_SENSE_RESPONSE_CODE_OFFSET 2
+
+/**
+ * iSCSI data-in basic header segment
+ *
+ */
+struct iscsi_bhs_data_in {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** SCSI status code */
+ uint8_t status;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** Data sequence number */
+ uint32_t datasn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Residual count */
+ uint32_t residual_count;
+};
+
+/** Data-in opcode */
+#define ISCSI_OPCODE_DATA_IN 0x25
+
+/** Data requires acknowledgement */
+#define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
+
+/** Data overflow occurred */
+#define ISCSI_DATA_FLAG_OVERFLOW 0x04
+
+/** Data underflow occurred */
+#define ISCSI_DATA_FLAG_UNDERFLOW 0x02
+
+/** SCSI status code and overflow/underflow flags are valid */
+#define ISCSI_DATA_FLAG_STATUS 0x01
+
+/**
+ * iSCSI data-out basic header segment
+ *
+ */
+struct iscsi_bhs_data_out {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Reserved */
+ uint32_t reserved_b;
+ /** Expected status sequence number */
+ uint32_t expstatsn;
+ /** Reserved */
+ uint32_t reserved_c;
+ /** Data sequence number */
+ uint32_t datasn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Reserved */
+ uint32_t reserved_d;
+};
+
+/** Data-out opcode */
+#define ISCSI_OPCODE_DATA_OUT 0x05
+
+/**
+ * iSCSI request to transfer basic header segment
+ *
+ */
+struct iscsi_bhs_r2t {
+ /** Opcode */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Reserved */
+ uint16_t reserved_a;
+ /** Segment lengths */
+ union iscsi_segment_lengths lengths;
+ /** Logical Unit Number */
+ struct scsi_lun lun;
+ /** Initiator Task Tag */
+ uint32_t itt;
+ /** Target Transfer Tag */
+ uint32_t ttt;
+ /** Status sequence number */
+ uint32_t statsn;
+ /** Expected command sequence number */
+ uint32_t expcmdsn;
+ /** Maximum command sequence number */
+ uint32_t maxcmdsn;
+ /** R2T sequence number */
+ uint32_t r2tsn;
+ /** Buffer offset */
+ uint32_t offset;
+ /** Desired data transfer length */
+ uint32_t len;
+};
+
+/** R2T opcode */
+#define ISCSI_OPCODE_R2T 0x31
+
+/**
+ * An iSCSI basic header segment
+ */
+union iscsi_bhs {
+ struct iscsi_bhs_common common;
+ struct iscsi_bhs_common_response common_response;
+ struct iscsi_bhs_login_request login_request;
+ struct iscsi_bhs_login_response login_response;
+ struct iscsi_bhs_scsi_command scsi_command;
+ struct iscsi_bhs_scsi_response scsi_response;
+ struct iscsi_bhs_data_in data_in;
+ struct iscsi_bhs_data_out data_out;
+ struct iscsi_bhs_r2t r2t;
+ unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
+};
+
+/** State of an iSCSI TX engine */
+enum iscsi_tx_state {
+ /** Nothing to send */
+ ISCSI_TX_IDLE = 0,
+ /** Sending the basic header segment */
+ ISCSI_TX_BHS,
+ /** Sending the additional header segment */
+ ISCSI_TX_AHS,
+ /** Sending the data segment */
+ ISCSI_TX_DATA,
+ /** Sending the data segment padding */
+ ISCSI_TX_DATA_PADDING,
+};
+
+/** State of an iSCSI RX engine */
+enum iscsi_rx_state {
+ /** Receiving the basic header segment */
+ ISCSI_RX_BHS = 0,
+ /** Receiving the additional header segment */
+ ISCSI_RX_AHS,
+ /** Receiving the data segment */
+ ISCSI_RX_DATA,
+ /** Receiving the data segment padding */
+ ISCSI_RX_DATA_PADDING,
+};
+
+/** An iSCSI session */
+struct iscsi_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Transport-layer socket */
+ struct xfer_interface socket;
+
+ /** Target address */
+ char *target_address;
+ /** Target port */
+ unsigned int target_port;
+ /** Target IQN */
+ char *target_iqn;
+ /** Logical Unit Number (LUN) */
+ struct scsi_lun lun;
+ /** Target socket address (recorded only for iBFT) */
+ struct sockaddr target_sockaddr;
+
+ /** Session status
+ *
+ * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
+ * constants.
+ */
+ int status;
+ /** Retry count
+ *
+ * Number of times that the connection has been retried.
+ * Reset upon a successful connection.
+ */
+ int retry_count;
+
+ /** Initiator username (if any) */
+ char *initiator_username;
+ /** Initiator password (if any) */
+ char *initiator_password;
+ /** Target username (if any) */
+ char *target_username;
+ /** Target password (if any) */
+ char *target_password;
+ /** CHAP challenge (for target auth only)
+ *
+ * This is a block of random data; the first byte is used as
+ * the CHAP identifier (CHAP_I) and the remainder as the CHAP
+ * challenge (CHAP_C).
+ */
+ unsigned char chap_challenge[17];
+ /** CHAP response (used for both initiator and target auth) */
+ struct chap_response chap;
+
+ /** Target session identifying handle
+ *
+ * This is assigned by the target when we first log in, and
+ * must be reused on subsequent login attempts.
+ */
+ uint16_t tsih;
+ /** Initiator task tag
+ *
+ * This is the tag of the current command. It is incremented
+ * whenever a new command is started.
+ */
+ uint32_t itt;
+ /** Target transfer tag
+ *
+ * This is the tag attached to a sequence of data-out PDUs in
+ * response to an R2T.
+ */
+ uint32_t ttt;
+ /**
+ * Transfer offset
+ *
+ * This is the offset for an in-progress sequence of data-out
+ * PDUs in response to an R2T.
+ */
+ uint32_t transfer_offset;
+ /**
+ * Transfer length
+ *
+ * This is the length for an in-progress sequence of data-out
+ * PDUs in response to an R2T.
+ */
+ uint32_t transfer_len;
+ /** Command sequence number
+ *
+ * This is the sequence number of the current command, used to
+ * fill out the CmdSN field in iSCSI request PDUs. It is
+ * updated with the value of the ExpCmdSN field whenever we
+ * receive an iSCSI response PDU containing such a field.
+ */
+ uint32_t cmdsn;
+ /** Status sequence number
+ *
+ * This is the most recent status sequence number present in
+ * the StatSN field of an iSCSI response PDU containing such a
+ * field. Whenever we send an iSCSI request PDU, we fill out
+ * the ExpStatSN field with this value plus one.
+ */
+ uint32_t statsn;
+
+ /** Basic header segment for current TX PDU */
+ union iscsi_bhs tx_bhs;
+ /** State of the TX engine */
+ enum iscsi_tx_state tx_state;
+ /** TX process */
+ struct process process;
+
+ /** Basic header segment for current RX PDU */
+ union iscsi_bhs rx_bhs;
+ /** State of the RX engine */
+ enum iscsi_rx_state rx_state;
+ /** Byte offset within the current RX state */
+ size_t rx_offset;
+ /** Length of the current RX state */
+ size_t rx_len;
+ /** Buffer for received data (not always used) */
+ void *rx_buffer;
+
+ /** Current SCSI command
+ *
+ * Set to NULL when command is complete.
+ */
+ struct scsi_command *command;
+ /** Instant return code
+ *
+ * Set to a non-zero value if all requests should return
+ * immediately. This can be used to e.g. avoid retrying
+ * logins that are doomed to fail authentication.
+ */
+ int instant_rc;
+};
+
+/** iSCSI session is currently in the security negotiation phase */
+#define ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE \
+ ( ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION | \
+ ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION )
+
+/** iSCSI session is currently in the operational parameter
+ * negotiation phase
+ */
+#define ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE \
+ ( ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION | \
+ ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE )
+
+/** iSCSI session is currently in the full feature phase */
+#define ISCSI_STATUS_FULL_FEATURE_PHASE ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE
+
+/** Mask for all iSCSI session phases */
+#define ISCSI_STATUS_PHASE_MASK ( ISCSI_LOGIN_CSG_MASK | ISCSI_LOGIN_NSG_MASK )
+
+/** iSCSI session needs to send the initial security negotiation strings */
+#define ISCSI_STATUS_STRINGS_SECURITY 0x0100
+
+/** iSCSI session needs to send the CHAP_A string */
+#define ISCSI_STATUS_STRINGS_CHAP_ALGORITHM 0x0200
+
+/** iSCSI session needs to send the CHAP response */
+#define ISCSI_STATUS_STRINGS_CHAP_RESPONSE 0x0400
+
+/** iSCSI session needs to send the mutual CHAP challenge */
+#define ISCSI_STATUS_STRINGS_CHAP_CHALLENGE 0x0800
+
+/** iSCSI session needs to send the operational negotiation strings */
+#define ISCSI_STATUS_STRINGS_OPERATIONAL 0x1000
+
+/** Mask for all iSCSI "needs to send" flags */
+#define ISCSI_STATUS_STRINGS_MASK 0xff00
+
+/** Target has requested forward (initiator) authentication */
+#define ISCSI_STATUS_AUTH_FORWARD_REQUIRED 0x00010000
+
+/** Initiator requires target (reverse) authentication */
+#define ISCSI_STATUS_AUTH_REVERSE_REQUIRED 0x00020000
+
+/** Target authenticated itself correctly */
+#define ISCSI_STATUS_AUTH_REVERSE_OK 0x00040000
+
+/** Maximum number of retries at connecting */
+#define ISCSI_MAX_RETRIES 2
+
+extern int iscsi_attach ( struct scsi_device *scsi, const char *root_path );
+extern void iscsi_detach ( struct scsi_device *scsi );
+extern const char * iscsi_initiator_iqn ( void );
+
+#endif /* _GPXE_ISCSI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/job.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/job.h
new file mode 100644
index 0000000..f1bcada
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/job.h
@@ -0,0 +1,169 @@
+#ifndef _GPXE_JOB_H
+#define _GPXE_JOB_H
+
+/** @file
+ *
+ * Job control interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <gpxe/interface.h>
+
+/** Job progress */
+struct job_progress {
+ /** Amount of operation completed so far
+ *
+ * The units for this quantity are arbitrary. @c completed
+ * divded by @total should give something which approximately
+ * represents the progress through the operation. For a
+ * download operation, using byte counts would make sense.
+ */
+ unsigned long completed;
+ /** Total operation size
+ *
+ * See @c completed. A zero value means "total size unknown"
+ * and is explcitly permitted; users should take this into
+ * account before calculating @c completed/total.
+ */
+ unsigned long total;
+};
+
+struct job_interface;
+
+/** Job control interface operations */
+struct job_interface_operations {
+ /** Job completed
+ *
+ * @v job Job control interface
+ * @v rc Overall job status code
+ */
+ void ( * done ) ( struct job_interface *job, int rc );
+ /** Abort job
+ *
+ * @v job Job control interface
+ */
+ void ( * kill ) ( struct job_interface *job );
+ /** Get job progress
+ *
+ * @v job Job control interface
+ * @v progress Progress data to fill in
+ */
+ void ( * progress ) ( struct job_interface *job,
+ struct job_progress *progress );
+};
+
+/** A job control interface */
+struct job_interface {
+ /** Generic object communication interface */
+ struct interface intf;
+ /** Operations for received messages */
+ struct job_interface_operations *op;
+};
+
+extern struct job_interface null_job;
+extern struct job_interface_operations null_job_ops;
+
+extern void job_done ( struct job_interface *job, int rc );
+extern void job_kill ( struct job_interface *job );
+extern void job_progress ( struct job_interface *job,
+ struct job_progress *progress );
+
+extern void ignore_job_done ( struct job_interface *job, int rc );
+extern void ignore_job_kill ( struct job_interface *job );
+extern void ignore_job_progress ( struct job_interface *job,
+ struct job_progress *progress );
+
+/**
+ * Initialise a job control interface
+ *
+ * @v job Job control interface
+ * @v op Job control interface operations
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void job_init ( struct job_interface *job,
+ struct job_interface_operations *op,
+ struct refcnt *refcnt ) {
+ job->intf.dest = &null_job.intf;
+ job->intf.refcnt = refcnt;
+ job->op = op;
+}
+
+/**
+ * Get job control interface from generic object communication interface
+ *
+ * @v intf Generic object communication interface
+ * @ret job Job control interface
+ */
+static inline __attribute__ (( always_inline )) struct job_interface *
+intf_to_job ( struct interface *intf ) {
+ return container_of ( intf, struct job_interface, intf );
+}
+
+/**
+ * Get reference to destination job control interface
+ *
+ * @v job Job control interface
+ * @ret dest Destination interface
+ */
+static inline __attribute__ (( always_inline )) struct job_interface *
+job_get_dest ( struct job_interface *job ) {
+ return intf_to_job ( intf_get ( job->intf.dest ) );
+}
+
+/**
+ * Drop reference to job control interface
+ *
+ * @v job Job control interface
+ */
+static inline __attribute__ (( always_inline )) void
+job_put ( struct job_interface *job ) {
+ intf_put ( &job->intf );
+}
+
+/**
+ * Plug a job control interface into a new destination interface
+ *
+ * @v job Job control interface
+ * @v dest New destination interface
+ */
+static inline void job_plug ( struct job_interface *job,
+ struct job_interface *dest ) {
+ plug ( &job->intf, &dest->intf );
+}
+
+/**
+ * Plug two job control interfaces together
+ *
+ * @v a Job control interface A
+ * @v b Job control interface B
+ */
+static inline void job_plug_plug ( struct job_interface *a,
+ struct job_interface *b ) {
+ plug_plug ( &a->intf, &b->intf );
+}
+
+/**
+ * Unplug a job control interface
+ *
+ * @v job Job control interface
+ */
+static inline void job_unplug ( struct job_interface *job ) {
+ plug ( &job->intf, &null_job.intf );
+}
+
+/**
+ * Stop using a job control interface
+ *
+ * @v job Job control interface
+ *
+ * After calling this method, no further messages will be received via
+ * the interface.
+ */
+static inline void job_nullify ( struct job_interface *job ) {
+ job->op = &null_job_ops;
+};
+
+#endif /* _GPXE_JOB_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/keys.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/keys.h
new file mode 100644
index 0000000..25bc9bc
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/keys.h
@@ -0,0 +1,81 @@
+#ifndef _GPXE_KEYS_H
+#define _GPXE_KEYS_H
+
+/** @file
+ *
+ * Key definitions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * Symbolic names for some standard ASCII characters
+ *
+ */
+
+#define NUL 0x00
+#define CTRL_A 0x01
+#define CTRL_B 0x02
+#define CTRL_C 0x03
+#define CTRL_D 0x04
+#define CTRL_E 0x05
+#define CTRL_F 0x06
+#define CTRL_G 0x07
+#define CTRL_H 0x08
+#define CTRL_I 0x09
+#define CTRL_J 0x0a
+#define CTRL_K 0x0b
+#define CTRL_L 0x0c
+#define CTRL_M 0x0d
+#define CTRL_N 0x0e
+#define CTRL_O 0x0f
+#define CTRL_P 0x10
+#define CTRL_Q 0x11
+#define CTRL_R 0x12
+#define CTRL_S 0x13
+#define CTRL_T 0x14
+#define CTRL_U 0x15
+#define CTRL_V 0x16
+#define CTRL_W 0x17
+#define CTRL_X 0x18
+#define CTRL_Y 0x19
+#define CTRL_Z 0x1a
+
+#define BACKSPACE CTRL_H
+#define TAB CTRL_I
+#define LF CTRL_J
+#define CR CTRL_M
+#define ESC 0x1b
+
+/*
+ * Special keys outside the normal ASCII range
+ *
+ *
+ * The names are chosen to match those used by curses. The values are
+ * chosen to facilitate easy conversion from a received ANSI escape
+ * sequence to a KEY_XXX constant.
+ */
+
+#define KEY_ANSI( n, terminator ) ( 0x100 * ( (n) + 1 ) + (terminator) )
+
+#define KEY_MIN 0x101
+#define KEY_UP KEY_ANSI ( 0, 'A' ) /**< Up arrow */
+#define KEY_DOWN KEY_ANSI ( 0, 'B' ) /**< Down arrow */
+#define KEY_RIGHT KEY_ANSI ( 0, 'C' ) /**< Right arrow */
+#define KEY_LEFT KEY_ANSI ( 0, 'D' ) /**< Left arrow */
+#define KEY_END KEY_ANSI ( 0, 'F' ) /**< End */
+#define KEY_HOME KEY_ANSI ( 0, 'H' ) /**< Home */
+#define KEY_IC KEY_ANSI ( 2, '~' ) /**< Insert */
+#define KEY_DC KEY_ANSI ( 3, '~' ) /**< Delete */
+#define KEY_PPAGE KEY_ANSI ( 5, '~' ) /**< Page up */
+#define KEY_NPAGE KEY_ANSI ( 6, '~' ) /**< Page down */
+#define KEY_F8 KEY_ANSI ( 19, '~' ) /**< F8 (for PXE) */
+
+/* Not in the [KEY_MIN,KEY_MAX] range; terminals seem to send these as
+ * normal ASCII values.
+ */
+#define KEY_BACKSPACE BACKSPACE
+#define KEY_ENTER LF
+
+#endif /* _GPXE_KEYS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/linebuf.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/linebuf.h
new file mode 100644
index 0000000..cfa2147
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/linebuf.h
@@ -0,0 +1,30 @@
+#ifndef _GPXE_LINEBUF_H
+#define _GPXE_LINEBUF_H
+
+/** @file
+ *
+ * Line buffering
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** A line buffer */
+struct line_buffer {
+ /** Current string in the buffer */
+ char *data;
+ /** Length of current string, excluding the terminating NUL */
+ size_t len;
+ /** String is ready to read */
+ int ready;
+};
+
+extern char * buffered_line ( struct line_buffer *linebuf );
+extern ssize_t line_buffer ( struct line_buffer *linebuf,
+ const char *data, size_t len );
+extern void empty_line_buffer ( struct line_buffer *linebuf );
+
+#endif /* _GPXE_LINEBUF_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/linux_compat.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/linux_compat.h
new file mode 100644
index 0000000..577512e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/linux_compat.h
@@ -0,0 +1,27 @@
+#ifndef _GPXE_LINUX_COMPAT_H
+#define _GPXE_LINUX_COMPAT_H
+
+/** @file
+ *
+ * Linux code compatibility
+ *
+ * This file exists to ease the building of Linux source code within
+ * gPXE. This is intended to facilitate quick testing; it is not
+ * intended to be a substitute for proper porting.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <gpxe/bitops.h>
+
+#define __init
+#define __exit
+#define __initdata
+#define __exitdata
+#define printk printf
+
+#endif /* _GPXE_LINUX_COMPAT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/login_ui.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/login_ui.h
new file mode 100644
index 0000000..4196f7b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/login_ui.h
@@ -0,0 +1,14 @@
+#ifndef _GPXE_LOGIN_UI_H
+#define _GPXE_LOGIN_UI_H
+
+/** @file
+ *
+ * Login UI
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int login_ui ( void );
+
+#endif /* _GPXE_LOGIN_UI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/malloc.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/malloc.h
new file mode 100644
index 0000000..c02a866
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/malloc.h
@@ -0,0 +1,59 @@
+#ifndef _GPXE_MALLOC_H
+#define _GPXE_MALLOC_H
+
+#include <stdint.h>
+
+/** @file
+ *
+ * Dynamic memory allocation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * Prototypes for the standard functions (malloc() et al) are in
+ * stdlib.h. Include <gpxe/malloc.h> only if you need the
+ * non-standard functions, such as malloc_dma().
+ *
+ */
+#include <stdlib.h>
+
+extern size_t freemem;
+
+extern void * __malloc alloc_memblock ( size_t size, size_t align );
+extern void free_memblock ( void *ptr, size_t size );
+extern void mpopulate ( void *start, size_t len );
+extern void mdumpfree ( void );
+
+/**
+ * Allocate memory for DMA
+ *
+ * @v size Requested size
+ * @v align Physical alignment
+ * @ret ptr Memory, or NULL
+ *
+ * Allocates physically-aligned memory for DMA.
+ *
+ * @c align must be a power of two. @c size may not be zero.
+ */
+static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
+ return alloc_memblock ( size, phys_align );
+}
+
+/**
+ * Free memory allocated with malloc_dma()
+ *
+ * @v ptr Memory allocated by malloc_dma(), or NULL
+ * @v size Size of memory, as passed to malloc_dma()
+ *
+ * Memory allocated with malloc_dma() can only be freed with
+ * free_dma(); it cannot be freed with the standard free().
+ *
+ * If @c ptr is NULL, no action is taken.
+ */
+static inline void free_dma ( void *ptr, size_t size ) {
+ free_memblock ( ptr, size );
+}
+
+#endif /* _GPXE_MALLOC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/mca.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/mca.h
new file mode 100644
index 0000000..da9d73e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/mca.h
@@ -0,0 +1,108 @@
+/*
+ * MCA bus driver code
+ *
+ * Abstracted from 3c509.c.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef MCA_H
+#define MCA_H
+
+#include <gpxe/isa_ids.h>
+#include <gpxe/device.h>
+#include <gpxe/tables.h>
+
+/*
+ * MCA constants
+ *
+ */
+#define MCA_MOTHERBOARD_SETUP_REG 0x94
+#define MCA_ADAPTER_SETUP_REG 0x96
+#define MCA_MAX_SLOT_NR 0x07 /* Must be 2^n - 1 */
+#define MCA_POS_REG(n) (0x100+(n))
+
+/* Is there a standard that would define this? */
+#define GENERIC_MCA_VENDOR ISA_VENDOR ( 'M', 'C', 'A' )
+
+/** An MCA device ID list entry */
+struct mca_device_id {
+ /** Name */
+ const char *name;
+ /** Device ID */
+ uint16_t id;
+};
+
+/** An MCA device */
+struct mca_device {
+ /** Generic device */
+ struct device dev;
+ /** Slot number */
+ unsigned int slot;
+ /** POS register values */
+ unsigned char pos[8];
+ /** Driver for this device */
+ struct mca_driver *driver;
+ /** Driver-private data
+ *
+ * Use mca_set_drvdata() and mca_get_drvdata() to access
+ * this field.
+ */
+ void *priv;
+ /** Driver name */
+ const char *driver_name;
+};
+
+#define MCA_ID(mca) ( ( (mca)->pos[1] << 8 ) + (mca)->pos[0] )
+
+/** An MCA driver */
+struct mca_driver {
+ /** MCA ID table */
+ struct mca_device_id *ids;
+ /** Number of entries in MCA ID table */
+ unsigned int id_count;
+ /**
+ * Probe device
+ *
+ * @v mca MCA device
+ * @v id Matching entry in ID table
+ * @ret rc Return status code
+ */
+ int ( * probe ) ( struct mca_device *mca,
+ const struct mca_device_id *id );
+ /**
+ * Remove device
+ *
+ * @v mca MCA device
+ */
+ void ( * remove ) ( struct mca_device *mca );
+};
+
+/** MCA driver table */
+#define MCA_DRIVERS __table ( struct mca_driver, "mca_drivers" )
+
+/** Declare an MCA driver */
+#define __mca_driver __table_entry ( MCA_DRIVERS, 01 )
+
+/**
+ * Set MCA driver-private data
+ *
+ * @v mca MCA device
+ * @v priv Private data
+ */
+static inline void mca_set_drvdata ( struct mca_device *mca, void *priv ) {
+ mca->priv = priv;
+}
+
+/**
+ * Get MCA driver-private data
+ *
+ * @v mca MCA device
+ * @ret priv Private data
+ */
+static inline void * mca_get_drvdata ( struct mca_device *mca ) {
+ return mca->priv;
+}
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/md5.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/md5.h
new file mode 100644
index 0000000..03d65c1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/md5.h
@@ -0,0 +1,24 @@
+#ifndef _GPXE_MD5_H
+#define _GPXE_MD5_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct digest_algorithm;
+
+#include <stdint.h>
+
+#define MD5_DIGEST_SIZE 16
+#define MD5_BLOCK_WORDS 16
+#define MD5_HASH_WORDS 4
+
+struct md5_ctx {
+ u32 hash[MD5_HASH_WORDS];
+ u32 block[MD5_BLOCK_WORDS];
+ u64 byte_count;
+};
+
+#define MD5_CTX_SIZE sizeof ( struct md5_ctx )
+
+extern struct digest_algorithm md5_algorithm;
+
+#endif /* _GPXE_MD5_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/memmap.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/memmap.h
new file mode 100644
index 0000000..dc5bec3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/memmap.h
@@ -0,0 +1,36 @@
+#ifndef _GPXE_MEMMAP_H
+#define _GPXE_MEMMAP_H
+
+#include <stdint.h>
+
+/**
+ * @file
+ *
+ * Memory mapping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A usable memory region */
+struct memory_region {
+ /** Physical start address */
+ uint64_t start;
+ /** Physical end address */
+ uint64_t end;
+};
+
+/** Maximum number of memory regions we expect to encounter */
+#define MAX_MEMORY_REGIONS 8
+
+/** A memory map */
+struct memory_map {
+ /** Memory regions */
+ struct memory_region regions[MAX_MEMORY_REGIONS];
+ /** Number of used regions */
+ unsigned int count;
+};
+
+extern void get_memmap ( struct memory_map *memmap );
+
+#endif /* _GPXE_MEMMAP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/monojob.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/monojob.h
new file mode 100644
index 0000000..35ff4fd
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/monojob.h
@@ -0,0 +1,17 @@
+#ifndef _GPXE_MONOJOB_H
+#define _GPXE_MONOJOB_H
+
+/** @file
+ *
+ * Single foreground job
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct job_interface;
+
+extern struct job_interface monojob;
+extern int monojob_wait ( const char *string );
+
+#endif /* _GPXE_MONOJOB_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/net80211.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/net80211.h
new file mode 100644
index 0000000..d924941
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/net80211.h
@@ -0,0 +1,1016 @@
+#ifndef _GPXE_NET80211_H
+#define _GPXE_NET80211_H
+
+#include <gpxe/process.h>
+#include <gpxe/ieee80211.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/rc80211.h>
+
+/** @file
+ *
+ * The gPXE 802.11 MAC layer.
+ */
+
+/*
+ * Major things NOT YET supported:
+ * - any type of security
+ * - 802.11n
+ *
+ * Major things that probably will NEVER be supported, barring a
+ * compelling use case and/or corporate sponsorship:
+ * - QoS
+ * - 802.1X authentication ("WPA Enterprise")
+ * - Contention-free periods
+ * - "ad-hoc" networks (IBSS), monitor mode, host AP mode
+ * - hidden networks on the 5GHz band due to regulatory issues
+ * - spectrum management on the 5GHz band (TPC and DFS), as required
+ * in some non-US regulatory domains
+ * - Clause 14 PHYs (Frequency-Hopping Spread Spectrum on 2.4GHz)
+ * and Clause 16 PHYs (infrared) - I'm not aware of any real-world
+ * use of these.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* All 802.11 devices are handled using a generic "802.11 device"
+ net_device, with a link in its `priv' field to a net80211_device
+ which we use to handle 802.11-specific details. */
+
+
+/** @defgroup net80211_band RF bands on which an 802.11 device can transmit */
+/** @{ */
+
+/** The 2.4 GHz ISM band, unlicensed in most countries */
+#define NET80211_BAND_2GHZ 0
+/** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */
+#define NET80211_BAND_5GHZ 1
+/** Number of RF bands */
+#define NET80211_NR_BANDS 2
+
+/** Bitmask for the 2GHz band */
+#define NET80211_BAND_BIT_2GHZ (1 << 0)
+/** Bitmask for the 5GHz band */
+#define NET80211_BAND_BIT_5GHZ (1 << 1)
+
+/** @} */
+
+
+/** @defgroup net80211_mode 802.11 operation modes supported by hardware */
+/** @{ */
+
+/** 802.11a: 54 Mbps operation using OFDM signaling on the 5GHz band */
+#define NET80211_MODE_A (1 << 0)
+
+/** 802.11b: 1-11 Mbps operation using DSSS/CCK signaling on the 2.4GHz band */
+#define NET80211_MODE_B (1 << 1)
+
+/** 802.11g: 54 Mbps operation using ERP/OFDM signaling on the 2.4GHz band */
+#define NET80211_MODE_G (1 << 2)
+
+/** 802.11n: High-rate operation using MIMO technology on 2.4GHz or 5GHz */
+#define NET80211_MODE_N (1 << 3)
+
+/** @} */
+
+
+/** @defgroup net80211_cfg Constants for the net80211 config callback */
+/** @{ */
+
+/** Channel choice (@c dev->channel) or regulatory parameters have changed */
+#define NET80211_CFG_CHANNEL (1 << 0)
+
+/** Requested transmission rate (@c dev->rate) has changed */
+#define NET80211_CFG_RATE (1 << 1)
+
+/** Association has been established with a new BSS (@c dev->bssid) */
+#define NET80211_CFG_ASSOC (1 << 2)
+
+/** Low-level link parameters (short preamble, protection, etc) have changed */
+#define NET80211_CFG_PHY_PARAMS (1 << 3)
+
+/** @} */
+
+
+/** An 802.11 security handshaking protocol */
+enum net80211_security_proto {
+ /** No security handshaking
+ *
+ * This might be used with an open network or with WEP, as
+ * WEP does not have a cryptographic handshaking phase.
+ */
+ NET80211_SECPROT_NONE = 0,
+
+ /** Pre-shared key handshaking
+ *
+ * This implements the "WPA Personal" handshake. 802.1X
+ * authentication is not performed -- the user supplies a
+ * pre-shared key directly -- but there is a 4-way handshake
+ * between client and AP to verify that both have the same key
+ * without revealing the contents of that key.
+ */
+ NET80211_SECPROT_PSK = 1,
+
+ /** Full EAP 802.1X handshaking
+ *
+ * This implements the "WPA Enterprise" handshake, connecting
+ * to an 802.1X authentication server to provide credentials
+ * and receive a pairwise master key (PMK), which is then used
+ * in the same 4-way handshake as the PSK method.
+ */
+ NET80211_SECPROT_EAP = 2,
+};
+
+
+/** An 802.11 data encryption algorithm */
+enum net80211_crypto_alg {
+ /** No security, an "Open" network */
+ NET80211_CRYPT_NONE = 0,
+
+ /** Network protected with WEP (awful RC4-based system)
+ *
+ * WEP uses a naive application of RC4, with a monotonically
+ * increasing initialization vector that is prepended to the
+ * key to initialize the RC4 keystream. It is highly insecure
+ * and can be completely cracked or subverted using automated,
+ * robust, freely available tools (aircrack-ng) in minutes.
+ *
+ * 40-bit and 104-bit WEP are differentiated only by the size
+ * of the key. They may be advertised as 64-bit and 128-bit,
+ * counting the non-random IV as part of the key bits.
+ */
+ NET80211_CRYPT_WEP = 1,
+
+ /** Network protected with TKIP (better RC4-based system)
+ *
+ * Usually known by its trade name of WPA (Wi-Fi Protected
+ * Access), TKIP implements a message integrity code (MIC)
+ * called Michael, a timestamp counter for replay prevention,
+ * and a key mixing function that together remove almost all
+ * the security problems with WEP. Countermeasures are
+ * implemented to prevent high data-rate attacks.
+ *
+ * There exists one known attack on TKIP, that allows one to
+ * send between 7 and 15 arbitrary short data packets on a
+ * QoS-enabled network given about an hour of data
+ * gathering. Since gPXE does not support QoS for 802.11
+ * networks, this is not a threat to us. The only other method
+ * is a brute-force passphrase attack.
+ */
+ NET80211_CRYPT_TKIP = 2,
+
+ /** Network protected with CCMP (AES-based system)
+ *
+ * Often called WPA2 in commerce, or RSNA (Robust Security
+ * Network Architecture) in the 802.11 standard, CCMP is
+ * highly secure and does not have any known attack vectors.
+ * Since it is based on a block cipher, the statistical
+ * correlation and "chopchop" attacks used with great success
+ * against WEP and minor success against TKIP fail.
+ */
+ NET80211_CRYPT_CCMP = 3,
+};
+
+
+/** @defgroup net80211_state Bits for the 802.11 association state field */
+/** @{ */
+
+/** An error code indicating the failure mode, or 0 if successful */
+#define NET80211_STATUS_MASK 0x7F
+
+/** Whether the error code provided is a "reason" code, not a "status" code */
+#define NET80211_IS_REASON 0x80
+
+/** Whether we have found the network we will be associating with */
+#define NET80211_PROBED (1 << 8)
+
+/** Whether we have successfully authenticated with the network
+ *
+ * This usually has nothing to do with actual security; it is a
+ * holdover from older 802.11 implementation ideas.
+ */
+#define NET80211_AUTHENTICATED (1 << 9)
+
+/** Whether we have successfully associated with the network */
+#define NET80211_ASSOCIATED (1 << 10)
+
+/** Whether we have completed security handshaking with the network
+ *
+ * Once this is set, we can send data packets. For that reason this
+ * bit is set even in cases where no security handshaking is
+ * required.
+ */
+#define NET80211_CRYPTO_SYNCED (1 << 11)
+
+/** Whether the auto-association task is running */
+#define NET80211_WORKING (1 << 12)
+
+/** Whether the auto-association task is waiting for a reply from the AP */
+#define NET80211_WAITING (1 << 13)
+
+/** Whether the auto-association task should be suppressed
+ *
+ * This is set by the `iwlist' command so that it can open the device
+ * without starting another probe process that will interfere with its
+ * own.
+ */
+#define NET80211_NO_ASSOC (1 << 14)
+
+/** Whether this association was performed using a broadcast SSID
+ *
+ * If the user opened this device without netX/ssid set, the device's
+ * SSID will be set to that of the network it chooses to associate
+ * with, but the netX/ssid setting will remain blank. If we don't
+ * remember that we started from no specified SSID, it will appear
+ * every time settings are updated (e.g. after DHCP) that we need to
+ * reassociate due to the difference between the set SSID and our own.
+ */
+#define NET80211_AUTO_SSID (1 << 15)
+
+
+/** @} */
+
+
+/** @defgroup net80211_phy 802.11 physical layer flags */
+/** @{ */
+
+/** Whether to use RTS/CTS or CTS-to-self protection for transmissions
+ *
+ * Since the RTS or CTS is transmitted using 802.11b signaling, and
+ * includes a field indicating the amount of time that will be used by
+ * transmission of the following packet, this serves as an effective
+ * protection mechanism to avoid 802.11b clients interfering with
+ * 802.11g clients on mixed networks.
+ */
+#define NET80211_PHY_USE_PROTECTION (1 << 1)
+
+/** Whether to use 802.11b short preamble operation
+ *
+ * Short-preamble operation can moderately increase throughput on
+ * 802.11b networks operating between 2Mbps and 11Mbps. It is
+ * irrelevant for 802.11g data rates, since they use a different
+ * modulation scheme.
+ */
+#define NET80211_PHY_USE_SHORT_PREAMBLE (1 << 2)
+
+/** Whether to use 802.11g short slot operation
+ *
+ * This affects a low-level timing parameter of 802.11g transmissions.
+ */
+#define NET80211_PHY_USE_SHORT_SLOT (1 << 3)
+
+/** @} */
+
+
+/** The maximum number of TX rates we allow to be configured simultaneously */
+#define NET80211_MAX_RATES 16
+
+/** The maximum number of channels we allow to be configured simultaneously */
+#define NET80211_MAX_CHANNELS 32
+
+/** Seconds we'll wait to get all fragments of a packet */
+#define NET80211_FRAG_TIMEOUT 2
+
+/** The number of fragments we can receive at once
+ *
+ * The 802.11 standard requires that this be at least 3.
+ */
+#define NET80211_NR_CONCURRENT_FRAGS 3
+
+/** Maximum TX power to allow (dBm), if we don't get a regulatory hint */
+#define NET80211_REG_TXPOWER 20
+
+
+struct net80211_device;
+
+/** Operations that must be implemented by an 802.11 driver */
+struct net80211_device_operations {
+ /** Open 802.11 device
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX I/O buffers and enable the
+ * hardware to start transmitting and receiving packets on the
+ * channels its net80211_register() call indicated it could
+ * handle. It does not need to tune the antenna to receive
+ * packets on any particular channel.
+ */
+ int ( * open ) ( struct net80211_device *dev );
+
+ /** Close 802.11 network device
+ *
+ * @v dev 802.11 device
+ *
+ * This method should stop the flow of packets, and call
+ * net80211_tx_complete() for any packets remaining in the
+ * device's TX queue.
+ */
+ void ( * close ) ( struct net80211_device *dev );
+
+ /** Transmit packet on 802.11 network device
+ *
+ * @v dev 802.11 device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware to initiate
+ * transmission of the I/O buffer, using the channel and rate
+ * most recently indicated by an appropriate call to the
+ * @c config callback. The 802.11 layer guarantees that said
+ * channel and rate will be the same as those currently
+ * reflected in the fields of @a dev.
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the network layer's TX queue, and the driver must
+ * eventually call net80211_tx_complete() to free the buffer
+ * whether transmission succeeded or not. If this method
+ * returns failure, it will be interpreted as "failure to
+ * enqueue buffer" and the I/O buffer will be immediately
+ * released.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * transmit ) ( struct net80211_device *dev,
+ struct io_buffer *iobuf );
+
+ /** Poll for completed and received packets
+ *
+ * @v dev 802.11 device
+ *
+ * This method should cause the hardware to check for
+ * completed transmissions and received packets. Any received
+ * packets should be delivered via net80211_rx(), and
+ * completed transmissions should be indicated using
+ * net80211_tx_complete().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ void ( * poll ) ( struct net80211_device *dev );
+
+ /** Enable or disable interrupts
+ *
+ * @v dev 802.11 device
+ * @v enable If TRUE, interrupts should be enabled
+ */
+ void ( * irq ) ( struct net80211_device *dev, int enable );
+
+ /** Update hardware state to match 802.11 layer state
+ *
+ * @v dev 802.11 device
+ * @v changed Set of flags indicating what may have changed
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware state to be
+ * reinitialized from the state indicated in fields of
+ * net80211_device, in the areas indicated by bits set in
+ * @a changed. If the hardware is unable to do so, this method
+ * may return an appropriate error indication.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * config ) ( struct net80211_device *dev, int changed );
+};
+
+/** An 802.11 RF channel. */
+struct net80211_channel
+{
+ /** The band with which this channel is associated */
+ u8 band;
+
+ /** A channel number interpreted according to the band
+ *
+ * The 2.4GHz band uses channel numbers from 1-13 at 5MHz
+ * intervals such that channel 1 is 2407 MHz; channel 14,
+ * legal for use only in Japan, is defined separately as 2484
+ * MHz. Adjacent channels will overlap, since 802.11
+ * transmissions use a 20 MHz (4-channel) bandwidth. Most
+ * commonly, channels 1, 6, and 11 are used.
+ *
+ * The 5GHz band uses channel numbers derived directly from
+ * the frequency; channel 0 is 5000 MHz, and channels are
+ * always spaced 5 MHz apart. Channel numbers over 180 are
+ * relative to 4GHz instead of 5GHz, but these are rarely
+ * seen. Most channels are not legal for use.
+ */
+ u8 channel_nr;
+
+ /** The center frequency for this channel
+ *
+ * Currently a bandwidth of 20 MHz is assumed.
+ */
+ u16 center_freq;
+
+ /** Hardware channel value */
+ u16 hw_value;
+
+ /** Maximum allowable transmit power, in dBm
+ *
+ * This should be interpreted as EIRP, the power supplied to
+ * an ideal isotropic antenna in order to achieve the same
+ * average signal intensity as the real hardware at a
+ * particular distance.
+ *
+ * Currently no provision is made for directional antennas.
+ */
+ u8 maxpower;
+};
+
+/** Information on the capabilities of an 802.11 hardware device
+ *
+ * In its probe callback, an 802.11 driver must read hardware
+ * registers to determine the appropriate contents of this structure,
+ * fill it, and pass it to net80211_register() so that the 802.11
+ * layer knows how to treat the hardware and what to advertise as
+ * supported to access points.
+ */
+struct net80211_hw_info
+{
+ /** Default hardware MAC address.
+ *
+ * The user may change this by setting the @c netX/mac setting
+ * before the driver's open function is called; in that case
+ * the driver must set the hardware MAC address to the address
+ * contained in the wrapping net_device's ll_addr field, or if
+ * that is impossible, set that ll_addr field back to the
+ * unchangeable hardware MAC address.
+ */
+ u8 hwaddr[ETH_ALEN];
+
+ /** A bitwise OR of the 802.11x modes supported by this device */
+ int modes;
+
+ /** A bitwise OR of the bands on which this device can communicate */
+ int bands;
+
+ /** A set of flags indicating peculiarities of this device. */
+ enum {
+ /** Received frames include a frame check sequence. */
+ NET80211_HW_RX_HAS_FCS = (1 << 1),
+
+ /** Hardware doesn't support 2.4GHz short preambles
+ *
+ * This is only relevant for 802.11b operation above
+ * 2Mbps. All 802.11g devices support short preambles.
+ */
+ NET80211_HW_NO_SHORT_PREAMBLE = (1 << 2),
+
+ /** Hardware doesn't support 802.11g short slot operation */
+ NET80211_HW_NO_SHORT_SLOT = (1 << 3),
+ } flags;
+
+ /** Signal strength information that can be provided by the device
+ *
+ * Signal strength is passed to net80211_rx(), primarily to
+ * allow determination of the closest access point for a
+ * multi-AP network. The units are provided for completeness
+ * of status displays.
+ */
+ enum {
+ /** No signal strength information supported */
+ NET80211_SIGNAL_NONE = 0,
+ /** Signal strength in arbitrary units */
+ NET80211_SIGNAL_ARBITRARY,
+ /** Signal strength in decibels relative to arbitrary base */
+ NET80211_SIGNAL_DB,
+ /** Signal strength in decibels relative to 1mW */
+ NET80211_SIGNAL_DBM,
+ } signal_type;
+
+ /** Maximum signal in arbitrary cases
+ *
+ * If signal_type is NET80211_SIGNAL_ARBITRARY or
+ * NET80211_SIGNAL_DB, the driver should report it on a scale
+ * from 0 to signal_max.
+ */
+ unsigned signal_max;
+
+ /** List of RF channels supported by the card */
+ struct net80211_channel channels[NET80211_MAX_CHANNELS];
+
+ /** Number of supported channels */
+ int nr_channels;
+
+ /** List of transmission rates supported by the card, indexed by band
+ *
+ * Rates should be in 100kbps increments (e.g. 11 Mbps would
+ * be represented as the number 110).
+ */
+ u16 rates[NET80211_NR_BANDS][NET80211_MAX_RATES];
+
+ /** Number of supported rates, indexed by band */
+ int nr_rates[NET80211_NR_BANDS];
+
+ /** Estimate of the time required to change channels, in microseconds
+ *
+ * If this is not known, a guess on the order of a few
+ * milliseconds (value of 1000-5000) is reasonable.
+ */
+ unsigned channel_change_time;
+};
+
+/** Structure tracking received fragments for a packet
+ *
+ * We set up a fragment cache entry when we receive a packet marked as
+ * fragment 0 with the "more fragments" bit set in its frame control
+ * header. We are required by the 802.11 standard to track 3
+ * fragmented packets arriving simultaneously; if we receive more we
+ * may drop some. Upon receipt of a new fragment-0 packet, if no entry
+ * is available or expired, we take over the most @e recent entry for
+ * the new packet, since we don't want to starve old entries from ever
+ * finishing at all. If we get a fragment after the zeroth with no
+ * cache entry for its packet, we drop it.
+ */
+struct net80211_frag_cache
+{
+ /** Whether this cache entry is in use */
+ u8 in_use;
+
+ /** Sequence number of this MSDU (packet) */
+ u16 seqnr;
+
+ /** Timestamp from point at which first fragment was collected */
+ u32 start_ticks;
+
+ /** Buffers for each fragment */
+ struct io_buffer *iob[16];
+};
+
+/** Interface to an 802.11 cryptographic algorithm
+ *
+ * Cryptographic algorithms define a net80211_crypto structure
+ * statically, using a gPXE linker table to make it available to the
+ * 802.11 layer. When the algorithm needs to be used, the 802.11 code
+ * will allocate a copy of the static definition plus whatever space
+ * the algorithm has requested for private state, and point
+ * net80211_device::crypto at it.
+ */
+struct net80211_crypto
+{
+ /** The cryptographic algorithm implemented */
+ enum net80211_crypto_alg algorithm;
+
+ /** Initialize cryptographic algorithm using a given key
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v key Pointer to key bytes
+ * @v keylen Number of key bytes
+ * @ret rc Return status code
+ *
+ * This method is passed the communication key provided by the
+ * security handshake handler, which will already be in the
+ * low-level form required.
+ */
+ int ( * initialize ) ( struct net80211_crypto *crypto, u8 *key,
+ int keylen );
+
+ /** Encrypt a frame using the cryptographic algorithm
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v iob I/O buffer
+ * @ret eiob Newly allocated I/O buffer with encrypted packet
+ *
+ * This method is called to encrypt a single frame. It is
+ * guaranteed that initialize() will have completed
+ * successfully before this method is called.
+ *
+ * The frame passed already has an 802.11 header prepended,
+ * but the PROTECTED bit in the frame control field will not
+ * be set; this method is responsible for setting it. The
+ * returned I/O buffer should contain a complete copy of @a
+ * iob, including the 802.11 header, but with the PROTECTED
+ * bit set, the data encrypted, and whatever encryption
+ * headers/trailers are necessary added.
+ *
+ * This method should never free the passed I/O buffer.
+ *
+ * Return NULL if the packet could not be encrypted, due to
+ * memory limitations or otherwise.
+ */
+ struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto,
+ struct io_buffer *iob );
+
+ /** Decrypt a frame using the cryptographic algorithm
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v eiob Encrypted I/O buffer
+ * @ret iob Newly allocated I/O buffer with decrypted packet
+ *
+ * This method is called to decrypt a single frame. It is
+ * guaranteed that initialize() will have completed
+ * successfully before this method is called.
+ *
+ * Decryption follows the reverse of the pattern used for
+ * encryption: this method must copy the 802.11 header into
+ * the returned packet, decrypt the data stream, remove any
+ * encryption header or trailer, and clear the PROTECTED bit
+ * in the frame control header.
+ *
+ * This method should never free the passed I/O buffer.
+ *
+ * Return NULL if memory was not available for decryption, if
+ * a consistency or integrity check on the decrypted frame
+ * failed, or if the decrypted frame should not be processed
+ * by the network stack for any other reason.
+ */
+ struct io_buffer * ( * decrypt ) ( struct net80211_crypto *crypto,
+ struct io_buffer *iob );
+
+ /** Length of private data requested to be allocated */
+ int priv_len;
+
+ /** Private data for the algorithm to store key and state info */
+ void *priv;
+};
+
+
+struct net80211_probe_ctx;
+struct net80211_assoc_ctx;
+
+
+/** Structure encapsulating the complete state of an 802.11 device
+ *
+ * An 802.11 device is always wrapped by a network device, and this
+ * network device is always pointed to by the @a netdev field. In
+ * general, operations should never be performed by 802.11 code using
+ * netdev functions directly. It is usually the case that the 802.11
+ * layer might need to do some processing or bookkeeping on top of
+ * what the netdevice code will do.
+ */
+struct net80211_device
+{
+ /** The net_device that wraps us. */
+ struct net_device *netdev;
+
+ /** List of 802.11 devices. */
+ struct list_head list;
+
+ /** 802.11 device operations */
+ struct net80211_device_operations *op;
+
+ /** Driver private data */
+ void *priv;
+
+ /** Information about the hardware, provided to net80211_register() */
+ struct net80211_hw_info *hw;
+
+ /* ---------- Channel and rate fields ---------- */
+
+ /** A list of all possible channels we might use */
+ struct net80211_channel channels[NET80211_MAX_CHANNELS];
+
+ /** The number of channels in the channels array */
+ u8 nr_channels;
+
+ /** The channel currently in use, as an index into the channels array */
+ u8 channel;
+
+ /** A list of all possible TX rates we might use
+ *
+ * Rates are in units of 100 kbps.
+ */
+ u16 rates[NET80211_MAX_RATES];
+
+ /** The number of transmission rates in the rates array */
+ u8 nr_rates;
+
+ /** The rate currently in use, as an index into the rates array */
+ u8 rate;
+
+ /** The rate to use for RTS/CTS transmissions
+ *
+ * This is always the fastest basic rate that is not faster
+ * than the data rate in use. Also an index into the rates array.
+ */
+ u8 rtscts_rate;
+
+ /** Bitmask of basic rates
+ *
+ * If bit N is set in this value, with the LSB considered to
+ * be bit 0, then rate N in the rates array is a "basic" rate.
+ *
+ * We don't decide which rates are "basic"; our AP does, and
+ * we respect its wishes. We need to be able to identify basic
+ * rates in order to calculate the duration of a CTS packet
+ * used for 802.11 g/b interoperability.
+ */
+ u32 basic_rates;
+
+ /* ---------- Association fields ---------- */
+
+ /** The asynchronous association process.
+ *
+ * When an 802.11 netdev is opened, or when the user changes
+ * the SSID setting on an open 802.11 device, an
+ * autoassociation task is started by net80211_autoassocate()
+ * to associate with the new best network. The association is
+ * asynchronous, but no packets can be transmitted until it is
+ * complete. If it is successful, the wrapping net_device is
+ * set as "link up". If it fails, @c assoc_rc will be set with
+ * an error indication.
+ */
+ struct process proc_assoc;
+
+ /** Network with which we are associating
+ *
+ * This will be NULL when we are not actively in the process
+ * of associating with a network we have already successfully
+ * probed for.
+ */
+ struct net80211_wlan *associating;
+
+ /** Context for the association process
+ *
+ * This is a probe_ctx if the @c PROBED flag is not set in @c
+ * state, and an assoc_ctx otherwise.
+ */
+ union {
+ struct net80211_probe_ctx *probe;
+ struct net80211_assoc_ctx *assoc;
+ } ctx;
+
+ /** State of our association to the network
+ *
+ * Since the association process happens asynchronously, it's
+ * necessary to have some channel of communication so the
+ * driver can say "I got an association reply and we're OK" or
+ * similar. This variable provides that link. It is a bitmask
+ * of any of NET80211_PROBED, NET80211_AUTHENTICATED,
+ * NET80211_ASSOCIATED, NET80211_CRYPTO_SYNCED to indicate how
+ * far along in associating we are; NET80211_WORKING if the
+ * association task is running; and NET80211_WAITING if a
+ * packet has been sent that we're waiting for a reply to. We
+ * can only be crypto-synced if we're associated, we can
+ * only be associated if we're authenticated, we can only be
+ * authenticated if we've probed.
+ *
+ * If an association process fails (that is, we receive a
+ * packet with an error indication), the error code is copied
+ * into bits 6-0 of this variable and bit 7 is set to specify
+ * what type of error code it is. An AP can provide either a
+ * "status code" (0-51 are defined) explaining why it refused
+ * an association immediately, or a "reason code" (0-45 are
+ * defined) explaining why it canceled an association after it
+ * had originally OK'ed it. Status and reason codes serve
+ * similar functions, but they use separate error message
+ * tables. A gPXE-formatted return status code (negative) is
+ * placed in @c assoc_rc.
+ *
+ * If the failure to associate is indicated by a status code,
+ * the NET80211_IS_REASON bit will be clear; if it is
+ * indicated by a reason code, the bit will be set. If we were
+ * successful, both zero status and zero reason mean success,
+ * so there is no ambiguity.
+ *
+ * To prevent association when opening the device, user code
+ * can set the NET80211_NO_ASSOC bit. The final bit in this
+ * variable, NET80211_AUTO_SSID, is used to remember whether
+ * we picked our SSID through automated probing as opposed to
+ * user specification; the distinction becomes relevant in the
+ * settings applicator.
+ */
+ u16 state;
+
+ /** Return status code associated with @c state */
+ int assoc_rc;
+
+ /* ---------- Parameters of currently associated network ---------- */
+
+ /** 802.11 cryptographic algorithm for our current network
+ *
+ * For an open network, this will be set to NULL.
+ */
+ struct net80211_crypto *crypto;
+
+ /** MAC address of the access point most recently associated */
+ u8 bssid[ETH_ALEN];
+
+ /** SSID of the access point we are or will be associated with
+ *
+ * Although the SSID field in 802.11 packets is generally not
+ * NUL-terminated, here and in net80211_wlan we add a NUL for
+ * convenience.
+ */
+ char essid[IEEE80211_MAX_SSID_LEN+1];
+
+ /** Association ID given to us by the AP */
+ u16 aid;
+
+ /** TSFT value for last beacon received, microseconds */
+ u64 last_beacon_timestamp;
+
+ /** Time between AP sending beacons, microseconds */
+ u32 tx_beacon_interval;
+
+ /** Smoothed average time between beacons, microseconds */
+ u32 rx_beacon_interval;
+
+ /* ---------- Physical layer information ---------- */
+
+ /** Physical layer options
+ *
+ * These control the use of CTS protection, short preambles,
+ * and short-slot operation.
+ */
+ int phy_flags;
+
+ /** Signal strength of last received packet */
+ int last_signal;
+
+ /** Rate control state */
+ struct rc80211_ctx *rctl;
+
+ /* ---------- Packet handling state ---------- */
+
+ /** Fragment reassembly state */
+ struct net80211_frag_cache frags[NET80211_NR_CONCURRENT_FRAGS];
+
+ /** The sequence number of the last packet we sent */
+ u16 last_tx_seqnr;
+
+ /** Packet duplication elimination state
+ *
+ * We are only required to handle immediate duplicates for
+ * each direct sender, and since we can only have one direct
+ * sender (the AP), we need only keep the sequence control
+ * field from the most recent packet we've received. Thus,
+ * this field stores the last sequence control field we've
+ * received for a packet from the AP.
+ */
+ u16 last_rx_seq;
+
+ /** RX management packet queue
+ *
+ * Sometimes we want to keep probe, beacon, and action packets
+ * that we receive, such as when we're scanning for networks.
+ * Ordinarily we drop them because they are sent at a large
+ * volume (ten beacons per second per AP, broadcast) and we
+ * have no need of them except when we're scanning.
+ *
+ * When keep_mgmt is TRUE, received probe, beacon, and action
+ * management packets will be stored in this queue.
+ */
+ struct list_head mgmt_queue;
+
+ /** RX management packet info queue
+ *
+ * We need to keep track of the signal strength for management
+ * packets we're keeping, because that provides the only way
+ * to distinguish between multiple APs for the same network.
+ * Since we can't extend io_buffer to store signal, this field
+ * heads a linked list of "RX packet info" structures that
+ * contain that signal strength field. Its entries always
+ * parallel the entries in mgmt_queue, because the two queues
+ * are always added to or removed from in parallel.
+ */
+ struct list_head mgmt_info_queue;
+
+ /** Whether to store management packets
+ *
+ * Received beacon, probe, and action packets will be added to
+ * mgmt_queue (and their signal strengths added to
+ * mgmt_info_queue) only when this variable is TRUE. It should
+ * be set by net80211_keep_mgmt() (which returns the old
+ * value) only when calling code is prepared to poll the
+ * management queue frequently, because packets will otherwise
+ * pile up and exhaust memory.
+ */
+ int keep_mgmt;
+};
+
+/** Structure representing a probed network.
+ *
+ * This is returned from the net80211_probe_finish functions and
+ * passed to the low-level association functions. At least essid,
+ * bssid, channel, beacon, and security must be filled in if you want
+ * to build this structure manually.
+ */
+struct net80211_wlan
+{
+ /** The human-readable ESSID (network name)
+ *
+ * Although the 802.11 SSID field is generally not
+ * NUL-terminated, the gPXE code adds an extra NUL (and
+ * expects one in this structure) for convenience.
+ */
+ char essid[IEEE80211_MAX_SSID_LEN+1];
+
+ /** MAC address of the strongest-signal access point for this ESSID */
+ u8 bssid[ETH_ALEN];
+
+ /** Signal strength of beacon frame from that access point */
+ int signal;
+
+ /** The channel on which that access point communicates
+ *
+ * This is a raw channel number (net80211_channel::channel_nr),
+ * so that it will not be affected by reconfiguration of the
+ * device channels array.
+ */
+ int channel;
+
+ /** The complete beacon or probe-response frame received */
+ struct io_buffer *beacon;
+
+ /** Security handshaking method used on the network */
+ enum net80211_security_proto handshaking;
+
+ /** Cryptographic algorithm used on the network */
+ enum net80211_crypto_alg crypto;
+
+ /** Link to allow chaining multiple structures into a list to
+ be returned from net80211_probe_finish_all(). */
+ struct list_head list;
+};
+
+
+/**
+ * @defgroup net80211_probe 802.11 network location API
+ * @{
+ */
+int net80211_prepare_probe ( struct net80211_device *dev, int band,
+ int active );
+struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev,
+ const char *essid,
+ int active );
+int net80211_probe_step ( struct net80211_probe_ctx *ctx );
+struct net80211_wlan *
+net80211_probe_finish_best ( struct net80211_probe_ctx *ctx );
+struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx );
+
+void net80211_free_wlan ( struct net80211_wlan *wlan );
+void net80211_free_wlanlist ( struct list_head *list );
+/** @} */
+
+
+/**
+ * @defgroup net80211_mgmt 802.11 network management API
+ * @{
+ */
+struct net80211_device * net80211_get ( struct net_device *netdev );
+void net80211_autoassociate ( struct net80211_device *dev );
+
+int net80211_change_channel ( struct net80211_device *dev, int channel );
+void net80211_set_rate_idx ( struct net80211_device *dev, int rate );
+
+int net80211_keep_mgmt ( struct net80211_device *dev, int enable );
+struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev,
+ int *signal );
+int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc,
+ u8 bssid[ETH_ALEN], struct io_buffer *iob );
+/** @} */
+
+
+/**
+ * @defgroup net80211_assoc 802.11 network association API
+ * @{
+ */
+int net80211_prepare_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan );
+int net80211_send_auth ( struct net80211_device *dev,
+ struct net80211_wlan *wlan, int method );
+int net80211_send_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan );
+/** @} */
+
+
+/**
+ * @defgroup net80211_driver 802.11 driver interface API
+ * @{
+ */
+struct net80211_device *net80211_alloc ( size_t priv_size );
+int net80211_register ( struct net80211_device *dev,
+ struct net80211_device_operations *ops,
+ struct net80211_hw_info *hw );
+u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate );
+void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
+ int signal, u16 rate );
+void net80211_rx_err ( struct net80211_device *dev,
+ struct io_buffer *iob, int rc );
+void net80211_tx_complete ( struct net80211_device *dev,
+ struct io_buffer *iob, int retries, int rc );
+void net80211_unregister ( struct net80211_device *dev );
+void net80211_free ( struct net80211_device *dev );
+/** @} */
+
+/**
+ * Calculate duration field for a CTS control frame
+ *
+ * @v dev 802.11 device
+ * @v size Size of the packet being cleared to send
+ *
+ * A CTS control frame's duration field captures the frame being
+ * protected and its 10-byte ACK.
+ */
+static inline u16 net80211_cts_duration ( struct net80211_device *dev,
+ int size )
+{
+ return ( net80211_duration ( dev, 10,
+ dev->rates[dev->rtscts_rate] ) +
+ net80211_duration ( dev, size, dev->rates[dev->rate] ) );
+}
+
+#endif
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/netdevice.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/netdevice.h
new file mode 100644
index 0000000..fd77d89
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/netdevice.h
@@ -0,0 +1,525 @@
+#ifndef _GPXE_NETDEVICE_H
+#define _GPXE_NETDEVICE_H
+
+/** @file
+ *
+ * Network device management
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/list.h>
+#include <gpxe/tables.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/settings.h>
+
+struct io_buffer;
+struct net_device;
+struct net_protocol;
+struct ll_protocol;
+struct device;
+
+/** Maximum length of a hardware address
+ *
+ * The longest currently-supported link-layer address is for IPoIB.
+ */
+#define MAX_HW_ADDR_LEN 8
+
+/** Maximum length of a link-layer address
+ *
+ * The longest currently-supported link-layer address is for IPoIB.
+ */
+#define MAX_LL_ADDR_LEN 20
+
+/** Maximum length of a link-layer header
+ *
+ * The longest currently-supported link-layer header is for 802.11: a
+ * 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header. (The
+ * IPoIB link-layer pseudo-header doesn't actually include link-layer
+ * addresses; see ipoib.c for details).
+ */
+#define MAX_LL_HEADER_LEN 32
+
+/** Maximum length of a network-layer address */
+#define MAX_NET_ADDR_LEN 4
+
+/**
+ * A network-layer protocol
+ *
+ */
+struct net_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer source address
+ *
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev,
+ const void *ll_source );
+ /**
+ * Transcribe network-layer address
+ *
+ * @v net_addr Network-layer address
+ * @ret string Human-readable transcription of address
+ *
+ * This method should convert the network-layer address into a
+ * human-readable format (e.g. dotted quad notation for IPv4).
+ *
+ * The buffer used to hold the transcription is statically
+ * allocated.
+ */
+ const char * ( *ntoa ) ( const void * net_addr );
+ /** Network-layer protocol
+ *
+ * This is an ETH_P_XXX constant, in network-byte order
+ */
+ uint16_t net_proto;
+ /** Network-layer address length */
+ uint8_t net_addr_len;
+};
+
+/**
+ * A link-layer protocol
+ *
+ */
+struct ll_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Add link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+ int ( * push ) ( struct net_device *netdev, struct io_buffer *iobuf,
+ const void *ll_dest, const void *ll_source,
+ uint16_t net_proto );
+ /**
+ * Remove link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Source link-layer address
+ * @ret net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+ int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf,
+ const void **ll_dest, const void **ll_source,
+ uint16_t *net_proto );
+ /**
+ * Initialise link-layer address
+ *
+ * @v hw_addr Hardware address
+ * @v ll_addr Link-layer address to fill in
+ */
+ void ( * init_addr ) ( const void *hw_addr, void *ll_addr );
+ /**
+ * Transcribe link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Human-readable transcription of address
+ *
+ * This method should convert the link-layer address into a
+ * human-readable format.
+ *
+ * The buffer used to hold the transcription is statically
+ * allocated.
+ */
+ const char * ( * ntoa ) ( const void *ll_addr );
+ /**
+ * Hash multicast address
+ *
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
+ */
+ int ( * mc_hash ) ( unsigned int af, const void *net_addr,
+ void *ll_addr );
+ /** Link-layer protocol
+ *
+ * This is an ARPHRD_XXX constant, in network byte order.
+ */
+ uint16_t ll_proto;
+ /** Hardware address length */
+ uint8_t hw_addr_len;
+ /** Link-layer address length */
+ uint8_t ll_addr_len;
+ /** Link-layer header length */
+ uint8_t ll_header_len;
+};
+
+/** Network device operations */
+struct net_device_operations {
+ /** Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX I/O buffers and enable
+ * the hardware to start transmitting and receiving packets.
+ */
+ int ( * open ) ( struct net_device *netdev );
+ /** Close network device
+ *
+ * @v netdev Network device
+ *
+ * This method should stop the flow of packets, and free up
+ * any packets that are currently in the device's TX queue.
+ */
+ void ( * close ) ( struct net_device *netdev );
+ /** Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware to initiate
+ * transmission of the I/O buffer.
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the net device's TX queue, and the net device must
+ * eventually call netdev_tx_complete() to free the buffer.
+ * If this method returns failure, the I/O buffer is
+ * immediately released; the failure is interpreted as
+ * "failure to enqueue buffer".
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * transmit ) ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+ /** Poll for completed and received packets
+ *
+ * @v netdev Network device
+ *
+ * This method should cause the hardware to check for
+ * completed transmissions and received packets. Any received
+ * packets should be delivered via netdev_rx().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ void ( * poll ) ( struct net_device *netdev );
+ /** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+ void ( * irq ) ( struct net_device *netdev, int enable );
+};
+
+/** Network device error */
+struct net_device_error {
+ /** Error status code */
+ int rc;
+ /** Error count */
+ unsigned int count;
+};
+
+/** Maximum number of unique errors that we will keep track of */
+#define NETDEV_MAX_UNIQUE_ERRORS 4
+
+/** Network device statistics */
+struct net_device_stats {
+ /** Count of successful completions */
+ unsigned int good;
+ /** Count of error completions */
+ unsigned int bad;
+ /** Error breakdowns */
+ struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS];
+};
+
+/**
+ * A network device
+ *
+ * This structure represents a piece of networking hardware. It has
+ * properties such as a link-layer address and methods for
+ * transmitting and receiving raw packets.
+ *
+ * Note that this structure must represent a generic network device,
+ * not just an Ethernet device.
+ */
+struct net_device {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of network devices */
+ struct list_head list;
+ /** List of open network devices */
+ struct list_head open_list;
+ /** Name of this network device */
+ char name[8];
+ /** Underlying hardware device */
+ struct device *dev;
+
+ /** Network device operations */
+ struct net_device_operations *op;
+
+ /** Link-layer protocol */
+ struct ll_protocol *ll_protocol;
+ /** Hardware address
+ *
+ * This is an address which is an intrinsic property of the
+ * hardware, e.g. an address held in EEPROM.
+ *
+ * Note that the hardware address may not be the same length
+ * as the link-layer address.
+ */
+ uint8_t hw_addr[MAX_HW_ADDR_LEN];
+ /** Link-layer address
+ *
+ * This is the current link-layer address assigned to the
+ * device. It can be changed at runtime.
+ */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+ /** Link-layer broadcast address */
+ const uint8_t *ll_broadcast;
+
+ /** Current device state
+ *
+ * This is the bitwise-OR of zero or more NETDEV_XXX constants.
+ */
+ unsigned int state;
+ /** Link status code
+ *
+ * Zero indicates that the link is up; any other value
+ * indicates the error preventing link-up.
+ */
+ int link_rc;
+ /** Maximum packet length
+ *
+ * This length includes any link-layer headers.
+ */
+ size_t max_pkt_len;
+ /** TX packet queue */
+ struct list_head tx_queue;
+ /** RX packet queue */
+ struct list_head rx_queue;
+ /** TX statistics */
+ struct net_device_stats tx_stats;
+ /** RX statistics */
+ struct net_device_stats rx_stats;
+
+ /** Configuration settings applicable to this device */
+ struct generic_settings settings;
+
+ /** Driver private data */
+ void *priv;
+};
+
+/** Network device is open */
+#define NETDEV_OPEN 0x0001
+
+/** Link-layer protocol table */
+#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
+
+/** Declare a link-layer protocol */
+#define __ll_protocol __table_entry ( LL_PROTOCOLS, 01 )
+
+/** Network-layer protocol table */
+#define NET_PROTOCOLS __table ( struct net_protocol, "net_protocols" )
+
+/** Declare a network-layer protocol */
+#define __net_protocol __table_entry ( NET_PROTOCOLS, 01 )
+
+extern struct list_head net_devices;
+extern struct net_device_operations null_netdev_operations;
+extern struct settings_operations netdev_settings_operations;
+
+/**
+ * Initialise a network device
+ *
+ * @v netdev Network device
+ * @v op Network device operations
+ */
+static inline void netdev_init ( struct net_device *netdev,
+ struct net_device_operations *op ) {
+ netdev->op = op;
+}
+
+/**
+ * Stop using a network device
+ *
+ * @v netdev Network device
+ *
+ * Drivers should call this method immediately before the final call
+ * to netdev_put().
+ */
+static inline void netdev_nullify ( struct net_device *netdev ) {
+ netdev->op = &null_netdev_operations;
+}
+
+/**
+ * Get printable network device link-layer address
+ *
+ * @v netdev Network device
+ * @ret name Link-layer address
+ */
+static inline const char * netdev_addr ( struct net_device *netdev ) {
+ return netdev->ll_protocol->ntoa ( netdev->ll_addr );
+}
+
+/** Iterate over all network devices */
+#define for_each_netdev( netdev ) \
+ list_for_each_entry ( (netdev), &net_devices, list )
+
+/** There exist some network devices
+ *
+ * @ret existence Existence of network devices
+ */
+static inline int have_netdevs ( void ) {
+ return ( ! list_empty ( &net_devices ) );
+}
+
+/**
+ * Get reference to network device
+ *
+ * @v netdev Network device
+ * @ret netdev Network device
+ */
+static inline __attribute__ (( always_inline )) struct net_device *
+netdev_get ( struct net_device *netdev ) {
+ ref_get ( &netdev->refcnt );
+ return netdev;
+}
+
+/**
+ * Drop reference to network device
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_put ( struct net_device *netdev ) {
+ ref_put ( &netdev->refcnt );
+}
+
+/**
+ * Get driver private area for this network device
+ *
+ * @v netdev Network device
+ * @ret priv Driver private area for this network device
+ */
+static inline __attribute__ (( always_inline )) void *
+netdev_priv ( struct net_device *netdev ) {
+ return netdev->priv;
+}
+
+/**
+ * Get per-netdevice configuration settings block
+ *
+ * @v netdev Network device
+ * @ret settings Settings block
+ */
+static inline __attribute__ (( always_inline )) struct settings *
+netdev_settings ( struct net_device *netdev ) {
+ return &netdev->settings.settings;
+}
+
+/**
+ * Initialise a per-netdevice configuration settings block
+ *
+ * @v generics Generic settings block
+ * @v refcnt Containing object reference counter, or NULL
+ * @v name Settings block name
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_settings_init ( struct net_device *netdev ) {
+ generic_settings_init ( &netdev->settings,
+ &netdev->refcnt, netdev->name );
+ netdev->settings.settings.op = &netdev_settings_operations;
+}
+
+/**
+ * Mark network device as having link up
+ *
+ * @v netdev Network device
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_link_up ( struct net_device *netdev ) {
+ netdev->link_rc = 0;
+}
+
+/**
+ * Mark network device as having link down due to a specific error
+ *
+ * @v netdev Network device
+ * @v rc Link status code
+ */
+static inline __attribute__ (( always_inline )) void
+netdev_link_err ( struct net_device *netdev, int rc ) {
+ netdev->link_rc = rc;
+}
+
+/**
+ * Check link state of network device
+ *
+ * @v netdev Network device
+ * @ret link_up Link is up
+ */
+static inline __attribute__ (( always_inline )) int
+netdev_link_ok ( struct net_device *netdev ) {
+ return ( netdev->link_rc == 0 );
+}
+
+extern void netdev_link_down ( struct net_device *netdev );
+extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_tx_complete_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc );
+extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_rx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
+extern void netdev_poll ( struct net_device *netdev );
+extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
+extern struct net_device * alloc_netdev ( size_t priv_size );
+extern int register_netdev ( struct net_device *netdev );
+extern int netdev_open ( struct net_device *netdev );
+extern void netdev_close ( struct net_device *netdev );
+extern void unregister_netdev ( struct net_device *netdev );
+extern void netdev_irq ( struct net_device *netdev, int enable );
+extern struct net_device * find_netdev ( const char *name );
+extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location );
+extern struct net_device * last_opened_netdev ( void );
+extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *ll_dest );
+extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ uint16_t net_proto, const void *ll_source );
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ *
+ * The packet must currently be in the network device's TX queue.
+ */
+static inline void netdev_tx_complete ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ netdev_tx_complete_err ( netdev, iobuf, 0 );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ *
+ * Completes the oldest outstanding packet in the TX queue.
+ */
+static inline void netdev_tx_complete_next ( struct net_device *netdev ) {
+ netdev_tx_complete_next_err ( netdev, 0 );
+}
+
+#endif /* _GPXE_NETDEVICE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/null_nap.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/null_nap.h
new file mode 100644
index 0000000..0f46eaa
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/null_nap.h
@@ -0,0 +1,23 @@
+#ifndef _GPXE_NULL_NAP_H
+#define _GPXE_NULL_NAP_H
+
+/** @file
+ *
+ * Null CPU sleeping
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifdef NAP_NULL
+#define NAP_PREFIX_null
+#else
+#define NAP_PREFIX_null __null_
+#endif
+
+static inline __always_inline void
+NAP_INLINE ( null, cpu_nap ) ( void ) {
+ /* Do nothing */
+}
+
+#endif /* _GPXE_NULL_NAP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/nvo.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/nvo.h
new file mode 100644
index 0000000..c965070
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/nvo.h
@@ -0,0 +1,55 @@
+#ifndef _GPXE_NVO_H
+#define _GPXE_NVO_H
+
+/** @file
+ *
+ * Non-volatile stored options
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/dhcpopts.h>
+#include <gpxe/settings.h>
+
+struct nvs_device;
+struct refcnt;
+
+/**
+ * A fragment of a non-volatile storage device used for stored options
+ */
+struct nvo_fragment {
+ /** Starting address of fragment within NVS device */
+ unsigned int address;
+ /** Length of fragment */
+ size_t len;
+};
+
+/**
+ * A block of non-volatile stored options
+ */
+struct nvo_block {
+ /** Settings block */
+ struct settings settings;
+ /** Underlying non-volatile storage device */
+ struct nvs_device *nvs;
+ /** List of option-containing fragments
+ *
+ * The list is terminated by a fragment with a length of zero.
+ */
+ struct nvo_fragment *fragments;
+ /** Total length of option-containing fragments */
+ size_t total_len;
+ /** Option-containing data */
+ void *data;
+ /** DHCP options block */
+ struct dhcp_options dhcpopts;
+};
+
+extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
+ struct nvo_fragment *fragments, struct refcnt *refcnt );
+extern int register_nvo ( struct nvo_block *nvo, struct settings *parent );
+extern void unregister_nvo ( struct nvo_block *nvo );
+
+#endif /* _GPXE_NVO_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/nvs.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/nvs.h
new file mode 100644
index 0000000..5c90c65
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/nvs.h
@@ -0,0 +1,68 @@
+#ifndef _GPXE_NVS_H
+#define _GPXE_NVS_H
+
+/** @file
+ *
+ * Non-volatile storage
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A non-volatile storage device */
+struct nvs_device {
+ /** Word length
+ *
+ * This is expressed as the base-2 logarithm of the word
+ * length in bytes. A value of 0 therefore translates as
+ * 8-bit words, and a value of 1 translates as 16-bit words.
+ */
+ unsigned int word_len_log2;
+ /** Device size (in words) */
+ unsigned int size;
+ /** Data block size (in words)
+ *
+ * This is the block size used by the device. It must be a
+ * power of two. Data reads and writes must not cross a block
+ * boundary.
+ *
+ * Many devices allow reads to cross a block boundary, and
+ * restrict only writes. For the sake of simplicity, we
+ * assume that the same restriction applies to both reads and
+ * writes.
+ */
+ unsigned int block_size;
+ /** Read data from device
+ *
+ * @v nvs NVS device
+ * @v address Address from which to read
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Reads may not cross a block boundary.
+ */
+ int ( * read ) ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+ /** Write data to device
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * Writes may not cross a block boundary.
+ */
+ int ( * write ) ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+};
+
+extern int nvs_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int nvs_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+#endif /* _GPXE_NVS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/open.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/open.h
new file mode 100644
index 0000000..ebf754d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/open.h
@@ -0,0 +1,105 @@
+#ifndef _GPXE_OPEN_H
+#define _GPXE_OPEN_H
+
+/** @file
+ *
+ * Data transfer interface opening
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdarg.h>
+#include <gpxe/tables.h>
+#include <gpxe/socket.h>
+
+struct xfer_interface;
+struct uri;
+
+/** Location types */
+enum {
+ /** Location is a URI
+ *
+ * Parameter list for open() is:
+ *
+ * struct uri *uri;
+ */
+ LOCATION_URI = 1,
+ /** Location is a URI string
+ *
+ * Parameter list for open() is:
+ *
+ * const char *uri_string;
+ */
+ LOCATION_URI_STRING,
+ /** Location is a socket
+ *
+ * Parameter list for open() is:
+ *
+ * int semantics;
+ * struct sockaddr *peer;
+ * struct sockaddr *local;
+ */
+ LOCATION_SOCKET,
+};
+
+/** A URI opener */
+struct uri_opener {
+ /** URI protocol name
+ *
+ * This is the "scheme" portion of the URI, e.g. "http" or
+ * "file".
+ */
+ const char *scheme;
+ /** Open URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct xfer_interface *xfer, struct uri *uri );
+};
+
+/** URI opener table */
+#define URI_OPENERS __table ( struct uri_opener, "uri_openers" )
+
+/** Register a URI opener */
+#define __uri_opener __table_entry ( URI_OPENERS, 01 )
+
+/** A socket opener */
+struct socket_opener {
+ /** Communication semantics (e.g. SOCK_STREAM) */
+ int semantics;
+ /** Address family (e.g. AF_INET) */
+ int family;
+ /** Open socket
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+ int ( * open ) ( struct xfer_interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local );
+};
+
+/** Socket opener table */
+#define SOCKET_OPENERS __table ( struct socket_opener, "socket_openers" )
+
+/** Register a socket opener */
+#define __socket_opener __table_entry ( SOCKET_OPENERS, 01 )
+
+extern int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri );
+extern int xfer_open_uri_string ( struct xfer_interface *xfer,
+ const char *uri_string );
+extern int xfer_open_named_socket ( struct xfer_interface *xfer,
+ int semantics, struct sockaddr *peer,
+ const char *name, struct sockaddr *local );
+extern int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
+ struct sockaddr *peer, struct sockaddr *local );
+extern int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args );
+extern int xfer_open ( struct xfer_interface *xfer, int type, ... );
+extern int xfer_vreopen ( struct xfer_interface *xfer, int type,
+ va_list args );
+
+#endif /* _GPXE_OPEN_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/pci_io.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/pci_io.h
new file mode 100644
index 0000000..8b2729a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/pci_io.h
@@ -0,0 +1,124 @@
+#ifndef _GPXE_PCI_IO_H
+#define _GPXE_PCI_IO_H
+
+/** @file
+ *
+ * PCI I/O API
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/api.h>
+#include <config/ioapi.h>
+
+/**
+ * Calculate static inline PCI I/O API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define PCIAPI_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide a PCI I/O API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_PCIAPI( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( PCIAPI_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline PCI I/O API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_PCIAPI_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent I/O API headers */
+#include <gpxe/efi/efi_pci.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/pci_io.h>
+
+/**
+ * Determine maximum PCI bus number within system
+ *
+ * @ret max_bus Maximum bus number
+ */
+int pci_max_bus ( void );
+
+/**
+ * Read byte from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pci_read_config_byte ( struct pci_device *pci, unsigned int where,
+ uint8_t *value );
+
+/**
+ * Read 16-bit word from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pci_read_config_word ( struct pci_device *pci, unsigned int where,
+ uint16_t *value );
+
+/**
+ * Read 32-bit dword from PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value read
+ * @ret rc Return status code
+ */
+int pci_read_config_dword ( struct pci_device *pci, unsigned int where,
+ uint32_t *value );
+
+/**
+ * Write byte to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pci_write_config_byte ( struct pci_device *pci, unsigned int where,
+ uint8_t value );
+
+/**
+ * Write 16-bit word to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pci_write_config_word ( struct pci_device *pci, unsigned int where,
+ uint16_t value );
+
+/**
+ * Write 32-bit dword to PCI configuration space
+ *
+ * @v pci PCI device
+ * @v where Location within PCI configuration space
+ * @v value Value to be written
+ * @ret rc Return status code
+ */
+int pci_write_config_dword ( struct pci_device *pci, unsigned int where,
+ uint32_t value );
+
+#endif /* _GPXE_PCI_IO_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/pcibackup.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/pcibackup.h
new file mode 100644
index 0000000..3d295c0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/pcibackup.h
@@ -0,0 +1,33 @@
+#ifndef _GPXE_PCIBACKUP_H
+#define _GPXE_PCIBACKUP_H
+
+/** @file
+ *
+ * PCI configuration space backup and restoration
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A PCI configuration space backup */
+struct pci_config_backup {
+ uint32_t dwords[64];
+};
+
+/** PCI configuration space backup exclusion list end marker */
+#define PCI_CONFIG_BACKUP_EXCLUDE_END 0xff
+
+/** Define a PCI configuration space backup exclusion list */
+#define PCI_CONFIG_BACKUP_EXCLUDE(...) \
+ { __VA_ARGS__, PCI_CONFIG_BACKUP_EXCLUDE_END }
+
+extern void pci_backup ( struct pci_device *pci,
+ struct pci_config_backup *backup,
+ const uint8_t *exclude );
+extern void pci_restore ( struct pci_device *pci,
+ struct pci_config_backup *backup,
+ const uint8_t *exclude );
+
+#endif /* _GPXE_PCIBACKUP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/posix_io.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/posix_io.h
new file mode 100644
index 0000000..3063dff
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/posix_io.h
@@ -0,0 +1,87 @@
+#ifndef _GPXE_POSIX_IO_H
+#define _GPXE_POSIX_IO_H
+
+/** @file
+ *
+ * POSIX-like I/O
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/uaccess.h>
+
+/** Minimum file descriptor that will ever be allocated */
+#define POSIX_FD_MIN ( 1 )
+
+/** Maximum file descriptor that will ever be allocated */
+#define POSIX_FD_MAX ( 31 )
+
+/** File descriptor set as used for select() */
+typedef uint32_t fd_set;
+
+extern int open ( const char *uri_string );
+extern ssize_t read_user ( int fd, userptr_t buffer,
+ off_t offset, size_t len );
+extern int select ( fd_set *readfds, int wait );
+extern ssize_t fsize ( int fd );
+extern int close ( int fd );
+
+/**
+ * Zero a file descriptor set
+ *
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_ZERO ( fd_set *set ) {
+ *set = 0;
+}
+
+/**
+ * Set a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_SET ( int fd, fd_set *set ) {
+ *set |= ( 1 << fd );
+}
+
+/**
+ * Clear a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ */
+static inline __attribute__ (( always_inline )) void
+FD_CLR ( int fd, fd_set *set ) {
+ *set &= ~( 1 << fd );
+}
+
+/**
+ * Test a bit within a file descriptor set
+ *
+ * @v fd File descriptor
+ * @v set File descriptor set
+ * @ret is_set Corresponding bit is set
+ */
+static inline __attribute__ (( always_inline )) int
+FD_ISSET ( int fd, fd_set *set ) {
+ return ( *set & ( 1 << fd ) );
+}
+
+/**
+ * Read data from file
+ *
+ * @v fd File descriptor
+ * @v buf Data buffer
+ * @v len Maximum length to read
+ * @ret len Actual length read, or negative error number
+ */
+static inline ssize_t read ( int fd, void *buf, size_t len ) {
+ return read_user ( fd, virt_to_user ( buf ), 0, len );
+}
+
+#endif /* _GPXE_POSIX_IO_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/process.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/process.h
new file mode 100644
index 0000000..944858d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/process.h
@@ -0,0 +1,80 @@
+#ifndef _GPXE_PROCESS_H
+#define _GPXE_PROCESS_H
+
+/** @file
+ *
+ * Processes
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/list.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/tables.h>
+
+/** A process */
+struct process {
+ /** List of processes */
+ struct list_head list;
+ /**
+ * Single-step the process
+ *
+ * This method should execute a single step of the process.
+ * Returning from this method is isomorphic to yielding the
+ * CPU to another process.
+ */
+ void ( * step ) ( struct process *process );
+ /** Reference counter
+ *
+ * If this interface is not part of a reference-counted
+ * object, this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+extern void process_add ( struct process *process );
+extern void process_del ( struct process *process );
+extern void step ( void );
+
+/**
+ * Initialise process without adding to process list
+ *
+ * @v process Process
+ * @v step Process' step() method
+ */
+static inline __attribute__ (( always_inline )) void
+process_init_stopped ( struct process *process,
+ void ( * step ) ( struct process *process ),
+ struct refcnt *refcnt ) {
+ INIT_LIST_HEAD ( &process->list );
+ process->step = step;
+ process->refcnt = refcnt;
+}
+
+/**
+ * Initialise process and add to process list
+ *
+ * @v process Process
+ * @v step Process' step() method
+ */
+static inline __attribute__ (( always_inline )) void
+process_init ( struct process *process,
+ void ( * step ) ( struct process *process ),
+ struct refcnt *refcnt ) {
+ process_init_stopped ( process, step, refcnt );
+ process_add ( process );
+}
+
+/** Permanent process table */
+#define PERMANENT_PROCESSES __table ( struct process, "processes" )
+
+/**
+ * Declare a permanent process
+ *
+ * Permanent processes will be automatically added to the process list
+ * at initialisation time.
+ */
+#define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
+
+#endif /* _GPXE_PROCESS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/profile.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/profile.h
new file mode 100644
index 0000000..a5bdd3a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/profile.h
@@ -0,0 +1,80 @@
+#ifndef _GPXE_PROFILE_H
+#define _GPXE_PROFILE_H
+
+/** @file
+ *
+ * Profiling
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * A data structure for storing profiling information
+ */
+union profiler {
+ /** Timestamp (in CPU-specific "ticks") */
+ uint64_t timestamp;
+ /** Registers returned by rdtsc.
+ *
+ * This part should really be architecture-specific code.
+ */
+ struct {
+ uint32_t eax;
+ uint32_t edx;
+ } rdtsc;
+};
+
+/**
+ * Static per-object profiler, for use with simple_profile()
+ */
+static union profiler simple_profiler;
+
+/**
+ * Perform profiling
+ *
+ * @v profiler Profiler data structure
+ * @ret delta Elapsed ticks since last call to profile().
+ *
+ * Call profile() both before and after the code you wish to measure.
+ * The "after" call will return the measurement. For example:
+ *
+ * @code
+ *
+ * profile ( &profiler );
+ * ... do something here ...
+ * printf ( "It took %ld ticks to execute\n", profile ( &profiler ) );
+ *
+ * @endcode
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+profile ( union profiler *profiler ) {
+ uint64_t last_timestamp = profiler->timestamp;
+
+ __asm__ __volatile__ ( "rdtsc" :
+ "=a" ( profiler->rdtsc.eax ),
+ "=d" ( profiler->rdtsc.edx ) );
+ return ( profiler->timestamp - last_timestamp );
+}
+
+/**
+ * Perform profiling
+ *
+ * @ret delta Elapsed ticks since last call to profile().
+ *
+ * When you only need one profiler, you can avoid the hassle of
+ * creating your own @c profiler data structure by using
+ * simple_profile() instead.
+ *
+ * simple_profile() is equivalent to profile(&simple_profiler), where
+ * @c simple_profiler is a @c profiler data structure that is static
+ * to each object which includes @c profile.h.
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+simple_profile ( void ) {
+ return profile ( &simple_profiler );
+}
+
+#endif /* _GPXE_PROFILE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/ramdisk.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ramdisk.h
new file mode 100644
index 0000000..31a1d99
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/ramdisk.h
@@ -0,0 +1,24 @@
+#ifndef _GPXE_RAMDISK_H
+#define _GPXE_RAMDISK_H
+
+/**
+ * @file
+ *
+ * RAM disks
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/uaccess.h>
+#include <gpxe/blockdev.h>
+
+struct ramdisk {
+ struct block_device blockdev;
+ userptr_t data;
+};
+
+extern int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
+ unsigned int blksize );
+
+#endif /* _GPXE_RAMDISK_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/rarp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rarp.h
new file mode 100644
index 0000000..7ade831
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rarp.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_RARP_H
+#define _GPXE_RARP_H
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net_protocol;
+
+extern struct net_protocol rarp_protocol;
+
+#endif /* _GPXE_RARP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/rc80211.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rc80211.h
new file mode 100644
index 0000000..0856896
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rc80211.h
@@ -0,0 +1,19 @@
+#ifndef _GPXE_RC80211_H
+#define _GPXE_RC80211_H
+
+/** @file
+ *
+ * Rate-control algorithm prototype for 802.11.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net80211_device;
+struct rc80211_ctx;
+
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev );
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc );
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate );
+void rc80211_free ( struct rc80211_ctx *ctx );
+
+#endif /* _GPXE_RC80211_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/refcnt.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/refcnt.h
new file mode 100644
index 0000000..e56f1d3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/refcnt.h
@@ -0,0 +1,46 @@
+#ifndef _GPXE_REFCNT_H
+#define _GPXE_REFCNT_H
+
+/** @file
+ *
+ * Reference counting
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * A reference counter
+ *
+ * This data structure is designed to be embedded within a
+ * reference-counted object.
+ *
+ * Reference-counted objects are freed when their reference count
+ * drops below zero. This means that a freshly allocated-and-zeroed
+ * reference-counted object will be freed on the first call to
+ * ref_put().
+ */
+struct refcnt {
+ /** Current reference count
+ *
+ * When this count is decremented below zero, the free()
+ * method will be called.
+ */
+ int refcnt;
+ /** Free containing object
+ *
+ * This method is called when the reference count is
+ * decremented below zero.
+ *
+ * If this method is left NULL, the standard library free()
+ * function will be called. The upshot of this is that you
+ * may omit the free() method if the @c refcnt object is the
+ * first element of your reference-counted struct.
+ */
+ void ( * free ) ( struct refcnt *refcnt );
+};
+
+extern struct refcnt * ref_get ( struct refcnt *refcnt );
+extern void ref_put ( struct refcnt *refcnt );
+
+#endif /* _GPXE_REFCNT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/resolv.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/resolv.h
new file mode 100644
index 0000000..33bb098
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/resolv.h
@@ -0,0 +1,170 @@
+#ifndef _GPXE_RESOLV_H
+#define _GPXE_RESOLV_H
+
+/** @file
+ *
+ * Name resolution
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/refcnt.h>
+#include <gpxe/interface.h>
+#include <gpxe/tables.h>
+#include <gpxe/socket.h>
+
+struct resolv_interface;
+
+/** Name resolution interface operations */
+struct resolv_interface_operations {
+ /** Name resolution completed
+ *
+ * @v resolv Name resolution interface
+ * @v sa Completed socket address (if successful)
+ * @v rc Final status code
+ */
+ void ( * done ) ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+};
+
+/** A name resolution interface */
+struct resolv_interface {
+ /** Generic object communication interface */
+ struct interface intf;
+ /** Operations for received messages */
+ struct resolv_interface_operations *op;
+};
+
+extern struct resolv_interface null_resolv;
+extern struct resolv_interface_operations null_resolv_ops;
+
+/**
+ * Initialise a name resolution interface
+ *
+ * @v resolv Name resolution interface
+ * @v op Name resolution interface operations
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void resolv_init ( struct resolv_interface *resolv,
+ struct resolv_interface_operations *op,
+ struct refcnt *refcnt ) {
+ resolv->intf.dest = &null_resolv.intf;
+ resolv->intf.refcnt = refcnt;
+ resolv->op = op;
+}
+
+/**
+ * Get name resolution interface from generic object communication interface
+ *
+ * @v intf Generic object communication interface
+ * @ret resolv Name resolution interface
+ */
+static inline __attribute__ (( always_inline )) struct resolv_interface *
+intf_to_resolv ( struct interface *intf ) {
+ return container_of ( intf, struct resolv_interface, intf );
+}
+
+/**
+ * Get reference to destination name resolution interface
+ *
+ * @v resolv Name resolution interface
+ * @ret dest Destination interface
+ */
+static inline __attribute__ (( always_inline )) struct resolv_interface *
+resolv_get_dest ( struct resolv_interface *resolv ) {
+ return intf_to_resolv ( intf_get ( resolv->intf.dest ) );
+}
+
+/**
+ * Drop reference to name resolution interface
+ *
+ * @v resolv name resolution interface
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_put ( struct resolv_interface *resolv ) {
+ intf_put ( &resolv->intf );
+}
+
+/**
+ * Plug a name resolution interface into a new destination interface
+ *
+ * @v resolv Name resolution interface
+ * @v dest New destination interface
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_plug ( struct resolv_interface *resolv, struct resolv_interface *dest ) {
+ plug ( &resolv->intf, &dest->intf );
+}
+
+/**
+ * Plug two name resolution interfaces together
+ *
+ * @v a Name resolution interface A
+ * @v b Name resolution interface B
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_plug_plug ( struct resolv_interface *a, struct resolv_interface *b ) {
+ plug_plug ( &a->intf, &b->intf );
+}
+
+/**
+ * Unplug a name resolution interface
+ *
+ * @v resolv Name resolution interface
+ */
+static inline __attribute__ (( always_inline )) void
+resolv_unplug ( struct resolv_interface *resolv ) {
+ plug ( &resolv->intf, &null_resolv.intf );
+}
+
+/**
+ * Stop using a name resolution interface
+ *
+ * @v resolv Name resolution interface
+ *
+ * After calling this method, no further messages will be received via
+ * the interface.
+ */
+static inline void resolv_nullify ( struct resolv_interface *resolv ) {
+ resolv->op = &null_resolv_ops;
+};
+
+/** A name resolver */
+struct resolver {
+ /** Name of this resolver (e.g. "DNS") */
+ const char *name;
+ /** Start name resolution
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to complete
+ * @ret rc Return status code
+ */
+ int ( * resolv ) ( struct resolv_interface *resolv, const char *name,
+ struct sockaddr *sa );
+};
+
+/** Numeric resolver priority */
+#define RESOLV_NUMERIC 01
+
+/** Normal resolver priority */
+#define RESOLV_NORMAL 02
+
+/** Resolvers table */
+#define RESOLVERS __table ( struct resolver, "resolvers" )
+
+/** Register as a name resolver */
+#define __resolver( resolv_order ) __table_entry ( RESOLVERS, resolv_order )
+
+extern void resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+extern void ignore_resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+extern struct resolv_interface_operations null_resolv_ops;
+extern struct resolv_interface null_resolv;
+
+extern int resolv ( struct resolv_interface *resolv, const char *name,
+ struct sockaddr *sa );
+
+#endif /* _GPXE_RESOLV_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/retry.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/retry.h
new file mode 100644
index 0000000..ada0204
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/retry.h
@@ -0,0 +1,81 @@
+#ifndef _GPXE_RETRY_H
+#define _GPXE_RETRY_H
+
+/** @file
+ *
+ * Retry timers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/list.h>
+
+/** Default timeout value */
+#define DEFAULT_MIN_TIMEOUT ( TICKS_PER_SEC / 4 )
+
+/** Limit after which the timeout will be deemed permanent */
+#define DEFAULT_MAX_TIMEOUT ( 10 * TICKS_PER_SEC )
+
+/** A retry timer */
+struct retry_timer {
+ /** List of active timers */
+ struct list_head list;
+ /** Timer is currently running */
+ unsigned int running;
+ /** Timeout value (in ticks) */
+ unsigned long timeout;
+ /** Minimum timeout value (in ticks)
+ *
+ * A value of zero means "use default timeout."
+ */
+ unsigned long min_timeout;
+ /** Maximum timeout value before failure (in ticks)
+ *
+ * A value of zero means "use default timeout."
+ */
+ unsigned long max_timeout;
+ /** Start time (in ticks) */
+ unsigned long start;
+ /** Retry count */
+ unsigned int count;
+ /** Timer expired callback
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ *
+ * The timer will already be stopped when this method is
+ * called. The failure indicator will be True if the retry
+ * timeout has already exceeded @c MAX_TIMEOUT.
+ */
+ void ( * expired ) ( struct retry_timer *timer, int over );
+};
+
+extern void start_timer ( struct retry_timer *timer );
+extern void start_timer_fixed ( struct retry_timer *timer,
+ unsigned long timeout );
+extern void stop_timer ( struct retry_timer *timer );
+
+/**
+ * Start timer with no delay
+ *
+ * @v timer Retry timer
+ *
+ * This starts the timer running with a zero timeout value.
+ */
+static inline void start_timer_nodelay ( struct retry_timer *timer ) {
+ start_timer_fixed ( timer, 0 );
+}
+
+/**
+ * Test to see if timer is currently running
+ *
+ * @v timer Retry timer
+ * @ret running Non-zero if timer is running
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+timer_running ( struct retry_timer *timer ) {
+ return ( timer->running );
+}
+
+#endif /* _GPXE_RETRY_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/rotate.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rotate.h
new file mode 100644
index 0000000..0371c57
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rotate.h
@@ -0,0 +1,29 @@
+#ifndef _GPXE_ROTATE_H
+#define _GPXE_ROTATE_H
+
+/** @file
+ *
+ * Bit operations
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+static inline uint32_t rol32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) );
+}
+
+static inline uint32_t ror32 ( uint32_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) );
+}
+
+static inline uint64_t rol64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) );
+}
+
+static inline uint64_t ror64 ( uint64_t data, unsigned int rotation ) {
+ return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) );
+}
+
+#endif /* _GPXE_ROTATE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/rsa.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rsa.h
new file mode 100644
index 0000000..5052ad4
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/rsa.h
@@ -0,0 +1,12 @@
+#ifndef _GPXE_RSA_H
+#define _GPXE_RSA_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct pubkey_algorithm;
+
+extern struct pubkey_algorithm rsa_algorithm;
+
+#include "crypto/axtls/crypto.h"
+
+#endif /* _GPXE_RSA_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/sanboot.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/sanboot.h
new file mode 100644
index 0000000..6ec2ec2
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/sanboot.h
@@ -0,0 +1,18 @@
+#ifndef _GPXE_SANBOOT_H
+#define _GPXE_SANBOOT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tables.h>
+
+struct sanboot_protocol {
+ const char *prefix;
+ int ( * boot ) ( const char *root_path );
+};
+
+#define SANBOOT_PROTOCOLS \
+ __table ( struct sanboot_protocol, "sanboot_protocols" )
+
+#define __sanboot_protocol __table_entry ( SANBOOT_PROTOCOLS, 01 )
+
+#endif /* _GPXE_SANBOOT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/scsi.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/scsi.h
new file mode 100644
index 0000000..9741697
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/scsi.h
@@ -0,0 +1,281 @@
+#ifndef _GPXE_SCSI_H
+#define _GPXE_SCSI_H
+
+#include <stdint.h>
+#include <gpxe/blockdev.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
+
+/** @file
+ *
+ * SCSI devices
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @defgroup scsiops SCSI operation codes
+ * @{
+ */
+
+#define SCSI_OPCODE_READ_10 0x28 /**< READ (10) */
+#define SCSI_OPCODE_READ_16 0x88 /**< READ (16) */
+#define SCSI_OPCODE_WRITE_10 0x2a /**< WRITE (10) */
+#define SCSI_OPCODE_WRITE_16 0x8a /**< WRITE (16) */
+#define SCSI_OPCODE_READ_CAPACITY_10 0x25 /**< READ CAPACITY (10) */
+#define SCSI_OPCODE_SERVICE_ACTION_IN 0x9e /**< SERVICE ACTION IN */
+#define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
+
+/** @} */
+
+/**
+ * @defgroup scsiflags SCSI flags
+ * @{
+ */
+
+#define SCSI_FL_FUA_NV 0x02 /**< Force unit access to NVS */
+#define SCSI_FL_FUA 0x08 /**< Force unit access */
+#define SCSI_FL_DPO 0x10 /**< Disable cache page out */
+
+/** @} */
+
+/**
+ * @defgroup scsicdbs SCSI command data blocks
+ * @{
+ */
+
+/** A SCSI "READ (10)" CDB */
+struct scsi_cdb_read_10 {
+ /** Opcode (0x28) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint32_t lba;
+ /** Group number */
+ uint8_t group;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint16_t len;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ (16)" CDB */
+struct scsi_cdb_read_16 {
+ /** Opcode (0x88) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint32_t len;
+ /** Group number */
+ uint8_t group;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "WRITE (10)" CDB */
+struct scsi_cdb_write_10 {
+ /** Opcode (0x2a) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint32_t lba;
+ /** Group number */
+ uint8_t group;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint16_t len;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "WRITE (16)" CDB */
+struct scsi_cdb_write_16 {
+ /** Opcode (0x8a) */
+ uint8_t opcode;
+ /** Flags */
+ uint8_t flags;
+ /** Start address
+ *
+ * This is a logical block number, in big-endian order.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is a logical block count, in big-endian order.
+ */
+ uint32_t len;
+ /** Group number */
+ uint8_t group;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ CAPACITY (10)" CDB */
+struct scsi_cdb_read_capacity_10 {
+ /** Opcode (0x25) */
+ uint8_t opcode;
+ /** Reserved */
+ uint8_t reserved_a;
+ /** Logical block address
+ *
+ * Applicable only if the PMI bit is set.
+ */
+ uint32_t lba;
+ /** Reserved */
+ uint8_t reserved_b[3];
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** SCSI "READ CAPACITY (10)" parameter data */
+struct scsi_capacity_10 {
+ /** Maximum logical block number */
+ uint32_t lba;
+ /** Block length in bytes */
+ uint32_t blksize;
+} __attribute__ (( packed ));
+
+/** A SCSI "READ CAPACITY (16)" CDB */
+struct scsi_cdb_read_capacity_16 {
+ /** Opcode (0x9e) */
+ uint8_t opcode;
+ /** Service action */
+ uint8_t service_action;
+ /** Logical block address
+ *
+ * Applicable only if the PMI bit is set.
+ */
+ uint64_t lba;
+ /** Transfer length
+ *
+ * This is the size of the data-in buffer, in bytes.
+ */
+ uint32_t len;
+ /** Reserved */
+ uint8_t reserved;
+ /** Control byte */
+ uint8_t control;
+} __attribute__ (( packed ));
+
+/** SCSI "READ CAPACITY (16)" parameter data */
+struct scsi_capacity_16 {
+ /** Maximum logical block number */
+ uint64_t lba;
+ /** Block length in bytes */
+ uint32_t blksize;
+ /** Reserved */
+ uint8_t reserved[20];
+} __attribute__ (( packed ));
+
+/** A SCSI Command Data Block */
+union scsi_cdb {
+ struct scsi_cdb_read_10 read10;
+ struct scsi_cdb_read_16 read16;
+ struct scsi_cdb_write_10 write10;
+ struct scsi_cdb_write_16 write16;
+ struct scsi_cdb_read_capacity_10 readcap10;
+ struct scsi_cdb_read_capacity_16 readcap16;
+ unsigned char bytes[16];
+};
+
+/** printf() format for dumping a scsi_cdb */
+#define SCSI_CDB_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+
+/** printf() parameters for dumping a scsi_cdb */
+#define SCSI_CDB_DATA(cdb) \
+ (cdb).bytes[0], (cdb).bytes[1], (cdb).bytes[2], (cdb).bytes[3], \
+ (cdb).bytes[4], (cdb).bytes[5], (cdb).bytes[6], (cdb).bytes[7], \
+ (cdb).bytes[8], (cdb).bytes[9], (cdb).bytes[10], (cdb).bytes[11], \
+ (cdb).bytes[12], (cdb).bytes[13], (cdb).bytes[14], (cdb).bytes[15]
+
+/** @} */
+
+/** A SCSI command */
+struct scsi_command {
+ /** CDB for this command */
+ union scsi_cdb cdb;
+ /** Data-out buffer (may be NULL) */
+ userptr_t data_out;
+ /** Data-out buffer length
+ *
+ * Must be zero if @c data_out is NULL
+ */
+ size_t data_out_len;
+ /** Data-in buffer (may be NULL) */
+ userptr_t data_in;
+ /** Data-in buffer length
+ *
+ * Must be zero if @c data_in is NULL
+ */
+ size_t data_in_len;
+ /** SCSI status code */
+ uint8_t status;
+ /** SCSI sense response code */
+ uint8_t sense_response;
+ /** Command status code */
+ int rc;
+};
+
+/** A SCSI LUN
+ *
+ * This is a four-level LUN as specified by SAM-2, in big-endian
+ * order.
+ */
+struct scsi_lun {
+ uint16_t u16[4];
+} __attribute__ (( packed ));
+
+/** A SCSI device */
+struct scsi_device {
+ /** Block device interface */
+ struct block_device blockdev;
+ /**
+ * Issue SCSI command
+ *
+ * @v scsi SCSI device
+ * @v command SCSI command
+ * @ret rc Return status code
+ *
+ * Note that a successful return status code indicates only
+ * that the SCSI command was issued. The caller must check
+ * the status field in the command structure to see when the
+ * command completes and whether, for example, the device
+ * returned CHECK CONDITION or some other non-success status
+ * code.
+ */
+ int ( * command ) ( struct scsi_device *scsi,
+ struct scsi_command *command );
+ /** Backing device */
+ struct refcnt *backend;
+};
+
+extern int scsi_detached_command ( struct scsi_device *scsi,
+ struct scsi_command *command );
+extern int init_scsidev ( struct scsi_device *scsi );
+extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
+
+#endif /* _GPXE_SCSI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/segment.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/segment.h
new file mode 100644
index 0000000..5b59c54
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/segment.h
@@ -0,0 +1,17 @@
+#ifndef _GPXE_SEGMENT_H
+#define _GPXE_SEGMENT_H
+
+/**
+ * @file
+ *
+ * Executable image segments
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/uaccess.h>
+
+extern int prep_segment ( userptr_t segment, size_t filesz, size_t memsz );
+
+#endif /* _GPXE_SEGMENT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/serial.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/serial.h
new file mode 100644
index 0000000..a72ca7e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/serial.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_SERIAL_H
+#define _GPXE_SERIAL_H
+
+/** @file
+ *
+ * Serial driver functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern void serial_putc ( int ch );
+extern int serial_getc ( void );
+extern int serial_ischar ( void );
+
+#endif /* _GPXE_SERIAL_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/settings.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/settings.h
new file mode 100644
index 0000000..09934b6
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/settings.h
@@ -0,0 +1,334 @@
+#ifndef _GPXE_SETTINGS_H
+#define _GPXE_SETTINGS_H
+
+/** @file
+ *
+ * Configuration settings
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/tables.h>
+#include <gpxe/list.h>
+#include <gpxe/refcnt.h>
+
+struct settings;
+struct in_addr;
+union uuid;
+
+/** A setting */
+struct setting {
+ /** Name
+ *
+ * This is the human-readable name for the setting.
+ */
+ const char *name;
+ /** Description */
+ const char *description;
+ /** Setting type
+ *
+ * This identifies the type of setting (e.g. string, IPv4
+ * address, etc.).
+ */
+ struct setting_type *type;
+ /** DHCP option number, if applicable */
+ unsigned int tag;
+};
+
+/** Configuration setting table */
+#define SETTINGS __table ( struct setting, "settings" )
+
+/** Declare a configuration setting */
+#define __setting __table_entry ( SETTINGS, 01 )
+
+/** Settings block operations */
+struct settings_operations {
+ /** Store value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+ int ( * store ) ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len );
+ /** Fetch value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ *
+ * The actual length of the setting will be returned even if
+ * the buffer was too small.
+ */
+ int ( * fetch ) ( struct settings *settings, struct setting *setting,
+ void *data, size_t len );
+ /** Clear settings block
+ *
+ * @v settings Settings block
+ */
+ void ( * clear ) ( struct settings *settings );
+};
+
+/** A settings block */
+struct settings {
+ /** Reference counter */
+ struct refcnt *refcnt;
+ /** Name */
+ const char *name;
+ /** Tag magic
+ *
+ * This value will be ORed in to any numerical tags
+ * constructed by parse_setting_name(), and can be used to
+ * avoid e.g. attempting to retrieve the subnet mask from
+ * SMBIOS, or the system UUID from DHCP.
+ */
+ unsigned int tag_magic;
+ /** Parent settings block */
+ struct settings *parent;
+ /** Sibling settings blocks */
+ struct list_head siblings;
+ /** Child settings blocks */
+ struct list_head children;
+ /** Settings block operations */
+ struct settings_operations *op;
+};
+
+/**
+ * A setting type
+ *
+ * This represents a type of setting (e.g. string, IPv4 address,
+ * etc.).
+ */
+struct setting_type {
+ /** Name
+ *
+ * This is the name exposed to the user (e.g. "string").
+ */
+ const char *name;
+ /** Parse and set value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v value Formatted setting data
+ * @ret rc Return status code
+ */
+ int ( * storef ) ( struct settings *settings, struct setting *setting,
+ const char *value );
+ /** Fetch and format value of setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+ int ( * fetchf ) ( struct settings *settings, struct setting *setting,
+ char *buf, size_t len );
+};
+
+/** Configuration setting type table */
+#define SETTING_TYPES __table ( struct setting_type, "setting_types" )
+
+/** Declare a configuration setting type */
+#define __setting_type __table_entry ( SETTING_TYPES, 01 )
+
+/**
+ * A settings applicator
+ *
+ */
+struct settings_applicator {
+ /** Apply updated settings
+ *
+ * @ret rc Return status code
+ */
+ int ( * apply ) ( void );
+};
+
+/** Settings applicator table */
+#define SETTINGS_APPLICATORS \
+ __table ( struct settings_applicator, "settings_applicators" )
+
+/** Declare a settings applicator */
+#define __settings_applicator __table_entry ( SETTINGS_APPLICATORS, 01 )
+
+/**
+ * A generic settings block
+ *
+ */
+struct generic_settings {
+ /** Settings block */
+ struct settings settings;
+ /** List of generic settings */
+ struct list_head list;
+};
+
+extern struct settings_operations generic_settings_operations;
+extern int generic_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len );
+extern int generic_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len );
+extern void generic_settings_clear ( struct settings *settings );
+
+extern int register_settings ( struct settings *settings,
+ struct settings *parent );
+extern void unregister_settings ( struct settings *settings );
+
+extern int store_setting ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len );
+extern int fetch_setting ( struct settings *settings, struct setting *setting,
+ void *data, size_t len );
+extern int fetch_setting_len ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_string_setting ( struct settings *settings,
+ struct setting *setting,
+ char *data, size_t len );
+extern int fetch_string_setting_copy ( struct settings *settings,
+ struct setting *setting,
+ char **data );
+extern int fetch_ipv4_setting ( struct settings *settings,
+ struct setting *setting, struct in_addr *inp );
+extern int fetch_int_setting ( struct settings *settings,
+ struct setting *setting, long *value );
+extern int fetch_uint_setting ( struct settings *settings,
+ struct setting *setting,
+ unsigned long *value );
+extern long fetch_intz_setting ( struct settings *settings,
+ struct setting *setting );
+extern unsigned long fetch_uintz_setting ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_uuid_setting ( struct settings *settings,
+ struct setting *setting, union uuid *uuid );
+extern void clear_settings ( struct settings *settings );
+extern int setting_cmp ( struct setting *a, struct setting *b );
+
+extern struct settings * find_settings ( const char *name );
+
+extern int storef_setting ( struct settings *settings,
+ struct setting *setting,
+ const char *value );
+extern int storef_named_setting ( const char *name, const char *value );
+extern int fetchf_named_setting ( const char *name, char *buf, size_t len );
+
+extern struct setting_type setting_type_string __setting_type;
+extern struct setting_type setting_type_ipv4 __setting_type;
+extern struct setting_type setting_type_int8 __setting_type;
+extern struct setting_type setting_type_int16 __setting_type;
+extern struct setting_type setting_type_int32 __setting_type;
+extern struct setting_type setting_type_uint8 __setting_type;
+extern struct setting_type setting_type_uint16 __setting_type;
+extern struct setting_type setting_type_uint32 __setting_type;
+extern struct setting_type setting_type_hex __setting_type;
+extern struct setting_type setting_type_uuid __setting_type;
+
+extern struct setting ip_setting __setting;
+extern struct setting netmask_setting __setting;
+extern struct setting gateway_setting __setting;
+extern struct setting dns_setting __setting;
+extern struct setting domain_setting __setting;
+extern struct setting hostname_setting __setting;
+extern struct setting filename_setting __setting;
+extern struct setting root_path_setting __setting;
+extern struct setting username_setting __setting;
+extern struct setting password_setting __setting;
+extern struct setting priority_setting __setting;
+extern struct setting uuid_setting __setting;
+extern struct setting next_server_setting __setting;
+extern struct setting mac_setting __setting;
+extern struct setting user_class_setting __setting;
+
+/**
+ * Initialise a settings block
+ *
+ * @v settings Settings block
+ * @v op Settings block operations
+ * @v refcnt Containing object reference counter, or NULL
+ * @v name Settings block name
+ * @v tag_magic Tag magic
+ */
+static inline void settings_init ( struct settings *settings,
+ struct settings_operations *op,
+ struct refcnt *refcnt,
+ const char *name,
+ unsigned int tag_magic ) {
+ INIT_LIST_HEAD ( &settings->siblings );
+ INIT_LIST_HEAD ( &settings->children );
+ settings->op = op;
+ settings->refcnt = refcnt;
+ settings->name = name;
+ settings->tag_magic = tag_magic;
+}
+
+/**
+ * Initialise a settings block
+ *
+ * @v generics Generic settings block
+ * @v refcnt Containing object reference counter, or NULL
+ * @v name Settings block name
+ */
+static inline void generic_settings_init ( struct generic_settings *generics,
+ struct refcnt *refcnt,
+ const char *name ) {
+ settings_init ( &generics->settings, &generic_settings_operations,
+ refcnt, name, 0 );
+ INIT_LIST_HEAD ( &generics->list );
+}
+
+/**
+ * Delete setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to delete
+ * @ret rc Return status code
+ */
+static inline int delete_setting ( struct settings *settings,
+ struct setting *setting ) {
+ return store_setting ( settings, setting, NULL, 0 );
+}
+
+/**
+ * Fetch and format value of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v type Settings type
+ * @v buf Buffer to contain formatted value
+ * @v len Length of buffer
+ * @ret len Length of formatted value, or negative error
+ */
+static inline int fetchf_setting ( struct settings *settings,
+ struct setting *setting,
+ char *buf, size_t len ) {
+ return setting->type->fetchf ( settings, setting, buf, len );
+}
+
+/**
+ * Delete named setting
+ *
+ * @v name Name of setting
+ * @ret rc Return status code
+ */
+static inline int delete_named_setting ( const char *name ) {
+ return storef_named_setting ( name, NULL );
+}
+
+/**
+ * Check existence of setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @ret exists Setting exists
+ */
+static inline int setting_exists ( struct settings *settings,
+ struct setting *setting ) {
+ return ( fetch_setting_len ( settings, setting ) >= 0 );
+}
+
+#endif /* _GPXE_SETTINGS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/settings_ui.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/settings_ui.h
new file mode 100644
index 0000000..a82d733
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/settings_ui.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_SETTINGS_UI_H
+#define _GPXE_SETTINGS_UI_H
+
+/** @file
+ *
+ * Option configuration console
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct settings;
+
+extern int settings_ui ( struct settings *settings ) __nonnull;
+
+#endif /* _GPXE_SETTINGS_UI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/shell.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/shell.h
new file mode 100644
index 0000000..a65a344
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/shell.h
@@ -0,0 +1,14 @@
+#ifndef _GPXE_SHELL_H
+#define _GPXE_SHELL_H
+
+/** @file
+ *
+ * Minimal command shell
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern void shell ( void );
+
+#endif /* _GPXE_SHELL_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/shell_banner.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/shell_banner.h
new file mode 100644
index 0000000..28482be
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/shell_banner.h
@@ -0,0 +1,14 @@
+#ifndef _GPXE_SHELL_BANNER_H
+#define _GPXE_SHELL_BANNER_H
+
+/** @file
+ *
+ * Shell startup banner
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int shell_banner ( void );
+
+#endif /* _GPXE_SHELL_BANNER_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/smbios.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/smbios.h
new file mode 100644
index 0000000..4df25c3
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/smbios.h
@@ -0,0 +1,161 @@
+#ifndef _GPXE_SMBIOS_H
+#define _GPXE_SMBIOS_H
+
+/** @file
+ *
+ * System Management BIOS
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/api.h>
+#include <config/general.h>
+#include <gpxe/uaccess.h>
+
+/**
+ * Provide an SMBIOS API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_SMBIOS( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( SMBIOS_PREFIX_ ## _subsys, _api_func, _func )
+
+/* Include all architecture-independent SMBIOS API headers */
+#include <gpxe/efi/efi_smbios.h>
+
+/* Include all architecture-dependent SMBIOS API headers */
+#include <bits/smbios.h>
+
+/** Signature for SMBIOS entry point */
+#define SMBIOS_SIGNATURE \
+ ( ( '_' << 0 ) + ( 'S' << 8 ) + ( 'M' << 16 ) + ( '_' << 24 ) )
+
+/**
+ * SMBIOS entry point
+ *
+ * This is the single table which describes the list of SMBIOS
+ * structures. It is located by scanning through the BIOS segment.
+ */
+struct smbios_entry {
+ /** Signature
+ *
+ * Must be equal to SMBIOS_SIGNATURE
+ */
+ uint32_t signature;
+ /** Checksum */
+ uint8_t checksum;
+ /** Length */
+ uint8_t len;
+ /** Major version */
+ uint8_t major;
+ /** Minor version */
+ uint8_t minor;
+ /** Maximum structure size */
+ uint16_t max;
+ /** Entry point revision */
+ uint8_t revision;
+ /** Formatted area */
+ uint8_t formatted[5];
+ /** DMI Signature */
+ uint8_t dmi_signature[5];
+ /** DMI checksum */
+ uint8_t dmi_checksum;
+ /** Structure table length */
+ uint16_t smbios_len;
+ /** Structure table address */
+ uint32_t smbios_address;
+ /** Number of SMBIOS structures */
+ uint16_t smbios_count;
+ /** BCD revision */
+ uint8_t bcd_revision;
+} __attribute__ (( packed ));
+
+/** An SMBIOS structure header */
+struct smbios_header {
+ /** Type */
+ uint8_t type;
+ /** Length */
+ uint8_t len;
+ /** Handle */
+ uint16_t handle;
+} __attribute__ (( packed ));
+
+/** SMBIOS structure descriptor */
+struct smbios_structure {
+ /** Copy of SMBIOS structure header */
+ struct smbios_header header;
+ /** Offset of structure within SMBIOS */
+ size_t offset;
+ /** Length of strings section */
+ size_t strings_len;
+};
+
+/** SMBIOS system information structure */
+struct smbios_system_information {
+ /** SMBIOS structure header */
+ struct smbios_header header;
+ /** Manufacturer string */
+ uint8_t manufacturer;
+ /** Product string */
+ uint8_t product;
+ /** Version string */
+ uint8_t version;
+ /** Serial number string */
+ uint8_t serial;
+ /** UUID */
+ uint8_t uuid[16];
+ /** Wake-up type */
+ uint8_t wakeup;
+} __attribute__ (( packed ));
+
+/** SMBIOS system information structure type */
+#define SMBIOS_TYPE_SYSTEM_INFORMATION 1
+
+/** SMBIOS enclosure information structure */
+struct smbios_enclosure_information {
+ /** SMBIOS structure header */
+ struct smbios_header header;
+ /** Manufacturer string */
+ uint8_t manufacturer;
+ /** Type string */
+ uint8_t type;
+ /** Version string */
+ uint8_t version;
+ /** Serial number string */
+ uint8_t serial;
+ /** Asset tag */
+ uint8_t asset_tag;
+} __attribute__ (( packed ));
+
+/** SMBIOS enclosure information structure type */
+#define SMBIOS_TYPE_ENCLOSURE_INFORMATION 3
+
+/**
+ * SMBIOS entry point descriptor
+ *
+ * This contains the information from the SMBIOS entry point that we
+ * care about.
+ */
+struct smbios {
+ /** Start of SMBIOS structures */
+ userptr_t address;
+ /** Length of SMBIOS structures */
+ size_t len;
+ /** Number of SMBIOS structures */
+ unsigned int count;
+};
+
+extern int find_smbios ( struct smbios *smbios );
+extern int find_smbios_structure ( unsigned int type,
+ struct smbios_structure *structure );
+extern int read_smbios_structure ( struct smbios_structure *structure,
+ void *data, size_t len );
+extern int read_smbios_string ( struct smbios_structure *structure,
+ unsigned int index,
+ void *data, size_t len );
+
+#endif /* _GPXE_SMBIOS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/socket.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/socket.h
new file mode 100644
index 0000000..9ea0db9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/socket.h
@@ -0,0 +1,101 @@
+#ifndef _GPXE_SOCKET_H
+#define _GPXE_SOCKET_H
+
+/** @file
+ *
+ * Socket addresses
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/**
+ * @defgroup commtypes Communication semantics
+ *
+ * @{
+ */
+
+/** Connection-based, reliable streams */
+extern int tcp_sock_stream;
+#define TCP_SOCK_STREAM 0x1
+#define SOCK_STREAM tcp_sock_stream
+
+/** Connectionless, unreliable streams */
+extern int udp_sock_dgram;
+#define UDP_SOCK_DGRAM 0x2
+#define SOCK_DGRAM udp_sock_dgram
+
+/** @} */
+
+/**
+ * Name communication semantics
+ *
+ * @v semantics Communication semantics (e.g. SOCK_STREAM)
+ * @ret name Name of communication semantics
+ */
+static inline __attribute__ (( always_inline )) const char *
+socket_semantics_name ( int semantics ) {
+ /* Cannot use a switch() because of the {TCP_UDP}_SOCK_XXX hack */
+ if ( semantics == SOCK_STREAM ) {
+ return "SOCK_STREAM";
+ } else if ( semantics == SOCK_DGRAM ) {
+ return "SOCK_DGRAM";
+ } else {
+ return "SOCK_UNKNOWN";
+ }
+}
+
+/**
+ * @defgroup addrfam Address families
+ *
+ * @{
+ */
+#define AF_INET 1 /**< IPv4 Internet addresses */
+#define AF_INET6 2 /**< IPv6 Internet addresses */
+/** @} */
+
+/**
+ * Name address family
+ *
+ * @v family Address family (e.g. AF_INET)
+ * @ret name Name of address family
+ */
+static inline __attribute__ (( always_inline )) const char *
+socket_family_name ( int family ) {
+ switch ( family ) {
+ case AF_INET: return "AF_INET";
+ case AF_INET6: return "AF_INET6";
+ default: return "AF_UNKNOWN";
+ }
+}
+
+/** A socket address family */
+typedef uint16_t sa_family_t;
+
+/** Length of a @c struct @c sockaddr */
+#define SA_LEN 32
+
+/**
+ * Generalized socket address structure
+ *
+ * This contains the fields common to socket addresses for all address
+ * families.
+ */
+struct sockaddr {
+ /** Socket address family
+ *
+ * This is an AF_XXX constant.
+ */
+ sa_family_t sa_family;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ SA_LEN - sizeof ( sa_family_t ) ];
+} __attribute__ (( may_alias ));
+
+#endif /* _GPXE_SOCKET_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/spi.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/spi.h
new file mode 100644
index 0000000..8e4a676
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/spi.h
@@ -0,0 +1,258 @@
+#ifndef _GPXE_SPI_H
+#define _GPXE_SPI_H
+
+/** @file
+ *
+ * SPI interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/nvs.h>
+
+/**
+ * @defgroup spicmds SPI commands
+ * @{
+ */
+
+/** Write status register */
+#define SPI_WRSR 0x01
+
+/** Write data to memory array */
+#define SPI_WRITE 0x02
+
+/** Read data from memory array */
+#define SPI_READ 0x03
+
+/** Reset write enable latch */
+#define SPI_WRDI 0x04
+
+/** Read status register */
+#define SPI_RDSR 0x05
+
+/** Set write enable latch */
+#define SPI_WREN 0x06
+
+/**
+ * @defgroup atmelcmds Atmel-specific SPI commands
+ * @{
+ */
+
+/** Erase one sector in memory array (Not supported on all devices) */
+#define ATMEL_SECTOR_ERASE 0x52
+
+/** Erase all sections in memory array (Not supported on all devices) */
+#define ATMEL_CHIP_ERASE 0x62
+
+/** Read manufacturer and product ID (Not supported on all devices) */
+#define ATMEL_RDID 0x15
+
+/** @} */
+
+/** @} */
+
+/**
+ * @defgroup spistatus SPI status register bits (not present on all devices)
+ * @{
+ */
+
+/** Write-protect pin enabled */
+#define SPI_STATUS_WPEN 0x80
+
+/** Block protection bit 2 */
+#define SPI_STATUS_BP2 0x10
+
+/** Block protection bit 1 */
+#define SPI_STATUS_BP1 0x08
+
+/** Block protection bit 0 */
+#define SPI_STATUS_BP0 0x04
+
+/** State of the write enable latch */
+#define SPI_STATUS_WEN 0x02
+
+/** Device busy flag */
+#define SPI_STATUS_NRDY 0x01
+
+/** @} */
+
+/**
+ * An SPI device
+ *
+ * This data structure represents a physical SPI device attached to an
+ * SPI bus.
+ */
+struct spi_device {
+ /** NVS device */
+ struct nvs_device nvs;
+ /** SPI bus to which device is attached */
+ struct spi_bus *bus;
+ /** Slave number */
+ unsigned int slave;
+ /** Command length, in bits */
+ unsigned int command_len;
+ /** Address length, in bits */
+ unsigned int address_len;
+ /** Address is munged
+ *
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM)
+ * use bit 3 of the command byte as address bit A8, rather
+ * than having a two-byte address. If this flag is set, then
+ * commands should be munged in this way.
+ */
+ unsigned int munge_address : 1;
+};
+
+/**
+ * SPI magic autodetection address length
+ *
+ * Set @c spi_device::address_len to @c SPI_AUTODETECT_ADDRESS_LEN if
+ * the address length should be autodetected.
+ */
+#define SPI_AUTODETECT_ADDRESS_LEN 0
+
+static inline __attribute__ (( always_inline )) struct spi_device *
+nvs_to_spi ( struct nvs_device *nvs ) {
+ return container_of ( nvs, struct spi_device, nvs );
+}
+
+/**
+ * An SPI bus
+ *
+ * This data structure represents an SPI bus controller capable of
+ * issuing commands to attached SPI devices.
+ */
+struct spi_bus {
+ /** SPI interface mode
+ *
+ * This is the bitwise OR of zero or more of @c SPI_MODE_CPHA
+ * and @c SPI_MODE_CPOL. It is also the number conventionally
+ * used to describe the SPI interface mode. For example, SPI
+ * mode 1 is the mode in which CPOL=0 and CPHA=1, which
+ * therefore corresponds to a mode value of (0|SPI_MODE_CPHA)
+ * which, happily, equals 1.
+ */
+ unsigned int mode;
+ /**
+ * Read/write data via SPI bus
+ *
+ * @v bus SPI bus
+ * @v device SPI device
+ * @v command Command
+ * @v address Address to read/write (<0 for no address)
+ * @v data_out TX data buffer (or NULL)
+ * @v data_in RX data buffer (or NULL)
+ * @v len Length of data buffer(s)
+ *
+ * This issues the specified command and optional address to
+ * the SPI device, then reads and/or writes data to/from the
+ * data buffers.
+ */
+ int ( * rw ) ( struct spi_bus *bus, struct spi_device *device,
+ unsigned int command, int address,
+ const void *data_out, void *data_in, size_t len );
+};
+
+/** Clock phase (CPHA) mode bit
+ *
+ * Phase 0 is sample on rising edge, shift data on falling edge.
+ *
+ * Phase 1 is shift data on rising edge, sample data on falling edge.
+ */
+#define SPI_MODE_CPHA 0x01
+
+/** Clock polarity (CPOL) mode bit
+ *
+ * This bit reflects the idle state of the clock line (SCLK).
+ */
+#define SPI_MODE_CPOL 0x02
+
+/** Slave select polarity mode bit
+ *
+ * This bit reflects that active state of the slave select lines. It
+ * is not part of the normal SPI mode number (which covers only @c
+ * SPI_MODE_CPOL and @c SPI_MODE_CPHA), but is included here for
+ * convenience.
+ */
+#define SPI_MODE_SSPOL 0x10
+
+/** Microwire-compatible mode
+ *
+ * This is SPI mode 1 (i.e. CPOL=0, CPHA=1), and is compatible with
+ * the original Microwire protocol.
+ */
+#define SPI_MODE_MICROWIRE 1
+
+/** Microwire/Plus-compatible mode
+ *
+ * This is SPI mode 0 (i.e. CPOL=0, CPHA=0), and is compatible with
+ * the Microwire/Plus protocol
+ */
+#define SPI_MODE_MICROWIRE_PLUS 0
+
+/** Threewire-compatible mode
+ *
+ * This mode is compatible with Atmel's series of "three-wire"
+ * interfaces.
+ */
+#define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL )
+
+extern int spi_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int spi_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+
+/**
+ * @defgroup spidevs SPI device types
+ * @{
+ */
+
+static inline __attribute__ (( always_inline )) void
+init_spi ( struct spi_device *device ) {
+ device->nvs.word_len_log2 = 0;
+ device->command_len = 8,
+ device->nvs.read = spi_read;
+ device->nvs.write = spi_write;
+}
+
+/** Atmel AT25F1024 serial flash */
+static inline __attribute__ (( always_inline )) void
+init_at25f1024 ( struct spi_device *device ) {
+ device->address_len = 24;
+ device->nvs.size = ( 128 * 1024 );
+ device->nvs.block_size = 256;
+ init_spi ( device );
+}
+
+/** Atmel 25040 serial EEPROM */
+static inline __attribute__ (( always_inline )) void
+init_at25040 ( struct spi_device *device ) {
+ device->address_len = 8;
+ device->munge_address = 1;
+ device->nvs.size = 512;
+ device->nvs.block_size = 8;
+ init_spi ( device );
+}
+
+/** ST M25P32 serial flash */
+static inline __attribute__ (( always_inline )) void
+init_m25p32 ( struct spi_device *device ) {
+ device->address_len = 24;
+ device->nvs.size = ( 4 * 1024 * 1024 );
+ device->nvs.block_size = 256;
+ init_spi ( device );
+}
+
+/** Microchip 25XX640 serial EEPROM */
+static inline __attribute__ (( always_inline )) void
+init_mc25xx640 ( struct spi_device *device ) {
+ device->address_len = 16;
+ device->nvs.size = ( 8 * 1024 );
+ device->nvs.block_size = 32;
+ init_spi ( device );
+}
+
+/** @} */
+
+#endif /* _GPXE_SPI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/spi_bit.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/spi_bit.h
new file mode 100644
index 0000000..8bd2519
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/spi_bit.h
@@ -0,0 +1,63 @@
+#ifndef _GPXE_SPI_BIT_H
+#define _GPXE_SPI_BIT_H
+
+/** @file
+ *
+ * SPI bit-bashing interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/spi.h>
+#include <gpxe/bitbash.h>
+
+/** A bit-bashing SPI bus */
+struct spi_bit_basher {
+ /** SPI bus */
+ struct spi_bus bus;
+ /** Bit-bashing interface */
+ struct bit_basher basher;
+ /** Endianness of data
+ *
+ * SPI commands and addresses are always big-endian (i.e. MSB
+ * transmitted first on the wire), but some cards
+ * (e.g. natsemi) choose to regard the data stored in the
+ * EEPROM as little-endian (i.e. LSB transmitted first on the
+ * wire).
+ */
+ int endianness;
+};
+
+/** Bit indices used for SPI bit-bashing interface */
+enum {
+ /** Serial clock */
+ SPI_BIT_SCLK = 0,
+ /** Master Out Slave In */
+ SPI_BIT_MOSI,
+ /** Master In Slave Out */
+ SPI_BIT_MISO,
+ /** Slave 0 select */
+ SPI_BIT_SS0,
+};
+
+/**
+ * Determine bit index for a particular slave
+ *
+ * @v slave Slave number
+ * @ret index Bit index (i.e. SPI_BIT_SSN, where N=slave)
+ */
+#define SPI_BIT_SS( slave ) ( SPI_BIT_SS0 + (slave) )
+
+/** Delay between SCLK transitions */
+#define SPI_BIT_UDELAY 1
+
+/** SPI bit basher treats data as big-endian */
+#define SPI_BIT_BIG_ENDIAN 0
+
+/** SPI bit basher treats data as little-endian */
+#define SPI_BIT_LITTLE_ENDIAN 1
+
+extern void init_spi_bit_basher ( struct spi_bit_basher *spibit );
+
+#endif /* _GPXE_SPI_BIT_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/srp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/srp.h
new file mode 100644
index 0000000..85f39b9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/srp.h
@@ -0,0 +1,868 @@
+#ifndef _GPXE_SRP_H
+#define _GPXE_SRP_H
+
+/** @file
+ *
+ * SCSI RDMA Protocol
+ *
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/xfer.h>
+#include <gpxe/scsi.h>
+
+/*****************************************************************************
+ *
+ * Common fields
+ *
+ *****************************************************************************
+ */
+
+/** An SRP information unit tag */
+struct srp_tag {
+ uint32_t dwords[2];
+} __attribute__ (( packed ));
+
+/** An SRP port ID */
+struct srp_port_id {
+ uint8_t bytes[16];
+} __attribute__ (( packed ));
+
+/** An SRP port ID pair */
+struct srp_port_ids {
+ /** Initiator port ID */
+ struct srp_port_id initiator;
+ /** Target port ID */
+ struct srp_port_id target;
+} __attribute__ (( packed ));
+
+/** SRP information unit common fields */
+struct srp_common {
+ /** Information unit type */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ struct srp_tag tag;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * Login request
+ *
+ *****************************************************************************
+ */
+
+/** An SRP login request information unit */
+struct srp_login_req {
+ /** Information unit type
+ *
+ * This must be @c SRP_LOGIN_REQ
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ struct srp_tag tag;
+ /** Requested maximum initiator to target IU length */
+ uint32_t max_i_t_iu_len;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Required buffer formats
+ *
+ * This is the bitwise OR of one or more @c
+ * SRP_LOGIN_REQ_FMT_XXX constants.
+ */
+ uint16_t required_buffer_formats;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_LOGIN_REQ_FLAG_XXX and @c SRP_LOGIN_REQ_MCA_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved2[5];
+ /** Initiator and target port identifiers */
+ struct srp_port_ids port_ids;
+} __attribute__ (( packed ));
+
+/** Type of an SRP login request */
+#define SRP_LOGIN_REQ 0x00
+
+/** Require indirect data buffer descriptor format */
+#define SRP_LOGIN_REQ_FMT_IDBD 0x04
+
+/** Require direct data buffer descriptor format */
+#define SRP_LOGIN_REQ_FMT_DDBD 0x02
+
+/** Use solicited notification for asynchronous events */
+#define SRP_LOGIN_REQ_FLAG_AESOLNT 0x40
+
+/** Use solicited notification for credit request */
+#define SRP_LOGIN_REQ_FLAG_CRSOLNT 0x20
+
+/** Use solicited notification for logouts */
+#define SRP_LOGIN_REQ_FLAG_LOSOLNT 0x10
+
+/** Multi-channel action mask */
+#define SRP_LOGIN_REQ_MCA_MASK 0x03
+
+/** Single RDMA channel operation */
+#define SRP_LOGIN_REQ_MCA_SINGLE_CHANNEL 0x00
+
+/** Multiple independent RDMA channel operation */
+#define SRP_LOGIN_REQ_MCA_MULTIPLE_CHANNELS 0x01
+
+/*****************************************************************************
+ *
+ * Login response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP login response */
+struct srp_login_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_LOGIN_RSP
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ struct srp_tag tag;
+ /** Maximum initiator to target IU length */
+ uint32_t max_i_t_iu_len;
+ /** Maximum target to initiator IU length */
+ uint32_t max_t_i_iu_len;
+ /** Supported buffer formats
+ *
+ * This is the bitwise OR of one or more @c
+ * SRP_LOGIN_RSP_FMT_XXX constants.
+ */
+ uint16_t supported_buffer_formats;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_LOGIN_RSP_FLAG_XXX and @c SRP_LOGIN_RSP_MCR_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved1[25];
+} __attribute__ (( packed ));
+
+/** Type of an SRP login response */
+#define SRP_LOGIN_RSP 0xc0
+
+/** Indirect data buffer descriptor format supported */
+#define SRP_LOGIN_RSP_FMT_IDBD 0x04
+
+/** Direct data buffer descriptor format supported */
+#define SRP_LOGIN_RSP_FMT_DDBD 0x02
+
+/** Solicited notification is supported */
+#define SRP_LOGIN_RSP_FLAG_SOLNTSUP 0x10
+
+/** Multi-channel result mask */
+#define SRP_LOGIN_RSP_MCR_MASK 0x03
+
+/** No existing RDMA channels were associated with the same I_T nexus */
+#define SRP_LOGIN_RSP_MCR_NO_EXISTING_CHANNELS 0x00
+
+/** One or more existing RDMA channels were terminated */
+#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_TERMINATED 0x01
+
+/** One or more existing RDMA channels continue to operate independently */
+#define SRP_LOGIN_RSP_MCR_EXISTING_CHANNELS_CONTINUE 0x02
+
+/*****************************************************************************
+ *
+ * Login rejection
+ *
+ *****************************************************************************
+ */
+
+/** An SRP login rejection */
+struct srp_login_rej {
+ /** Information unit type
+ *
+ * This must be @c SRP_LOGIN_REJ
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Reason
+ *
+ * This is a @c SRP_LOGIN_REJ_REASON_XXX constant.
+ */
+ uint32_t reason;
+ /** Tag */
+ struct srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[8];
+ /** Supported buffer formats
+ *
+ * This is the bitwise OR of one or more @c
+ * SRP_LOGIN_REJ_FMT_XXX constants.
+ */
+ uint16_t supported_buffer_formats;
+ /** Reserved */
+ uint8_t reserved2[6];
+} __attribute__ (( packed ));
+
+/** Type of an SRP login rejection */
+#define SRP_LOGIN_REJ 0xc2
+
+/** Unable to establish RDMA channel, no reason specified */
+#define SRP_LOGIN_REJ_REASON_UNKNOWN 0x00010000UL
+
+/** Insufficient RDMA channel resources */
+#define SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES 0x00010001UL
+
+/** Requested maximum initiator to target IU length value too large */
+#define SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN 0x00010002UL
+
+/** Unable to associate RDMA channel with specified I_T nexus */
+#define SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE 0x00010003UL
+
+/** One or more requested data buffer descriptor formats are not supported */
+#define SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT 0x00010004UL
+
+/** SRP target port does not support multiple RDMA channels per I_T nexus */
+#define SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS 0x00010005UL
+
+/** RDMA channel limit reached for this initiator */
+#define SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS 0x00010006UL
+
+/** Indirect data buffer descriptor format supported */
+#define SRP_LOGIN_REJ_FMT_IDBD 0x04
+
+/** Direct data buffer descriptor format supported */
+#define SRP_LOGIN_REJ_FMT_DDBD 0x02
+
+/*****************************************************************************
+ *
+ * Initiator logout
+ *
+ *****************************************************************************
+ */
+
+/** An SRP initiator logout request */
+struct srp_i_logout {
+ /** Information unit type
+ *
+ * This must be @c SRP_I_LOGOUT
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ struct srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP initiator logout request */
+#define SRP_I_LOGOUT 0x03
+
+/*****************************************************************************
+ *
+ * Target logout
+ *
+ *****************************************************************************
+ */
+
+/** An SRP target logout request */
+struct srp_t_logout {
+ /** Information unit type
+ *
+ * This must be @c SRP_T_LOGOUT
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_T_LOGOUT_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Reason
+ *
+ * This is a @c SRP_T_LOGOUT_REASON_XXX constant.
+ */
+ uint32_t reason;
+ /** Tag */
+ struct srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP target logout request */
+#define SRP_T_LOGOUT 0x80
+
+/** The initiator specified solicited notification of logouts */
+#define SRP_T_LOGOUT_FLAG_SOLNT 0x01
+
+/** No reason specified */
+#define SRP_T_LOGOUT_REASON_UNKNOWN 0x00000000UL
+
+/** Inactive RDMA channel (reclaiming resources) */
+#define SRP_T_LOGOUT_REASON_INACTIVE 0x00000001UL
+
+/** Invalid information unit type code received by SRP target port */
+#define SRP_T_LOGOUT_REASON_INVALID_TYPE 0x00000002UL
+
+/** SRP initiator port sent response with no corresponding request */
+#define SRP_T_LOGOUT_REASON_SPURIOUS_RESPONSE 0x00000003UL
+
+/** RDMA channel disconnected due to multi-channel action code in new login */
+#define SRP_T_LOGOUT_REASON_MCA 0x00000004UL
+
+/** Unsuppported format code value specified in data-out buffer descriptor */
+#define SRP_T_LOGOUT_UNSUPPORTED_DATA_OUT_FORMAT 0x00000005UL
+
+/** Unsuppported format code value specified in data-in buffer descriptor */
+#define SRP_T_LOGOUT_UNSUPPORTED_DATA_IN_FORMAT 0x00000006UL
+
+/** Invalid length for IU type */
+#define SRP_T_LOGOUT_INVALID_IU_LEN 0x00000008UL
+
+/*****************************************************************************
+ *
+ * Task management
+ *
+ *****************************************************************************
+ */
+
+/** An SRP task management request */
+struct srp_tsk_mgmt {
+ /** Information unit type
+ *
+ * This must be @c SRP_TSK_MGMT
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more
+ * @c SRP_TSK_MGMT_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[6];
+ /** Tag */
+ struct srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Reserved */
+ uint8_t reserved2[2];
+ /** Task management function
+ *
+ * This is a @c SRP_TASK_MGMT_FUNC_XXX constant
+ */
+ uint8_t function;
+ /** Reserved */
+ uint8_t reserved3[1];
+ /** Tag of task to be managed */
+ struct srp_tag managed_tag;
+ /** Reserved */
+ uint8_t reserved4[8];
+} __attribute__ (( packed ));
+
+/** Type of an SRP task management request */
+#define SRP_TSK_MGMT 0x01
+
+/** Use solicited notification for unsuccessful completions */
+#define SRP_TSK_MGMT_FLAG_UCSOLNT 0x04
+
+/** Use solicited notification for successful completions */
+#define SRP_TSK_MGMT_FLAG_SCSOLNT 0x02
+
+/** The task manager shall perform an ABORT TASK function */
+#define SRP_TSK_MGMT_FUNC_ABORT_TASK 0x01
+
+/** The task manager shall perform an ABORT TASK SET function */
+#define SRP_TSK_MGMT_FUNC_ABORT_TASK_SET 0x02
+
+/** The task manager shall perform a CLEAR TASK SET function */
+#define SRP_TSK_MGMT_FUNC_CLEAR_TASK_SET 0x04
+
+/** The task manager shall perform a LOGICAL UNIT RESET function */
+#define SRP_TSK_MGMT_FUNC_LOGICAL_UNIT_RESET 0x08
+
+/** The task manager shall perform a CLEAR ACA function */
+#define SRP_TSK_MGMT_FUNC_CLEAR_ACA 0x40
+
+/*****************************************************************************
+ *
+ * SCSI command
+ *
+ *****************************************************************************
+ */
+
+/** An SRP SCSI command */
+struct srp_cmd {
+ /** Information unit type
+ *
+ * This must be @c SRP_CMD
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c SRP_CMD_FLAG_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[3];
+ /** Data buffer descriptor formats
+ *
+ * This is the bitwise OR of one @c SRP_CMD_DO_FMT_XXX and one @c
+ * SRP_CMD_DI_FMT_XXX constant.
+ */
+ uint8_t data_buffer_formats;
+ /** Data-out buffer descriptor count */
+ uint8_t data_out_buffer_count;
+ /** Data-in buffer descriptor count */
+ uint8_t data_in_buffer_count;
+ /** Tag */
+ struct srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Reserved */
+ uint8_t reserved2[1];
+ /** Task attribute
+ *
+ * This is a @c SRP_CMD_TASK_ATTR_XXX constant.
+ */
+ uint8_t task_attr;
+ /** Reserved */
+ uint8_t reserved3[1];
+ /** Additional CDB length */
+ uint8_t additional_cdb_len;
+ /** Command data block */
+ union scsi_cdb cdb;
+} __attribute__ (( packed ));
+
+/** Type of an SRP SCSI command */
+#define SRP_CMD 0x02
+
+/** Use solicited notification for unsuccessful completions */
+#define SRP_CMD_FLAG_UCSOLNT 0x04
+
+/** Use solicited notification for successful completions */
+#define SRP_CMD_FLAG_SCSOLNT 0x02
+
+/** Data-out buffer format mask */
+#define SRP_CMD_DO_FMT_MASK 0xf0
+
+/** Direct data-out buffer format */
+#define SRP_CMD_DO_FMT_DIRECT 0x10
+
+/** Indirect data-out buffer format */
+#define SRP_CMD_DO_FMT_INDIRECT 0x20
+
+/** Data-in buffer format mask */
+#define SRP_CMD_DI_FMT_MASK 0x0f
+
+/** Direct data-in buffer format */
+#define SRP_CMD_DI_FMT_DIRECT 0x01
+
+/** Indirect data-in buffer format */
+#define SRP_CMD_DI_FMT_INDIRECT 0x02
+
+/** Use the rules for a simple task attribute */
+#define SRP_CMD_TASK_ATTR_SIMPLE 0x00
+
+/** Use the rules for a head of queue task attribute */
+#define SRP_CMD_TASK_ATTR_QUEUE_HEAD 0x01
+
+/** Use the rules for an ordered task attribute */
+#define SRP_CMD_TASK_ATTR_ORDERED 0x02
+
+/** Use the rules for an automatic contingent allegiance task attribute */
+#define SRP_CMD_TASK_ATTR_AUTOMATIC_CONTINGENT_ALLEGIANCE 0x08
+
+/** An SRP memory descriptor */
+struct srp_memory_descriptor {
+ /** Virtual address */
+ uint64_t address;
+ /** Memory handle */
+ uint32_t handle;
+ /** Data length */
+ uint32_t len;
+} __attribute__ (( packed ));
+
+/*****************************************************************************
+ *
+ * SCSI response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP SCSI response */
+struct srp_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_RSP
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c SRP_RSP_FLAG_XXX
+ * constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ struct srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[2];
+ /** Valid fields
+ *
+ * This is the bitwise OR of zero or more @c SRP_RSP_VALID_XXX
+ * constants.
+ */
+ uint8_t valid;
+ /** Status
+ *
+ * This is the SCSI status code.
+ */
+ uint8_t status;
+ /** Data-out residual count */
+ uint32_t data_out_residual_count;
+ /** Data-in residual count */
+ uint32_t data_in_residual_count;
+ /** Sense data list length */
+ uint32_t sense_data_len;
+ /** Response data list length */
+ uint32_t response_data_len;
+} __attribute__ (( packed ));
+
+/** Type of an SRP SCSI response */
+#define SRP_RSP 0xc1
+
+/** The initiator specified solicited notification of this response */
+#define SRP_RSP_FLAG_SOLNT 0x01
+
+/** Data-in residual count field is valid and represents an underflow */
+#define SRP_RSP_VALID_DIUNDER 0x20
+
+/** Data-in residual count field is valid and represents an overflow */
+#define SRP_RSP_VALID_DIOVER 0x10
+
+/** Data-out residual count field is valid and represents an underflow */
+#define SRP_RSP_VALID_DOUNDER 0x08
+
+/** Data-out residual count field is valid and represents an overflow */
+#define SRP_RSP_VALID_DOOVER 0x04
+
+/** Sense data list length field is valid */
+#define SRP_RSP_VALID_SNSVALID 0x02
+
+/** Response data list length field is valid */
+#define SRP_RSP_VALID_RSPVALID 0x01
+
+/**
+ * Get response data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret response_data Response data, or NULL if not present
+ */
+static inline void * srp_rsp_response_data ( struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
+ ( ( ( void * ) rsp ) + sizeof ( *rsp ) ) : NULL );
+}
+
+/**
+ * Get length of response data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret response_data_len Response data length
+ */
+static inline size_t srp_rsp_response_data_len ( struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_RSPVALID ) ?
+ ntohl ( rsp->response_data_len ) : 0 );
+}
+
+/**
+ * Get sense data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret sense_data Sense data, or NULL if not present
+ */
+static inline void * srp_rsp_sense_data ( struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
+ ( ( ( void * ) rsp ) + sizeof ( *rsp ) +
+ srp_rsp_response_data_len ( rsp ) ) : NULL );
+}
+
+/**
+ * Get length of sense data portion of SCSI response
+ *
+ * @v rsp SCSI response
+ * @ret sense_data_len Sense data length
+ */
+static inline size_t srp_rsp_sense_data_len ( struct srp_rsp *rsp ) {
+ return ( ( rsp->valid & SRP_RSP_VALID_SNSVALID ) ?
+ ntohl ( rsp->sense_data_len ) : 0 );
+}
+
+/*****************************************************************************
+ *
+ * Credit request
+ *
+ *****************************************************************************
+ */
+
+/** An SRP credit request */
+struct srp_cred_req {
+ /** Information unit type
+ *
+ * This must be @c SRP_CRED_REQ
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more
+ * @c SRP_CRED_REQ_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ struct srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP credit request */
+#define SRP_CRED_REQ 0x81
+
+/** The initiator specified solicited notification of credit requests */
+#define SRP_CRED_REQ_FLAG_SOLNT 0x01
+
+/*****************************************************************************
+ *
+ * Credit response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP credit response */
+struct srp_cred_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_CRED_RSP
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ struct srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP credit response */
+#define SRP_CRED_RSP 0x41
+
+/*****************************************************************************
+ *
+ * Asynchronous event request
+ *
+ *****************************************************************************
+ */
+
+/** An SRP asynchronous event request */
+struct srp_aer_req {
+ /** Information unit type
+ *
+ * This must be @c SRP_AER_REQ
+ */
+ uint8_t type;
+ /** Flags
+ *
+ * This is the bitwise OR of zero or more @c
+ * SRP_AER_REQ_FLAG_XXX constants.
+ */
+ uint8_t flags;
+ /** Reserved */
+ uint8_t reserved0[2];
+ /** Request limit delta */
+ uint32_t request_limit_delta;
+ /** Tag */
+ struct srp_tag tag;
+ /** Reserved */
+ uint8_t reserved1[4];
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Sense data list length */
+ uint32_t sense_data_len;
+ /** Reserved */
+ uint8_t reserved2[4];
+} __attribute__ (( packed ));
+
+/** Type of an SRP asynchronous event request */
+#define SRP_AER_REQ 0x82
+
+/** The initiator specified solicited notification of asynchronous events */
+#define SRP_AER_REQ_FLAG_SOLNT 0x01
+
+/**
+ * Get sense data portion of asynchronous event request
+ *
+ * @v aer_req SRP asynchronous event request
+ * @ret sense_data Sense data
+ */
+static inline __always_inline void *
+srp_aer_req_sense_data ( struct srp_aer_req *aer_req ) {
+ return ( ( ( void * ) aer_req ) + sizeof ( *aer_req ) );
+}
+
+/**
+ * Get length of sense data portion of asynchronous event request
+ *
+ * @v aer_req SRP asynchronous event request
+ * @ret sense_data_len Sense data length
+ */
+static inline __always_inline size_t
+srp_aer_req_sense_data_len ( struct srp_aer_req *aer_req ) {
+ return ( ntohl ( aer_req->sense_data_len ) );
+}
+
+/*****************************************************************************
+ *
+ * Asynchronous event response
+ *
+ *****************************************************************************
+ */
+
+/** An SRP asynchronous event response */
+struct srp_aer_rsp {
+ /** Information unit type
+ *
+ * This must be @c SRP_AER_RSP
+ */
+ uint8_t type;
+ /** Reserved */
+ uint8_t reserved0[7];
+ /** Tag */
+ struct srp_tag tag;
+} __attribute__ (( packed ));
+
+/** Type of an SRP asynchronous event response */
+#define SRP_AER_RSP 0x42
+
+/*****************************************************************************
+ *
+ * Information units
+ *
+ *****************************************************************************
+ */
+
+/** Maximum length of any initiator-to-target IU that we will send
+ *
+ * The longest IU is a SRP_CMD with no additional CDB and two direct
+ * data buffer descriptors, which comes to 80 bytes.
+ */
+#define SRP_MAX_I_T_IU_LEN 80
+
+/*****************************************************************************
+ *
+ * SRP device
+ *
+ *****************************************************************************
+ */
+
+struct srp_device;
+
+/** An SRP transport type */
+struct srp_transport_type {
+ /** Length of transport private data */
+ size_t priv_len;
+ /** Parse root path
+ *
+ * @v srp SRP device
+ * @v root_path Root path
+ * @ret Return status code
+ */
+ int ( * parse_root_path ) ( struct srp_device *srp,
+ const char *root_path );
+ /** Connect SRP session
+ *
+ * @v srp SRP device
+ * @ret rc Return status code
+ *
+ * This method should open the underlying socket.
+ */
+ int ( * connect ) ( struct srp_device *srp );
+};
+
+/** An SRP device */
+struct srp_device {
+ /** Reference count */
+ struct refcnt refcnt;
+
+ /** Initiator and target port IDs */
+ struct srp_port_ids port_ids;
+ /** Logical unit number */
+ struct scsi_lun lun;
+ /** Memory handle */
+ uint32_t memory_handle;
+
+ /** Current state
+ *
+ * This is the bitwise-OR of zero or more @c SRP_STATE_XXX
+ * flags.
+ */
+ unsigned int state;
+ /** Retry counter */
+ unsigned int retry_count;
+ /** Current SCSI command */
+ struct scsi_command *command;
+
+ /** Underlying data transfer interface */
+ struct xfer_interface socket;
+
+ /** Transport type */
+ struct srp_transport_type *transport;
+ /** Transport private data */
+ char transport_priv[0];
+};
+
+/**
+ * Get SRP transport private data
+ *
+ * @v srp SRP device
+ * @ret priv SRP transport private data
+ */
+static inline __always_inline void *
+srp_transport_priv ( struct srp_device *srp ) {
+ return ( ( void * ) srp->transport_priv );
+}
+
+/** SRP state flags */
+enum srp_state {
+ /** Underlying socket is open */
+ SRP_STATE_SOCKET_OPEN = 0x0001,
+ /** Session is logged in */
+ SRP_STATE_LOGGED_IN = 0x0002,
+};
+
+/** Maximum number of SRP retry attempts */
+#define SRP_MAX_RETRIES 3
+
+extern int srp_attach ( struct scsi_device *scsi, const char *root_path );
+extern void srp_detach ( struct scsi_device *scsi );
+
+#endif /* _GPXE_SRP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/tables.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tables.h
new file mode 100644
index 0000000..7dfced8
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tables.h
@@ -0,0 +1,434 @@
+#ifndef _GPXE_TABLES_H
+#define _GPXE_TABLES_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @page ifdef_harmful #ifdef considered harmful
+ *
+ * Overuse of @c #ifdef has long been a problem in Etherboot.
+ * Etherboot provides a rich array of features, but all these features
+ * take up valuable space in a ROM image. The traditional solution to
+ * this problem has been for each feature to have its own @c #ifdef
+ * option, allowing the feature to be compiled in only if desired.
+ *
+ * The problem with this is that it becomes impossible to compile, let
+ * alone test, all possible versions of Etherboot. Code that is not
+ * typically used tends to suffer from bit-rot over time. It becomes
+ * extremely difficult to predict which combinations of compile-time
+ * options will result in code that can even compile and link
+ * correctly.
+ *
+ * To solve this problem, we have adopted a new approach from
+ * Etherboot 5.5 onwards. @c #ifdef is now "considered harmful", and
+ * its use should be minimised. Separate features should be
+ * implemented in separate @c .c files, and should \b always be
+ * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
+ * MY_PET_FEATURE statement). By making (almost) all code always
+ * compile, we avoid the problem of bit-rot in rarely-used code.
+ *
+ * The file config.h, in combination with the @c make command line,
+ * specifies the objects that will be included in any particular build
+ * of Etherboot. For example, suppose that config.h includes the line
+ *
+ * @code
+ *
+ * #define CONSOLE_SERIAL
+ * #define DOWNLOAD_PROTO_TFTP
+ *
+ * @endcode
+ *
+ * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
+ * built, the options specified in config.h are used to drag in the
+ * relevant objects at link-time. For the above example, serial.o and
+ * tftp.o would be linked in.
+ *
+ * There remains one problem to solve: how do these objects get used?
+ * Traditionally, we had code such as
+ *
+ * @code
+ *
+ * #ifdef CONSOLE_SERIAL
+ * serial_init();
+ * #endif
+ *
+ * @endcode
+ *
+ * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
+ * We cannot simply remove the @c #ifdef and make it
+ *
+ * @code
+ *
+ * serial_init();
+ *
+ * @endcode
+ *
+ * because then serial.o would end up always being linked in.
+ *
+ * The solution is to use @link tables.h linker tables @endlink.
+ *
+ */
+
+/** @file
+ *
+ * Linker tables
+ *
+ * Read @ref ifdef_harmful first for some background on the motivation
+ * for using linker tables.
+ *
+ * This file provides macros for dealing with linker-generated tables
+ * of fixed-size symbols. We make fairly extensive use of these in
+ * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
+ * For example, instead of having code such as
+ *
+ * @code
+ *
+ * #ifdef CONSOLE_SERIAL
+ * serial_init();
+ * #endif
+ *
+ * @endcode
+ *
+ * we make serial.c generate an entry in the initialisation function
+ * table, and then have a function call_init_fns() that simply calls
+ * all functions present in this table. If and only if serial.o gets
+ * linked in, then its initialisation function will be called. We
+ * avoid linker symbol pollution (i.e. always dragging in serial.o
+ * just because of a call to serial_init()) and we also avoid @c
+ * #ifdef spaghetti (having to conditionalise every reference to
+ * functions in serial.c).
+ *
+ * The linker script takes care of assembling the tables for us. All
+ * our table sections have names of the format @c .tbl.NAME.NN where
+ * @c NAME designates the data structure stored in the table (e.g. @c
+ * init_fns) and @c NN is a two-digit decimal number used to impose an
+ * ordering upon the tables if required. @c NN=00 is reserved for the
+ * symbol indicating "table start", and @c NN=99 is reserved for the
+ * symbol indicating "table end".
+ *
+ * As an example, suppose that we want to create a "frobnicator"
+ * feature framework, and allow for several independent modules to
+ * provide frobnicating services. Then we would create a frob.h
+ * header file containing e.g.
+ *
+ * @code
+ *
+ * struct frobnicator {
+ * const char *name; // Name of the frobnicator
+ * void ( *frob ) ( void ); // The frobnicating function itself
+ * };
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * @endcode
+ *
+ * Any module providing frobnicating services would look something
+ * like
+ *
+ * @code
+ *
+ * #include "frob.h"
+ *
+ * static void my_frob ( void ) {
+ * // Do my frobnicating
+ * ...
+ * }
+ *
+ * struct frob my_frobnicator __frobnicator = {
+ * .name = "my_frob",
+ * .frob = my_frob,
+ * };
+ *
+ * @endcode
+ *
+ * The central frobnicator code (frob.c) would use the frobnicating
+ * modules as follows
+ *
+ * @code
+ *
+ * #include "frob.h"
+ *
+ * // Call all linked-in frobnicators
+ * void frob_all ( void ) {
+ * struct frob *frob;
+ *
+ * for_each_table ( frob, FROBNICATORS ) {
+ * printf ( "Calling frobnicator \"%s\"\n", frob->name );
+ * frob->frob ();
+ * }
+ * }
+ *
+ * @endcode
+ *
+ * See init.h and init.c for a real-life example.
+ *
+ */
+
+#ifdef DOXYGEN
+#define __attribute__( x )
+#endif
+
+/**
+ * Declare a linker table
+ *
+ * @v type Data type
+ * @v name Table name
+ * @ret table Linker table
+ */
+#define __table( type, name ) ( type, name )
+
+/**
+ * Get linker table data type
+ *
+ * @v table Linker table
+ * @ret type Data type
+ */
+#define __table_type( table ) __table_extract_type table
+#define __table_extract_type( type, name ) type
+
+/**
+ * Get linker table name
+ *
+ * @v table Linker table
+ * @ret name Table name
+ */
+#define __table_name( table ) __table_extract_name table
+#define __table_extract_name( type, name ) name
+
+/**
+ * Get linker table section name
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ * @ret section Section name
+ */
+#define __table_section( table, idx ) \
+ ".tbl." __table_name ( table ) "." __table_str ( idx )
+#define __table_str( x ) #x
+
+/**
+ * Get linker table alignment
+ *
+ * @v table Linker table
+ * @ret align Alignment
+ */
+#define __table_alignment( table ) __alignof__ ( __table_type ( table ) )
+
+/**
+ * Declare a linker table entry
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * #define __frobnicator __table_entry ( FROBNICATORS, 01 )
+ *
+ * struct frobnicator my_frob __frobnicator = {
+ * ...
+ * };
+ *
+ * @endcode
+ */
+#define __table_entry( table, idx ) \
+ __attribute__ (( __section__ ( __table_section ( table, idx ) ),\
+ __aligned__ ( __table_alignment ( table ) ) ))
+
+/**
+ * Get start of linker table entries
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ * @ret entries Start of entries
+ */
+#define __table_entries( table, idx ) ( { \
+ static __table_type ( table ) __table_entries[0] \
+ __table_entry ( table, idx ); \
+ __table_entries; } )
+
+/**
+ * Get start of linker table
+ *
+ * @v table Linker table
+ * @ret start Start of linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frobs = table_start ( FROBNICATORS );
+ *
+ * @endcode
+ */
+#define table_start( table ) __table_entries ( table, 00 )
+
+/**
+ * Get end of linker table
+ *
+ * @v table Linker table
+ * @ret end End of linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frobs_end = table_end ( FROBNICATORS );
+ *
+ * @endcode
+ */
+#define table_end( table ) __table_entries ( table, 99 )
+
+/**
+ * Get number of entries in linker table
+ *
+ * @v table Linker table
+ * @ret num_entries Number of entries in linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * unsigned int num_frobs = table_num_entries ( FROBNICATORS );
+ *
+ * @endcode
+ *
+ */
+#define table_num_entries( table ) \
+ ( ( unsigned int ) ( table_end ( table ) - \
+ table_start ( table ) ) )
+
+/**
+ * Iterate through all entries within a linker table
+ *
+ * @v pointer Entry pointer
+ * @v table Linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frob;
+ *
+ * for_each_table_entry ( frob, FROBNICATORS ) {
+ * ...
+ * }
+ *
+ * @endcode
+ *
+ */
+#define for_each_table_entry( pointer, table ) \
+ for ( pointer = table_start ( table ) ; \
+ pointer < table_end ( table ) ; \
+ pointer++ )
+
+/**
+ * Iterate through all entries within a linker table in reverse order
+ *
+ * @v pointer Entry pointer
+ * @v table Linker table
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * #define FROBNICATORS __table ( struct frobnicator, "frobnicators" )
+ *
+ * struct frobnicator *frob;
+ *
+ * for_each_table_entry_reverse ( frob, FROBNICATORS ) {
+ * ...
+ * }
+ *
+ * @endcode
+ *
+ */
+#define for_each_table_entry_reverse( pointer, table ) \
+ for ( pointer = ( table_end ( table ) - 1 ) ; \
+ pointer >= table_start ( table ) ; \
+ pointer-- )
+
+/******************************************************************************
+ *
+ * Intel's C compiler chokes on several of the constructs used in this
+ * file. The workarounds are ugly, so we use them only for an icc
+ * build.
+ *
+ */
+#define ICC_ALIGN_HACK_FACTOR 128
+#ifdef __ICC
+
+/*
+ * icc miscompiles zero-length arrays by inserting padding to a length
+ * of two array elements. We therefore have to generate the
+ * __table_entries() symbols by hand in asm.
+ *
+ */
+#undef __table_entries
+#define __table_entries( table, idx ) ( { \
+ extern __table_type ( table ) \
+ __table_temp_sym ( idx, __LINE__ ) [] \
+ __table_entry ( table, idx ) \
+ asm ( __table_entries_sym ( table, idx ) ); \
+ __asm__ ( ".ifndef %c0\n\t" \
+ ".section " __table_section ( table, idx ) "\n\t" \
+ ".align %c1\n\t" \
+ "\n%c0:\n\t" \
+ ".previous\n\t" \
+ ".endif\n\t" \
+ : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \
+ "i" ( __table_alignment ( table ) ) ); \
+ __table_temp_sym ( idx, __LINE__ ); } )
+#define __table_entries_sym( table, idx ) \
+ "__tbl_" __table_name ( table ) "_" #idx
+#define __table_temp_sym( a, b ) \
+ ___table_temp_sym( __table_, a, _, b )
+#define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
+
+/*
+ * icc ignores __attribute__ (( aligned (x) )) when it is used to
+ * decrease the compiler's default choice of alignment (which may be
+ * higher than the alignment actually required by the structure). We
+ * work around this by forcing the alignment to a large multiple of
+ * the required value (so that we are never attempting to decrease the
+ * default alignment) and then postprocessing the object file to
+ * reduce the alignment back down to the "real" value.
+ *
+ */
+#undef __table_alignment
+#define __table_alignment( table ) \
+ ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
+
+/*
+ * Because of the alignment hack, we must ensure that the compiler
+ * never tries to place multiple objects within the same section,
+ * otherwise the assembler will insert padding to the (incorrect)
+ * alignment boundary. Do this by appending the line number to table
+ * section names.
+ *
+ * Note that we don't need to worry about padding between array
+ * elements, since the alignment is declared on the variable (i.e. the
+ * whole array) rather than on the type (i.e. on all individual array
+ * elements).
+ */
+#undef __table_section
+#define __table_section( table, idx ) \
+ ".tbl." __table_name ( table ) "." __table_str ( idx ) \
+ "." __table_xstr ( __LINE__ )
+#define __table_xstr( x ) __table_str ( x )
+
+#endif /* __ICC */
+
+#endif /* _GPXE_TABLES_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/tcp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tcp.h
new file mode 100644
index 0000000..7ae7eab
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tcp.h
@@ -0,0 +1,318 @@
+#ifndef _GPXE_TCP_H
+#define _GPXE_TCP_H
+
+/** @file
+ *
+ * TCP protocol
+ *
+ * This file defines the gPXE TCP API.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/tcpip.h>
+
+/**
+ * A TCP header
+ */
+struct tcp_header {
+ uint16_t src; /* Source port */
+ uint16_t dest; /* Destination port */
+ uint32_t seq; /* Sequence number */
+ uint32_t ack; /* Acknowledgement number */
+ uint8_t hlen; /* Header length (4), Reserved (4) */
+ uint8_t flags; /* Reserved (2), Flags (6) */
+ uint16_t win; /* Advertised window */
+ uint16_t csum; /* Checksum */
+ uint16_t urg; /* Urgent pointer */
+};
+
+/** @defgroup tcpopts TCP options
+ * @{
+ */
+
+/** End of TCP options list */
+#define TCP_OPTION_END 0
+
+/** TCP option pad */
+#define TCP_OPTION_NOP 1
+
+/** Generic TCP option */
+struct tcp_option {
+ uint8_t kind;
+ uint8_t length;
+} __attribute__ (( packed ));
+
+/** TCP MSS option */
+struct tcp_mss_option {
+ uint8_t kind;
+ uint8_t length;
+ uint16_t mss;
+} __attribute__ (( packed ));
+
+/** Code for the TCP MSS option */
+#define TCP_OPTION_MSS 2
+
+/** TCP timestamp option */
+struct tcp_timestamp_option {
+ uint8_t kind;
+ uint8_t length;
+ uint32_t tsval;
+ uint32_t tsecr;
+} __attribute__ (( packed ));
+
+/** Padded TCP timestamp option (used for sending) */
+struct tcp_timestamp_padded_option {
+ uint8_t nop[2];
+ struct tcp_timestamp_option tsopt;
+} __attribute__ (( packed ));
+
+/** Code for the TCP timestamp option */
+#define TCP_OPTION_TS 8
+
+/** Parsed TCP options */
+struct tcp_options {
+ /** MSS option, if present */
+ const struct tcp_mss_option *mssopt;
+ /** Timestampe option, if present */
+ const struct tcp_timestamp_option *tsopt;
+};
+
+/** @} */
+
+/*
+ * TCP flags
+ */
+#define TCP_CWR 0x80
+#define TCP_ECE 0x40
+#define TCP_URG 0x20
+#define TCP_ACK 0x10
+#define TCP_PSH 0x08
+#define TCP_RST 0x04
+#define TCP_SYN 0x02
+#define TCP_FIN 0x01
+
+/**
+* @defgroup tcpstates TCP states
+*
+* The TCP state is defined by a combination of the flags that have
+* been sent to the peer, the flags that have been acknowledged by the
+* peer, and the flags that have been received from the peer.
+*
+* @{
+*/
+
+/** TCP flags that have been sent in outgoing packets */
+#define TCP_STATE_SENT(flags) ( (flags) << 0 )
+#define TCP_FLAGS_SENT(state) ( ( (state) >> 0 ) & 0xff )
+
+/** TCP flags that have been acknowledged by the peer
+ *
+ * Note that this applies only to SYN and FIN.
+ */
+#define TCP_STATE_ACKED(flags) ( (flags) << 8 )
+#define TCP_FLAGS_ACKED(state) ( ( (state) >> 8 ) & 0xff )
+
+/** TCP flags that have been received from the peer
+ *
+ * Note that this applies only to SYN and FIN, and that once SYN has
+ * been received, we should always be sending ACK.
+ */
+#define TCP_STATE_RCVD(flags) ( (flags) << 16 )
+#define TCP_FLAGS_RCVD(state) ( ( (state) >> 16 ) & 0xff )
+
+/** TCP flags that are currently being sent in outgoing packets */
+#define TCP_FLAGS_SENDING(state) \
+ ( TCP_FLAGS_SENT ( state ) & ~TCP_FLAGS_ACKED ( state ) )
+
+/** CLOSED
+ *
+ * The connection has not yet been used for anything.
+ */
+#define TCP_CLOSED TCP_RST
+
+/** LISTEN
+ *
+ * Not currently used as a state; we have no support for listening
+ * connections. Given a unique value to avoid compiler warnings.
+ */
+#define TCP_LISTEN 0
+
+/** SYN_SENT
+ *
+ * SYN has been sent, nothing has yet been received or acknowledged.
+ */
+#define TCP_SYN_SENT ( TCP_STATE_SENT ( TCP_SYN ) )
+
+/** SYN_RCVD
+ *
+ * SYN has been sent but not acknowledged, SYN has been received.
+ */
+#define TCP_SYN_RCVD ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** ESTABLISHED
+ *
+ * SYN has been sent and acknowledged, SYN has been received.
+ */
+#define TCP_ESTABLISHED ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** FIN_WAIT_1
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent but not acknowledged, FIN has not been received.
+ *
+ * RFC 793 shows that we can enter FIN_WAIT_1 without have had SYN
+ * acknowledged, i.e. if the application closes the connection after
+ * sending and receiving SYN, but before having had SYN acknowledged.
+ * However, we have to *pretend* that SYN has been acknowledged
+ * anyway, otherwise we end up sending SYN and FIN in the same
+ * sequence number slot. Therefore, when we transition from SYN_RCVD
+ * to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN)
+ * and increment our sequence number.
+ */
+#define TCP_FIN_WAIT_1 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** FIN_WAIT_2
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent and acknowledged, FIN ha not been received.
+ */
+#define TCP_FIN_WAIT_2 ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) )
+
+/** CLOSING / LAST_ACK
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent but not acknowledged, FIN has been received.
+ *
+ * This state actually encompasses both CLOSING and LAST_ACK; they are
+ * identical with the definition of state that we use. I don't
+ * *believe* that they need to be distinguished.
+ */
+#define TCP_CLOSING_OR_LAST_ACK \
+ ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** TIME_WAIT
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been sent and acknowledged, FIN has been received.
+ */
+#define TCP_TIME_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) | \
+ TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** CLOSE_WAIT
+ *
+ * SYN has been sent and acknowledged, SYN has been received, FIN has
+ * been received.
+ */
+#define TCP_CLOSE_WAIT ( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) | \
+ TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
+
+/** Can send data in current state
+ *
+ * We can send data if and only if we have had our SYN acked and we
+ * have not yet sent our FIN.
+ */
+#define TCP_CAN_SEND_DATA(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_SENT ( TCP_FIN ) ) ) \
+ == TCP_STATE_ACKED ( TCP_SYN ) )
+
+/** Have ever been fully established
+ *
+ * We have been fully established if we have both received a SYN and
+ * had our own SYN acked.
+ */
+#define TCP_HAS_BEEN_ESTABLISHED(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) | \
+ TCP_STATE_RCVD ( TCP_SYN ) ) ) \
+ == ( TCP_STATE_ACKED ( TCP_SYN ) | TCP_STATE_RCVD ( TCP_SYN ) ) )
+
+/** Have closed gracefully
+ *
+ * We have closed gracefully if we have both received a FIN and had
+ * our own FIN acked.
+ */
+#define TCP_CLOSED_GRACEFULLY(state) \
+ ( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) | \
+ TCP_STATE_RCVD ( TCP_FIN ) ) ) \
+ == ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) )
+
+/** @} */
+
+/** Mask for TCP header length field */
+#define TCP_MASK_HLEN 0xf0
+
+/** Smallest port number on which a TCP connection can listen */
+#define TCP_MIN_PORT 1
+
+/* Some IOB constants */
+#define MAX_HDR_LEN 100
+#define MAX_IOB_LEN 1500
+#define MIN_IOB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
+
+/**
+ * Maxmimum advertised TCP window size
+ *
+ * We estimate the TCP window size as the amount of free memory we
+ * have. This is not strictly accurate (since it ignores any space
+ * already allocated as RX buffers), but it will do for now.
+ *
+ * Since we don't store out-of-order received packets, the
+ * retransmission penalty is that the whole window contents must be
+ * resent. This suggests keeping the window size small, but bear in
+ * mind that the maximum bandwidth on any link is limited to
+ *
+ * max_bandwidth = ( tcp_window / round_trip_time )
+ *
+ * With a 48kB window, which probably accurately reflects our amount
+ * of free memory, and a WAN RTT of say 200ms, this gives a maximum
+ * bandwidth of 240kB/s. This is sufficiently close to realistic that
+ * we will need to be careful that our advertised window doesn't end
+ * up limiting WAN download speeds.
+ *
+ * Finally, since the window goes into a 16-bit field and we cannot
+ * actually use 65536, we use a window size of (65536-4) to ensure
+ * that payloads remain dword-aligned.
+ */
+//#define TCP_MAX_WINDOW_SIZE ( 65536 - 4 )
+#define TCP_MAX_WINDOW_SIZE 4096
+
+/**
+ * Path MTU
+ *
+ * We really ought to implement Path MTU discovery. Until we do,
+ * anything with a path MTU greater than this may fail.
+ */
+#define TCP_PATH_MTU 1460
+
+/**
+ * Advertised TCP MSS
+ *
+ * We currently hardcode this to a reasonable value and hope that the
+ * sender uses path MTU discovery. The alternative is breaking the
+ * abstraction layer so that we can find out the MTU from the IP layer
+ * (which would have to find out from the net device layer).
+ */
+#define TCP_MSS 1460
+
+/** TCP maximum segment lifetime
+ *
+ * Currently set to 2 minutes, as per RFC 793.
+ */
+#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )
+
+extern struct tcpip_protocol tcp_protocol;
+
+#endif /* _GPXE_TCP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/tcpip.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tcpip.h
new file mode 100644
index 0000000..f71d7d6
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tcpip.h
@@ -0,0 +1,128 @@
+#ifndef _GPXE_TCPIP_H
+#define _GPXE_TCPIP_H
+
+/** @file
+ *
+ * Transport-network layer interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/socket.h>
+#include <gpxe/in.h>
+#include <gpxe/tables.h>
+
+struct io_buffer;
+struct net_device;
+
+/** Empty checksum value
+ *
+ * This is the TCP/IP checksum over a zero-length block of data.
+ */
+#define TCPIP_EMPTY_CSUM 0xffff
+
+/**
+ * TCP/IP socket address
+ *
+ * This contains the fields common to socket addresses for all TCP/IP
+ * address families.
+ */
+struct sockaddr_tcpip {
+ /** Socket address family (part of struct @c sockaddr) */
+ sa_family_t st_family;
+ /** TCP/IP port */
+ uint16_t st_port;
+ /** Padding
+ *
+ * This ensures that a struct @c sockaddr_tcpip is large
+ * enough to hold a socket address for any TCP/IP address
+ * family.
+ */
+ char pad[ sizeof ( struct sockaddr ) -
+ ( sizeof ( sa_family_t ) + sizeof ( uint16_t ) ) ];
+} __attribute__ (( may_alias ));
+
+/**
+ * A transport-layer protocol of the TCP/IP stack (eg. UDP, TCP, etc)
+ */
+struct tcpip_protocol {
+ /** Protocol name */
+ const char *name;
+ /**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ *
+ * This method takes ownership of the I/O buffer.
+ */
+ int ( * rx ) ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
+ /**
+ * Transport-layer protocol number
+ *
+ * This is a constant of the type IP_XXX
+ */
+ uint8_t tcpip_proto;
+};
+
+/**
+ * A network-layer protocol of the TCP/IP stack (eg. IPV4, IPv6, etc)
+ */
+struct tcpip_net_protocol {
+ /** Protocol name */
+ const char *name;
+ /** Network address family */
+ sa_family_t sa_family;
+ /**
+ * Transmit packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_protocol Transport-layer protocol
+ * @v st_src Source address, or NULL to use default
+ * @v st_dest Destination address
+ * @v netdev Network device (or NULL to route automatically)
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Return status code
+ *
+ * This function takes ownership of the I/O buffer.
+ */
+ int ( * tx ) ( struct io_buffer *iobuf,
+ struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum );
+};
+
+/** TCP/IP transport-layer protocol table */
+#define TCPIP_PROTOCOLS __table ( struct tcpip_protocol, "tcpip_protocols" )
+
+/** Declare a TCP/IP transport-layer protocol */
+#define __tcpip_protocol __table_entry ( TCPIP_PROTOCOLS, 01 )
+
+/** TCP/IP network-layer protocol table */
+#define TCPIP_NET_PROTOCOLS \
+ __table ( struct tcpip_net_protocol, "tcpip_net_protocols" )
+
+/** Declare a TCP/IP network-layer protocol */
+#define __tcpip_net_protocol __table_entry ( TCPIP_NET_PROTOCOLS, 01 )
+
+extern int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
+extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum );
+extern uint16_t tcpip_continue_chksum ( uint16_t partial,
+ const void *data, size_t len );
+extern uint16_t tcpip_chksum ( const void *data, size_t len );
+
+#endif /* _GPXE_TCPIP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/tftp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tftp.h
new file mode 100644
index 0000000..c57bb25
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tftp.h
@@ -0,0 +1,85 @@
+#ifndef _GPXE_TFTP_H
+#define _GPXE_TFTP_H
+
+/** @file
+ *
+ * TFTP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+#define TFTP_PORT 69 /**< Default TFTP server port */
+#define TFTP_DEFAULT_BLKSIZE 512 /**< Default TFTP data block size */
+#define TFTP_MAX_BLKSIZE 1432
+
+#define TFTP_RRQ 1 /**< Read request opcode */
+#define TFTP_WRQ 2 /**< Write request opcode */
+#define TFTP_DATA 3 /**< Data block opcode */
+#define TFTP_ACK 4 /**< Data block acknowledgement opcode */
+#define TFTP_ERROR 5 /**< Error opcode */
+#define TFTP_OACK 6 /**< Options acknowledgement opcode */
+
+#define TFTP_ERR_FILE_NOT_FOUND 1 /**< File not found */
+#define TFTP_ERR_ACCESS_DENIED 2 /**< Access violation */
+#define TFTP_ERR_DISK_FULL 3 /**< Disk full or allocation exceeded */
+#define TFTP_ERR_ILLEGAL_OP 4 /**< Illegal TFTP operation */
+#define TFTP_ERR_UNKNOWN_TID 5 /**< Unknown transfer ID */
+#define TFTP_ERR_FILE_EXISTS 6 /**< File already exists */
+#define TFTP_ERR_UNKNOWN_USER 7 /**< No such user */
+#define TFTP_ERR_BAD_OPTS 8 /**< Option negotiation failed */
+
+#define MTFTP_PORT 1759 /**< Default MTFTP server port */
+
+/** A TFTP read request (RRQ) packet */
+struct tftp_rrq {
+ uint16_t opcode;
+ char data[0];
+} __attribute__ (( packed ));
+
+/** A TFTP data (DATA) packet */
+struct tftp_data {
+ uint16_t opcode;
+ uint16_t block;
+ uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** A TFTP acknowledgement (ACK) packet */
+struct tftp_ack {
+ uint16_t opcode;
+ uint16_t block;
+} __attribute__ (( packed ));
+
+/** A TFTP error (ERROR) packet */
+struct tftp_error {
+ uint16_t opcode;
+ uint16_t errcode;
+ char errmsg[0];
+} __attribute__ (( packed ));
+
+/** A TFTP options acknowledgement (OACK) packet */
+struct tftp_oack {
+ uint16_t opcode;
+ char data[0];
+} __attribute__ (( packed ));
+
+/** The common header of all TFTP packets */
+struct tftp_common {
+ uint16_t opcode;
+} __attribute__ (( packed ));
+
+/** A union encapsulating all TFTP packet types */
+union tftp_any {
+ struct tftp_common common;
+ struct tftp_rrq rrq;
+ struct tftp_data data;
+ struct tftp_ack ack;
+ struct tftp_error error;
+ struct tftp_oack oack;
+};
+
+extern void tftp_set_request_blksize ( unsigned int blksize );
+
+#endif /* _GPXE_TFTP_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/threewire.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/threewire.h
new file mode 100644
index 0000000..e23284a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/threewire.h
@@ -0,0 +1,105 @@
+#ifndef _GPXE_THREEWIRE_H
+#define _GPXE_THREEWIRE_H
+
+/** @file
+ *
+ * Three-wire serial interface
+ *
+ * The Atmel three-wire interface is a subset of the (newer) SPI
+ * interface, and is implemented here as a layer on top of the SPI
+ * support.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/spi.h>
+#include <limits.h>
+
+/**
+ * @defgroup tcmds Three-wire commands
+ * @{
+ */
+
+/** Read data from memory array */
+#define THREEWIRE_READ 0x6
+
+/** Write data to memory array */
+#define THREEWIRE_WRITE 0x5
+
+/** Write enable */
+#define THREEWIRE_EWEN 0x4
+
+/** Address to be used for write enable command */
+#define THREEWIRE_EWEN_ADDRESS INT_MAX
+
+/** Time to wait for write cycles to complete
+ *
+ * This is sufficient for AT93C46/AT93C56 devices, but may need to be
+ * increased in future when other devices are added.
+ */
+#define THREEWIRE_WRITE_MDELAY 10
+
+/** @} */
+
+extern int threewire_read ( struct nvs_device *nvs, unsigned int address,
+ void *data, size_t len );
+extern int threewire_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t len );
+extern int threewire_detect_address_len ( struct spi_device *device );
+
+/**
+ * @defgroup tdevs Three-wire device types
+ * @{
+ */
+
+static inline __attribute__ (( always_inline )) void
+init_at93cx6 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.word_len_log2 = ( ( organisation == 8 ) ? 0 : 1 );
+ device->nvs.block_size = 1;
+ device->command_len = 3,
+ device->nvs.read = threewire_read;
+ device->nvs.write = threewire_write;
+}
+
+/**
+ * Initialise Atmel AT93C46 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c46 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 1024 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 7 : 6 );
+ init_at93cx6 ( device, organisation );
+}
+
+/**
+ * Initialise Atmel AT93C56 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c56 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 2048 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 9 : 8 );
+ init_at93cx6 ( device, organisation );
+}
+
+/**
+ * Initialise Atmel AT93C66 serial EEPROM
+ *
+ * @v device SPI device
+ * @v organisation Word organisation (8 or 16)
+ */
+static inline __attribute__ (( always_inline )) void
+init_at93c66 ( struct spi_device *device, unsigned int organisation ) {
+ device->nvs.size = ( 4096 / organisation );
+ device->address_len = ( ( organisation == 8 ) ? 9 : 8 );
+ init_at93cx6 ( device, organisation );
+}
+
+/** @} */
+
+#endif /* _GPXE_THREEWIRE_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/tls.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tls.h
new file mode 100644
index 0000000..e2da046
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/tls.h
@@ -0,0 +1,187 @@
+#ifndef _GPXE_TLS_H
+#define _GPXE_TLS_H
+
+/**
+ * @file
+ *
+ * Transport Layer Security Protocol
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/filter.h>
+#include <gpxe/process.h>
+#include <gpxe/crypto.h>
+#include <gpxe/md5.h>
+#include <gpxe/sha1.h>
+#include <gpxe/x509.h>
+
+/** A TLS header */
+struct tls_header {
+ /** Content type
+ *
+ * This is a TLS_TYPE_XXX constant
+ */
+ uint8_t type;
+ /** Protocol version
+ *
+ * This is a TLS_VERSION_XXX constant
+ */
+ uint16_t version;
+ /** Length of payload */
+ uint16_t length;
+} __attribute__ (( packed ));
+
+/** TLS version 1.0 */
+#define TLS_VERSION_TLS_1_0 0x0301
+
+/** TLS version 1.1 */
+#define TLS_VERSION_TLS_1_1 0x0302
+
+/** Change cipher content type */
+#define TLS_TYPE_CHANGE_CIPHER 20
+
+/** Alert content type */
+#define TLS_TYPE_ALERT 21
+
+/** Handshake content type */
+#define TLS_TYPE_HANDSHAKE 22
+
+/** Application data content type */
+#define TLS_TYPE_DATA 23
+
+/* Handshake message types */
+#define TLS_HELLO_REQUEST 0
+#define TLS_CLIENT_HELLO 1
+#define TLS_SERVER_HELLO 2
+#define TLS_CERTIFICATE 11
+#define TLS_SERVER_KEY_EXCHANGE 12
+#define TLS_CERTIFICATE_REQUEST 13
+#define TLS_SERVER_HELLO_DONE 14
+#define TLS_CERTIFICATE_VERIFY 15
+#define TLS_CLIENT_KEY_EXCHANGE 16
+#define TLS_FINISHED 20
+
+/* TLS alert levels */
+#define TLS_ALERT_WARNING 1
+#define TLS_ALERT_FATAL 2
+
+/* TLS cipher specifications */
+#define TLS_RSA_WITH_NULL_MD5 0x0001
+#define TLS_RSA_WITH_NULL_SHA 0x0002
+#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002f
+#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
+
+/** TLS RX state machine state */
+enum tls_rx_state {
+ TLS_RX_HEADER = 0,
+ TLS_RX_DATA,
+};
+
+/** TLS TX state machine state */
+enum tls_tx_state {
+ TLS_TX_NONE = 0,
+ TLS_TX_CLIENT_HELLO,
+ TLS_TX_CLIENT_KEY_EXCHANGE,
+ TLS_TX_CHANGE_CIPHER,
+ TLS_TX_FINISHED,
+ TLS_TX_DATA
+};
+
+/** A TLS cipher specification */
+struct tls_cipherspec {
+ /** Public-key encryption algorithm */
+ struct pubkey_algorithm *pubkey;
+ /** Bulk encryption cipher algorithm */
+ struct cipher_algorithm *cipher;
+ /** MAC digest algorithm */
+ struct digest_algorithm *digest;
+ /** Key length */
+ size_t key_len;
+ /** Dynamically-allocated storage */
+ void *dynamic;
+ /** Public key encryption context */
+ void *pubkey_ctx;
+ /** Bulk encryption cipher context */
+ void *cipher_ctx;
+ /** Next bulk encryption cipher context (TX only) */
+ void *cipher_next_ctx;
+ /** MAC secret */
+ void *mac_secret;
+};
+
+/** TLS pre-master secret */
+struct tls_pre_master_secret {
+ /** TLS version */
+ uint16_t version;
+ /** Random data */
+ uint8_t random[46];
+} __attribute__ (( packed ));
+
+/** TLS client random data */
+struct tls_client_random {
+ /** GMT Unix time */
+ uint32_t gmt_unix_time;
+ /** Random data */
+ uint8_t random[28];
+} __attribute__ (( packed ));
+
+/** A TLS session */
+struct tls_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Plaintext stream */
+ struct xfer_filter_half plainstream;
+ /** Ciphertext stream */
+ struct xfer_filter_half cipherstream;
+
+ /** Current TX cipher specification */
+ struct tls_cipherspec tx_cipherspec;
+ /** Next TX cipher specification */
+ struct tls_cipherspec tx_cipherspec_pending;
+ /** Current RX cipher specification */
+ struct tls_cipherspec rx_cipherspec;
+ /** Next RX cipher specification */
+ struct tls_cipherspec rx_cipherspec_pending;
+ /** Premaster secret */
+ struct tls_pre_master_secret pre_master_secret;
+ /** Master secret */
+ uint8_t master_secret[48];
+ /** Server random bytes */
+ uint8_t server_random[32];
+ /** Client random bytes */
+ struct tls_client_random client_random;
+ /** MD5 context for handshake verification */
+ uint8_t handshake_md5_ctx[MD5_CTX_SIZE];
+ /** SHA1 context for handshake verification */
+ uint8_t handshake_sha1_ctx[SHA1_CTX_SIZE];
+
+ /** Hack: server RSA public key */
+ struct x509_rsa_public_key rsa;
+
+ /** TX sequence number */
+ uint64_t tx_seq;
+ /** TX state */
+ enum tls_tx_state tx_state;
+ /** TX process */
+ struct process process;
+
+ /** RX sequence number */
+ uint64_t rx_seq;
+ /** RX state */
+ enum tls_rx_state rx_state;
+ /** Offset within current RX state */
+ size_t rx_rcvd;
+ /** Current received record header */
+ struct tls_header rx_header;
+ /** Current received raw data buffer */
+ void *rx_data;
+};
+
+extern int add_tls ( struct xfer_interface *xfer,
+ struct xfer_interface **next );
+
+#endif /* _GPXE_TLS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/uaccess.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/uaccess.h
new file mode 100644
index 0000000..5a8f292
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/uaccess.h
@@ -0,0 +1,344 @@
+#ifndef _GPXE_UACCESS_H
+#define _GPXE_UACCESS_H
+
+/**
+ * @file
+ *
+ * Access to external ("user") memory
+ *
+ * gPXE often needs to transfer data between internal and external
+ * buffers. On i386, the external buffers may require access via a
+ * different segment, and the buffer address cannot be encoded into a
+ * simple void * pointer. The @c userptr_t type encapsulates the
+ * information needed to identify an external buffer, and the
+ * copy_to_user() and copy_from_user() functions provide methods for
+ * transferring data between internal and external buffers.
+ *
+ * Note that userptr_t is an opaque type; in particular, performing
+ * arithmetic upon a userptr_t is not allowed.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <gpxe/api.h>
+#include <config/ioapi.h>
+
+/**
+ * A pointer to a user buffer
+ *
+ */
+typedef unsigned long userptr_t;
+
+/** Equivalent of NULL for user pointers */
+#define UNULL ( ( userptr_t ) 0 )
+
+/**
+ * @defgroup uaccess_trivial Trivial user access API implementations
+ *
+ * User access API implementations that can be used by environments in
+ * which virtual addresses allow access to all of memory.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Convert virtual address to user pointer
+ *
+ * @v addr Virtual address
+ * @ret userptr User pointer
+ */
+static inline __always_inline userptr_t
+trivial_virt_to_user ( volatile const void *addr ) {
+ return ( ( userptr_t ) addr );
+}
+
+/**
+ * Convert user pointer to virtual address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret addr Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void *
+trivial_user_to_virt ( userptr_t userptr, off_t offset ) {
+ return ( ( void * ) userptr + offset );
+}
+
+/**
+ * Add offset to user pointer
+ *
+ * @v userptr User pointer
+ * @v offset Offset
+ * @ret userptr New pointer value
+ */
+static inline __always_inline userptr_t
+trivial_userptr_add ( userptr_t userptr, off_t offset ) {
+ return ( userptr + offset );
+}
+
+/**
+ * Copy data between user buffers
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+trivial_memcpy_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len ) {
+ memcpy ( ( ( void * ) dest + dest_off ),
+ ( ( void * ) src + src_off ), len );
+}
+
+/**
+ * Copy data between user buffers, allowing for overlap
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+trivial_memmove_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len ) {
+ memmove ( ( ( void * ) dest + dest_off ),
+ ( ( void * ) src + src_off ), len );
+}
+
+/**
+ * Fill user buffer with a constant byte
+ *
+ * @v buffer User buffer
+ * @v offset Offset within buffer
+ * @v c Constant byte with which to fill
+ * @v len Length
+ */
+static inline __always_inline void
+trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+ memset ( ( ( void * ) buffer + offset ), c, len );
+}
+
+/**
+ * Find length of NUL-terminated string in user buffer
+ *
+ * @v buffer User buffer
+ * @v offset Offset within buffer
+ * @ret len Length of string (excluding NUL)
+ */
+static inline __always_inline size_t
+trivial_strlen_user ( userptr_t buffer, off_t offset ) {
+ return strlen ( ( void * ) buffer + offset );
+}
+
+/**
+ * Find character in user buffer
+ *
+ * @v buffer User buffer
+ * @v offset Starting offset within buffer
+ * @v c Character to search for
+ * @v len Length of user buffer
+ * @ret offset Offset of character, or <0 if not found
+ */
+static inline __always_inline off_t
+trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+ void *found;
+
+ found = memchr ( ( ( void * ) buffer + offset ), c, len );
+ return ( found ? ( found - ( void * ) buffer ) : -1 );
+}
+
+/** @} */
+
+/**
+ * Calculate static inline user access API function name
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @ret _subsys_func Subsystem API function
+ */
+#define UACCESS_INLINE( _subsys, _api_func ) \
+ SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide an user access API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline user access API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ */
+#define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
+ PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent user access API headers */
+#include <gpxe/efi/efi_uaccess.h>
+
+/* Include all architecture-dependent user access API headers */
+#include <bits/uaccess.h>
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr Physical address
+ * @ret userptr User pointer
+ */
+userptr_t phys_to_user ( unsigned long phys_addr );
+
+/**
+ * Convert user pointer to physical address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret phys_addr Physical address
+ */
+unsigned long user_to_phys ( userptr_t userptr, off_t offset );
+
+/**
+ * Convert virtual address to user pointer
+ *
+ * @v addr Virtual address
+ * @ret userptr User pointer
+ */
+userptr_t virt_to_user ( volatile const void *addr );
+
+/**
+ * Convert user pointer to virtual address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret addr Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+void * user_to_virt ( userptr_t userptr, off_t offset );
+
+/**
+ * Add offset to user pointer
+ *
+ * @v userptr User pointer
+ * @v offset Offset
+ * @ret userptr New pointer value
+ */
+userptr_t userptr_add ( userptr_t userptr, off_t offset );
+
+/**
+ * Convert virtual address to a physical address
+ *
+ * @v addr Virtual address
+ * @ret phys_addr Physical address
+ */
+static inline __always_inline unsigned long
+virt_to_phys ( volatile const void *addr ) {
+ return user_to_phys ( virt_to_user ( addr ), 0 );
+}
+
+/**
+ * Convert physical address to a virtual address
+ *
+ * @v addr Virtual address
+ * @ret phys_addr Physical address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
+ return user_to_virt ( phys_to_user ( phys_addr ), 0 );
+}
+
+/**
+ * Copy data between user buffers
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+void memcpy_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len );
+
+/**
+ * Copy data to user buffer
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v len Length
+ */
+static inline __always_inline void
+copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
+ memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
+}
+
+/**
+ * Copy data from user buffer
+ *
+ * @v dest Destination
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
+ memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
+}
+
+/**
+ * Copy data between user buffers, allowing for overlap
+ *
+ * @v dest Destination
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v src_off Source offset
+ * @v len Length
+ */
+void memmove_user ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len );
+
+/**
+ * Fill user buffer with a constant byte
+ *
+ * @v userptr User buffer
+ * @v offset Offset within buffer
+ * @v c Constant byte with which to fill
+ * @v len Length
+ */
+void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
+
+/**
+ * Find length of NUL-terminated string in user buffer
+ *
+ * @v userptr User buffer
+ * @v offset Offset within buffer
+ * @ret len Length of string (excluding NUL)
+ */
+size_t strlen_user ( userptr_t userptr, off_t offset );
+
+/**
+ * Find character in user buffer
+ *
+ * @v userptr User buffer
+ * @v offset Starting offset within buffer
+ * @v c Character to search for
+ * @v len Length of user buffer
+ * @ret offset Offset of character, or <0 if not found
+ */
+off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
+
+#endif /* _GPXE_UACCESS_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/udp.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/udp.h
new file mode 100644
index 0000000..670c5e5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/udp.h
@@ -0,0 +1,48 @@
+#ifndef _GPXE_UDP_H
+#define _GPXE_UDP_H
+
+/** @file
+ *
+ * UDP protocol
+ *
+ * This file defines the gPXE UDP API.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/if_ether.h>
+
+struct xfer_interface;
+
+/**
+ * UDP constants
+ */
+
+#define UDP_MAX_HLEN 72
+#define UDP_MAX_TXIOB ETH_MAX_MTU
+#define UDP_MIN_TXIOB ETH_ZLEN
+
+/**
+ * A UDP header
+ */
+struct udp_header {
+ /** Source port */
+ uint16_t src;
+ /** Destination port */
+ uint16_t dest;
+ /** Length */
+ uint16_t len;
+ /** Checksum */
+ uint16_t chksum;
+};
+
+extern int udp_open_promisc ( struct xfer_interface *xfer );
+extern int udp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local );
+
+#endif /* _GPXE_UDP_H */
+
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/umalloc.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/umalloc.h
new file mode 100644
index 0000000..b0e5564
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/umalloc.h
@@ -0,0 +1,68 @@
+#ifndef _GPXE_UMALLOC_H
+#define _GPXE_UMALLOC_H
+
+/**
+ * @file
+ *
+ * User memory allocation
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/api.h>
+#include <config/umalloc.h>
+#include <gpxe/uaccess.h>
+
+/**
+ * Provide a user memory allocation API implementation
+ *
+ * @v _prefix Subsystem prefix
+ * @v _api_func API function
+ * @v _func Implementing function
+ */
+#define PROVIDE_UMALLOC( _subsys, _api_func, _func ) \
+ PROVIDE_SINGLE_API ( UMALLOC_PREFIX_ ## _subsys, _api_func, _func )
+
+/* Include all architecture-independent I/O API headers */
+#include <gpxe/efi/efi_umalloc.h>
+
+/* Include all architecture-dependent I/O API headers */
+#include <bits/umalloc.h>
+
+/**
+ * Reallocate external memory
+ *
+ * @v userptr Memory previously allocated by umalloc(), or UNULL
+ * @v new_size Requested size
+ * @ret userptr Allocated memory, or UNULL
+ *
+ * Calling realloc() with a new size of zero is a valid way to free a
+ * memory block.
+ */
+userptr_t urealloc ( userptr_t userptr, size_t new_size );
+
+/**
+ * Allocate external memory
+ *
+ * @v size Requested size
+ * @ret userptr Memory, or UNULL
+ *
+ * Memory is guaranteed to be aligned to a page boundary.
+ */
+static inline __always_inline userptr_t umalloc ( size_t size ) {
+ return urealloc ( UNULL, size );
+}
+
+/**
+ * Free external memory
+ *
+ * @v userptr Memory allocated by umalloc(), or UNULL
+ *
+ * If @c ptr is UNULL, no action is taken.
+ */
+static inline __always_inline void ufree ( userptr_t userptr ) {
+ urealloc ( userptr, 0 );
+}
+
+#endif /* _GPXE_UMALLOC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/uri.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/uri.h
new file mode 100644
index 0000000..03c88d2
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/uri.h
@@ -0,0 +1,144 @@
+#ifndef _GPXE_URI_H
+#define _GPXE_URI_H
+
+/** @file
+ *
+ * Uniform Resource Identifiers
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <gpxe/refcnt.h>
+
+/** A Uniform Resource Identifier
+ *
+ * Terminology for this data structure is as per uri(7), except that
+ * "path" is defined to include the leading '/' for an absolute path.
+ *
+ * Note that all fields within a URI are optional and may be NULL.
+ *
+ * Some examples are probably helpful:
+ *
+ * http://www.etherboot.org/wiki :
+ *
+ * scheme = "http", host = "www.etherboot.org", path = "/wiki"
+ *
+ * /var/lib/tftpboot :
+ *
+ * path = "/var/lib/tftpboot"
+ *
+ * mailto:bob@nowhere.com :
+ *
+ * scheme = "mailto", opaque = "bob@nowhere.com"
+ *
+ * ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this
+ *
+ * scheme = "ftp", user = "joe", password = "secret",
+ * host = "insecure.org", port = "8081", path = "/hidden/path/to",
+ * query = "what=is", fragment = "this"
+ */
+struct uri {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Scheme */
+ const char *scheme;
+ /** Opaque part */
+ const char *opaque;
+ /** User name */
+ const char *user;
+ /** Password */
+ const char *password;
+ /** Host name */
+ const char *host;
+ /** Port number */
+ const char *port;
+ /** Path */
+ const char *path;
+ /** Query */
+ const char *query;
+ /** Fragment */
+ const char *fragment;
+};
+
+/**
+ * URI is an absolute URI
+ *
+ * @v uri URI
+ * @ret is_absolute URI is absolute
+ *
+ * An absolute URI begins with a scheme, e.g. "http:" or "mailto:".
+ * Note that this is a separate concept from a URI with an absolute
+ * path.
+ */
+static inline int uri_is_absolute ( struct uri *uri ) {
+ return ( uri->scheme != NULL );
+}
+
+/**
+ * URI has an absolute path
+ *
+ * @v uri URI
+ * @ret has_absolute_path URI has an absolute path
+ *
+ * An absolute path begins with a '/'. Note that this is a separate
+ * concept from an absolute URI. Note also that a URI may not have a
+ * path at all.
+ */
+static inline int uri_has_absolute_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] == '/' ) );
+}
+
+/**
+ * URI has a relative path
+ *
+ * @v uri URI
+ * @ret has_relative_path URI has a relative path
+ *
+ * A relative path begins with something other than a '/'. Note that
+ * this is a separate concept from a relative URI. Note also that a
+ * URI may not have a path at all.
+ */
+static inline int uri_has_relative_path ( struct uri *uri ) {
+ return ( uri->path && ( uri->path[0] != '/' ) );
+}
+
+/**
+ * Increment URI reference count
+ *
+ * @v uri URI, or NULL
+ * @ret uri URI as passed in
+ */
+static inline __attribute__ (( always_inline )) struct uri *
+uri_get ( struct uri *uri ) {
+ ref_get ( &uri->refcnt );
+ return uri;
+}
+
+/**
+ * Decrement URI reference count
+ *
+ * @v uri URI, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+uri_put ( struct uri *uri ) {
+ ref_put ( &uri->refcnt );
+}
+
+extern struct uri *cwuri;
+
+extern struct uri * parse_uri ( const char *uri_string );
+extern unsigned int uri_port ( struct uri *uri, unsigned int default_port );
+extern int unparse_uri ( char *buf, size_t size, struct uri *uri );
+extern struct uri * uri_dup ( struct uri *uri );
+extern char * resolve_path ( const char *base_path,
+ const char *relative_path );
+extern struct uri * resolve_uri ( struct uri *base_uri,
+ struct uri *relative_uri );
+extern void churi ( struct uri *uri );
+extern size_t uri_encode ( const char *raw_string, char *buf, size_t len );
+extern size_t uri_decode ( const char *encoded_string, char *buf, size_t len );
+
+#endif /* _GPXE_URI_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/uuid.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/uuid.h
new file mode 100644
index 0000000..019cd05
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/uuid.h
@@ -0,0 +1,33 @@
+#ifndef _GPXE_UUID_H
+#define _GPXE_UUID_H
+
+/** @file
+ *
+ * Universally unique IDs
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** A universally unique ID */
+union uuid {
+ /** Canonical form (00000000-0000-0000-0000-000000000000) */
+ struct {
+ /** 8 hex digits, big-endian */
+ uint32_t a;
+ /** 2 hex digits, big-endian */
+ uint16_t b;
+ /** 2 hex digits, big-endian */
+ uint16_t c;
+ /** 2 hex digits, big-endian */
+ uint16_t d;
+ /** 12 hex digits, big-endian */
+ uint8_t e[6];
+ } canonical;
+ uint8_t raw[16];
+};
+
+extern char * uuid_ntoa ( union uuid *uuid );
+
+#endif /* _GPXE_UUID_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/x509.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/x509.h
new file mode 100644
index 0000000..1b9d9aa
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/x509.h
@@ -0,0 +1,41 @@
+#ifndef _GPXE_X509_H
+#define _GPXE_X509_H
+
+/** @file
+ *
+ * X.509 certificates
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+struct asn1_cursor;
+
+/** An X.509 RSA public key */
+struct x509_rsa_public_key {
+ /** Modulus */
+ uint8_t *modulus;
+ /** Modulus length */
+ size_t modulus_len;
+ /** Exponent */
+ uint8_t *exponent;
+ /** Exponent length */
+ size_t exponent_len;
+};
+
+/**
+ * Free X.509 RSA public key
+ *
+ * @v rsa_pubkey RSA public key
+ */
+static inline void
+x509_free_rsa_public_key ( struct x509_rsa_public_key *rsa_pubkey ) {
+ free ( rsa_pubkey->modulus );
+}
+
+extern int x509_rsa_public_key ( const struct asn1_cursor *certificate,
+ struct x509_rsa_public_key *rsa_pubkey );
+
+#endif /* _GPXE_X509_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/gpxe/xfer.h b/debian/grub-extras/disabled/gpxe/src/include/gpxe/xfer.h
new file mode 100644
index 0000000..edd3703
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/gpxe/xfer.h
@@ -0,0 +1,277 @@
+#ifndef _GPXE_XFER_H
+#define _GPXE_XFER_H
+
+/** @file
+ *
+ * Data transfer interfaces
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <gpxe/interface.h>
+#include <gpxe/iobuf.h>
+
+struct xfer_interface;
+struct xfer_metadata;
+
+/** Data transfer interface operations */
+struct xfer_interface_operations {
+ /** Close interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+ void ( * close ) ( struct xfer_interface *xfer, int rc );
+ /** Redirect to new location
+ *
+ * @v xfer Data transfer interface
+ * @v type New location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+ int ( * vredirect ) ( struct xfer_interface *xfer, int type,
+ va_list args );
+ /** Check flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ *
+ * Flow control is regarded as advisory but not mandatory.
+ * Users who have control over their own rate of data
+ * generation should perform a flow control check before
+ * generating new data. Users who have no control (such as
+ * NIC drivers or filter layers) are not obliged to check.
+ *
+ * Data transfer interfaces must be prepared to accept
+ * datagrams even if they are advertising a window of zero
+ * bytes.
+ */
+ size_t ( * window ) ( struct xfer_interface *xfer );
+ /** Allocate I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v len I/O buffer payload length
+ * @ret iobuf I/O buffer
+ */
+ struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer,
+ size_t len );
+ /** Deliver datagram as I/O buffer with metadata
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ *
+ * A data transfer interface that wishes to support only raw
+ * data delivery should set this method to
+ * xfer_deliver_as_raw().
+ */
+ int ( * deliver_iob ) ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+ /** Deliver datagram as raw data
+ *
+ * @v xfer Data transfer interface
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ *
+ * A data transfer interface that wishes to support only I/O
+ * buffer delivery should set this method to
+ * xfer_deliver_as_iob().
+ */
+ int ( * deliver_raw ) ( struct xfer_interface *xfer,
+ const void *data, size_t len );
+};
+
+/** A data transfer interface */
+struct xfer_interface {
+ /** Generic object communication interface */
+ struct interface intf;
+ /** Operations for received messages */
+ struct xfer_interface_operations *op;
+};
+
+/** Basis positions for seek() events */
+enum seek_whence {
+ SEEK_CUR = 0,
+ SEEK_SET,
+};
+
+/** Data transfer metadata */
+struct xfer_metadata {
+ /** Position of data within stream */
+ off_t offset;
+ /** Basis for data position
+ *
+ * Must be one of @c SEEK_CUR or @c SEEK_SET.
+ */
+ int whence;
+ /** Source socket address, or NULL */
+ struct sockaddr *src;
+ /** Destination socket address, or NULL */
+ struct sockaddr *dest;
+ /** Network device, or NULL */
+ struct net_device *netdev;
+};
+
+/**
+ * Describe seek basis
+ *
+ * @v whence Basis for new position
+ */
+static inline __attribute__ (( always_inline )) const char *
+whence_text ( int whence ) {
+ switch ( whence ) {
+ case SEEK_CUR: return "CUR";
+ case SEEK_SET: return "SET";
+ default: return "INVALID";
+ }
+}
+
+extern struct xfer_interface null_xfer;
+extern struct xfer_interface_operations null_xfer_ops;
+
+extern void xfer_close ( struct xfer_interface *xfer, int rc );
+extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
+ va_list args );
+extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
+extern size_t xfer_window ( struct xfer_interface *xfer );
+extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer,
+ size_t len );
+extern int xfer_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf );
+extern int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+extern int xfer_deliver_raw ( struct xfer_interface *xfer,
+ const void *data, size_t len );
+extern int xfer_vprintf ( struct xfer_interface *xfer,
+ const char *format, va_list args );
+extern int __attribute__ (( format ( printf, 2, 3 ) ))
+xfer_printf ( struct xfer_interface *xfer, const char *format, ... );
+extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
+
+extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
+extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,
+ int type, va_list args );
+extern size_t unlimited_xfer_window ( struct xfer_interface *xfer );
+extern size_t no_xfer_window ( struct xfer_interface *xfer );
+extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer,
+ size_t len );
+extern int xfer_deliver_as_raw ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta );
+extern int xfer_deliver_as_iob ( struct xfer_interface *xfer,
+ const void *data, size_t len );
+extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
+ const void *data __unused, size_t len );
+
+/**
+ * Initialise a data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @v op Data transfer interface operations
+ * @v refcnt Containing object reference counter, or NULL
+ */
+static inline void xfer_init ( struct xfer_interface *xfer,
+ struct xfer_interface_operations *op,
+ struct refcnt *refcnt ) {
+ xfer->intf.dest = &null_xfer.intf;
+ xfer->intf.refcnt = refcnt;
+ xfer->op = op;
+}
+
+/**
+ * Initialise a static data transfer interface
+ *
+ * @v operations Data transfer interface operations
+ */
+#define XFER_INIT( operations ) { \
+ .intf = { \
+ .dest = &null_xfer.intf, \
+ .refcnt = NULL, \
+ }, \
+ .op = operations, \
+ }
+
+/**
+ * Get data transfer interface from generic object communication interface
+ *
+ * @v intf Generic object communication interface
+ * @ret xfer Data transfer interface
+ */
+static inline __attribute__ (( always_inline )) struct xfer_interface *
+intf_to_xfer ( struct interface *intf ) {
+ return container_of ( intf, struct xfer_interface, intf );
+}
+
+/**
+ * Get reference to destination data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @ret dest Destination interface
+ */
+static inline __attribute__ (( always_inline )) struct xfer_interface *
+xfer_get_dest ( struct xfer_interface *xfer ) {
+ return intf_to_xfer ( intf_get ( xfer->intf.dest ) );
+}
+
+/**
+ * Drop reference to data transfer interface
+ *
+ * @v xfer Data transfer interface
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_put ( struct xfer_interface *xfer ) {
+ intf_put ( &xfer->intf );
+}
+
+/**
+ * Plug a data transfer interface into a new destination interface
+ *
+ * @v xfer Data transfer interface
+ * @v dest New destination interface
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_plug ( struct xfer_interface *xfer, struct xfer_interface *dest ) {
+ plug ( &xfer->intf, &dest->intf );
+}
+
+/**
+ * Plug two data transfer interfaces together
+ *
+ * @v a Data transfer interface A
+ * @v b Data transfer interface B
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_plug_plug ( struct xfer_interface *a, struct xfer_interface *b ) {
+ plug_plug ( &a->intf, &b->intf );
+}
+
+/**
+ * Unplug a data transfer interface
+ *
+ * @v xfer Data transfer interface
+ */
+static inline __attribute__ (( always_inline )) void
+xfer_unplug ( struct xfer_interface *xfer ) {
+ plug ( &xfer->intf, &null_xfer.intf );
+}
+
+/**
+ * Stop using a data transfer interface
+ *
+ * @v xfer Data transfer interface
+ *
+ * After calling this method, no further messages will be received via
+ * the interface.
+ */
+static inline void xfer_nullify ( struct xfer_interface *xfer ) {
+ xfer->op = &null_xfer_ops;
+};
+
+#endif /* _GPXE_XFER_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/include/nic.h b/debian/grub-extras/disabled/gpxe/src/include/nic.h
new file mode 100644
index 0000000..7097068
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/include/nic.h
@@ -0,0 +1,273 @@
+ /*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef NIC_H
+#define NIC_H
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <gpxe/pci.h>
+#include <gpxe/isapnp.h>
+#include <gpxe/isa.h>
+#include <gpxe/eisa.h>
+#include <gpxe/mca.h>
+#include <gpxe/io.h>
+
+typedef enum {
+ DISABLE = 0,
+ ENABLE,
+ FORCE
+} irq_action_t;
+
+typedef enum duplex {
+ HALF_DUPLEX = 1,
+ FULL_DUPLEX
+} duplex_t;
+
+/*
+ * Structure returned from eth_probe and passed to other driver
+ * functions.
+ */
+struct nic {
+ struct nic_operations *nic_op;
+ int flags; /* driver specific flags */
+ unsigned char *node_addr;
+ unsigned char *packet;
+ unsigned int packetlen;
+ unsigned int ioaddr;
+ unsigned char irqno;
+ unsigned int mbps;
+ duplex_t duplex;
+ void *priv_data; /* driver private data */
+};
+
+struct nic_operations {
+ int ( *connect ) ( struct nic * );
+ int ( *poll ) ( struct nic *, int retrieve );
+ void ( *transmit ) ( struct nic *, const char *,
+ unsigned int, unsigned int, const char * );
+ void ( *irq ) ( struct nic *, irq_action_t );
+};
+
+extern struct nic nic;
+
+static inline int eth_poll ( int retrieve ) {
+ return nic.nic_op->poll ( &nic, retrieve );
+}
+
+static inline void eth_transmit ( const char *dest, unsigned int type,
+ unsigned int size, const void *packet ) {
+ nic.nic_op->transmit ( &nic, dest, type, size, packet );
+}
+
+/*
+ * Function prototypes
+ *
+ */
+extern int dummy_connect ( struct nic *nic );
+extern void dummy_irq ( struct nic *nic, irq_action_t irq_action );
+extern int legacy_probe ( void *hwdev,
+ void ( * set_drvdata ) ( void *hwdev, void *priv ),
+ struct device *dev,
+ int ( * probe ) ( struct nic *nic, void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ));
+void legacy_remove ( void *hwdev,
+ void * ( * get_drvdata ) ( void *hwdev ),
+ void ( * disable ) ( struct nic *nic, void *hwdev ) );
+
+#define PCI_DRIVER(_name,_ids,_class) \
+ static inline int \
+ _name ## _pci_legacy_probe ( struct pci_device *pci, \
+ const struct pci_device_id *id ); \
+ static inline void \
+ _name ## _pci_legacy_remove ( struct pci_device *pci ); \
+ struct pci_driver _name __pci_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _pci_legacy_probe, \
+ .remove = _name ## _pci_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( pci );
+
+static inline void legacy_pci_set_drvdata ( void *hwdev, void *priv ) {
+ pci_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_pci_get_drvdata ( void *hwdev ) {
+ return pci_get_drvdata ( hwdev );
+}
+
+#define ISAPNP_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
+ const struct isapnp_device_id *id ); \
+ static inline void \
+ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ); \
+ struct isapnp_driver _name __isapnp_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _isapnp_legacy_probe, \
+ .remove = _name ## _isapnp_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( isapnp );
+
+static inline void legacy_isapnp_set_drvdata ( void *hwdev, void *priv ) {
+ isapnp_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_isapnp_get_drvdata ( void *hwdev ) {
+ return isapnp_get_drvdata ( hwdev );
+}
+
+#define EISA_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
+ const struct eisa_device_id *id ); \
+ static inline void \
+ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ); \
+ struct eisa_driver _name __eisa_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _eisa_legacy_probe, \
+ .remove = _name ## _eisa_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( eisa );
+
+static inline void legacy_eisa_set_drvdata ( void *hwdev, void *priv ) {
+ eisa_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_eisa_get_drvdata ( void *hwdev ) {
+ return eisa_get_drvdata ( hwdev );
+}
+
+#define MCA_DRIVER(_name,_ids) \
+ static inline int \
+ _name ## _mca_legacy_probe ( struct mca_device *mca, \
+ const struct mca_device_id *id ); \
+ static inline void \
+ _name ## _mca_legacy_remove ( struct mca_device *mca ); \
+ struct mca_driver _name __mca_driver = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .probe = _name ## _mca_legacy_probe, \
+ .remove = _name ## _mca_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( mca );
+
+static inline void legacy_mca_set_drvdata ( void *hwdev, void *priv ) {
+ mca_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_mca_get_drvdata ( void *hwdev ) {
+ return mca_get_drvdata ( hwdev );
+}
+
+#define ISA_DRIVER(_name,_probe_addrs,_probe_addr,_vendor_id,_prod_id) \
+ static inline int \
+ _name ## _isa_legacy_probe ( struct isa_device *isa ); \
+ static inline int \
+ _name ## _isa_legacy_probe_at_addr ( struct isa_device *isa ) { \
+ if ( ! _probe_addr ( isa->ioaddr ) ) \
+ return -ENODEV; \
+ return _name ## _isa_legacy_probe ( isa ); \
+ } \
+ static inline void \
+ _name ## _isa_legacy_remove ( struct isa_device *isa ); \
+ static const char _name ## _text[]; \
+ struct isa_driver _name __isa_driver = { \
+ .name = _name ## _text, \
+ .probe_addrs = _probe_addrs, \
+ .addr_count = ( sizeof ( _probe_addrs ) / \
+ sizeof ( _probe_addrs[0] ) ), \
+ .vendor_id = _vendor_id, \
+ .prod_id = _prod_id, \
+ .probe = _name ## _isa_legacy_probe_at_addr, \
+ .remove = _name ## _isa_legacy_remove, \
+ }; \
+ REQUIRE_OBJECT ( isa );
+
+static inline void legacy_isa_set_drvdata ( void *hwdev, void *priv ) {
+ isa_set_drvdata ( hwdev, priv );
+}
+static inline void * legacy_isa_get_drvdata ( void *hwdev ) {
+ return isa_get_drvdata ( hwdev );
+}
+
+#undef DRIVER
+#define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable) \
+ static const char _name ## _text[] = _name_text; \
+ static inline int \
+ _name ## _probe ( struct nic *nic, void *hwdev ) { \
+ return _probe ( nic, hwdev ); \
+ } \
+ static inline void \
+ _name ## _disable ( struct nic *nic, void *hwdev ) { \
+ void ( * _unsafe_disable ) () = _disable; \
+ _unsafe_disable ( nic, hwdev ); \
+ } \
+ static inline int \
+ _name ## _pci_legacy_probe ( struct pci_device *pci, \
+ const struct pci_device_id *id __unused ) { \
+ return legacy_probe ( pci, legacy_pci_set_drvdata, \
+ (void *) &pci->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _pci_legacy_remove ( struct pci_device *pci ) { \
+ return legacy_remove ( pci, legacy_pci_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
+ const struct isapnp_device_id *id __unused ) { \
+ return legacy_probe ( isapnp, legacy_isapnp_set_drvdata, \
+ &isapnp->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \
+ return legacy_remove ( isapnp, legacy_isapnp_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
+ const struct eisa_device_id *id __unused ) { \
+ return legacy_probe ( eisa, legacy_eisa_set_drvdata, \
+ &eisa->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _eisa_legacy_remove ( struct eisa_device *eisa ) { \
+ return legacy_remove ( eisa, legacy_eisa_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _mca_legacy_probe ( struct mca_device *mca, \
+ const struct mca_device_id *id __unused ) { \
+ return legacy_probe ( mca, legacy_mca_set_drvdata, \
+ &mca->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _mca_legacy_remove ( struct mca_device *mca ) { \
+ return legacy_remove ( mca, legacy_mca_get_drvdata, \
+ _name ## _disable ); \
+ } \
+ static inline int \
+ _name ## _isa_legacy_probe ( struct isa_device *isa ) { \
+ return legacy_probe ( isa, legacy_isa_set_drvdata, \
+ &isa->dev, _name ## _probe, \
+ _name ## _disable ); \
+ } \
+ static inline void \
+ _name ## _isa_legacy_remove ( struct isa_device *isa ) { \
+ return legacy_remove ( isa, legacy_isa_get_drvdata, \
+ _name ## _disable ); \
+ }
+
+#endif /* NIC_H */
diff --git a/debian/grub-extras/disabled/gpxe/src/net/80211/net80211.c b/debian/grub-extras/disabled/gpxe/src/net/80211/net80211.c
new file mode 100644
index 0000000..1fc983a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/80211/net80211.c
@@ -0,0 +1,2645 @@
+/*
+ * The gPXE 802.11 MAC layer.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <byteswap.h>
+#include <stdlib.h>
+#include <gpxe/settings.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/ieee80211.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/net80211.h>
+#include <gpxe/timer.h>
+#include <gpxe/nap.h>
+#include <unistd.h>
+#include <errno.h>
+
+/** @file
+ *
+ * 802.11 device management
+ */
+
+/* Disambiguate the EINVAL's a bit */
+#define EINVAL_PKT_TOO_SHORT ( EINVAL | EUNIQ_01 )
+#define EINVAL_PKT_VERSION ( EINVAL | EUNIQ_02 )
+#define EINVAL_PKT_NOT_DATA ( EINVAL | EUNIQ_03 )
+#define EINVAL_PKT_NOT_FROMDS ( EINVAL | EUNIQ_04 )
+#define EINVAL_PKT_LLC_HEADER ( EINVAL | EUNIQ_05 )
+#define EINVAL_CRYPTO_REQUEST ( EINVAL | EUNIQ_06 )
+#define EINVAL_ACTIVE_SCAN ( EINVAL | EUNIQ_07 )
+
+/*
+ * 802.11 error codes: The AP can give us a status code explaining why
+ * authentication failed, or a reason code explaining why we were
+ * deauthenticated/disassociated. These codes range from 0-63 (the
+ * field is 16 bits wide, but only up to 45 or so are defined yet; we
+ * allow up to 63 for extensibility). This is encoded into an error
+ * code as such:
+ *
+ * status & 0x1f goes here --vv--
+ * Status code 0-31: ECONNREFUSED | EUNIQ_(status & 0x1f) (0e1a6038)
+ * Status code 32-63: EHOSTUNREACH | EUNIQ_(status & 0x1f) (171a6011)
+ * Reason code 0-31: ECONNRESET | EUNIQ_(reason & 0x1f) (0f1a6039)
+ * Reason code 32-63: ENETRESET | EUNIQ_(reason & 0x1f) (271a6001)
+ *
+ * The POSIX error codes more or less convey the appropriate message
+ * (status codes occur when we can't associate at all, reason codes
+ * when we lose association unexpectedly) and let us extract the
+ * complete 802.11 error code from the rc value.
+ */
+
+/** Make return status code from 802.11 status code */
+#define E80211_STATUS( stat ) ( ((stat & 0x20)? EHOSTUNREACH : ECONNREFUSED) \
+ | ((stat & 0x1f) << 8) )
+
+/** Make return status code from 802.11 reason code */
+#define E80211_REASON( reas ) ( ((reas & 0x20)? ENETRESET : ECONNRESET) \
+ | ((reas & 0x1f) << 8) )
+
+
+/** List of 802.11 devices */
+static struct list_head net80211_devices = LIST_HEAD_INIT ( net80211_devices );
+
+/** Set of device operations that does nothing */
+static struct net80211_device_operations net80211_null_ops;
+
+/** Information associated with a received management packet
+ *
+ * This is used to keep beacon signal strengths in a parallel queue to
+ * the beacons themselves.
+ */
+struct net80211_rx_info {
+ int signal;
+ struct list_head list;
+};
+
+/** Context for a probe operation */
+struct net80211_probe_ctx {
+ /** 802.11 device to probe on */
+ struct net80211_device *dev;
+
+ /** Value of keep_mgmt before probe was started */
+ int old_keep_mgmt;
+
+ /** If scanning actively, pointer to probe packet to send */
+ struct io_buffer *probe;
+
+ /** If non-"", the ESSID to limit ourselves to */
+ const char *essid;
+
+ /** Time probe was started */
+ u32 ticks_start;
+
+ /** Time last useful beacon was received */
+ u32 ticks_beacon;
+
+ /** Time channel was last changed */
+ u32 ticks_channel;
+
+ /** Time to stay on each channel */
+ u32 hop_time;
+
+ /** Channels to hop by when changing channel */
+ int hop_step;
+
+ /** List of best beacons for each network found so far */
+ struct list_head *beacons;
+};
+
+/** Context for the association task */
+struct net80211_assoc_ctx {
+ /** Next authentication method to try using */
+ int method;
+
+ /** Time (in ticks) of the last sent association-related packet */
+ int last_packet;
+
+ /** Number of times we have tried sending it */
+ int times_tried;
+};
+
+/**
+ * @defgroup net80211_netdev Network device interface functions
+ * @{
+ */
+static int net80211_netdev_open ( struct net_device *netdev );
+static void net80211_netdev_close ( struct net_device *netdev );
+static int net80211_netdev_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+static void net80211_netdev_poll ( struct net_device *netdev );
+static void net80211_netdev_irq ( struct net_device *netdev, int enable );
+/** @} */
+
+/**
+ * @defgroup net80211_linklayer 802.11 link-layer protocol functions
+ * @{
+ */
+static int net80211_ll_push ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source, uint16_t net_proto );
+static int net80211_ll_pull ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void **ll_dest,
+ const void **ll_source, uint16_t * net_proto );
+/** @} */
+
+/**
+ * @defgroup net80211_help 802.11 helper functions
+ * @{
+ */
+static void net80211_add_channels ( struct net80211_device *dev, int start,
+ int len, int txpower );
+static void net80211_filter_hw_channels ( struct net80211_device *dev );
+static void net80211_set_rtscts_rate ( struct net80211_device *dev );
+static int net80211_process_capab ( struct net80211_device *dev,
+ u16 capab );
+static int net80211_process_ie ( struct net80211_device *dev,
+ union ieee80211_ie *ie, void *ie_end );
+static union ieee80211_ie *
+net80211_marshal_request_info ( struct net80211_device *dev,
+ union ieee80211_ie *ie );
+/** @} */
+
+/**
+ * @defgroup net80211_assoc_ll 802.11 association handling functions
+ * @{
+ */
+static void net80211_step_associate ( struct process *proc );
+static void net80211_handle_auth ( struct net80211_device *dev,
+ struct io_buffer *iob );
+static void net80211_handle_assoc_reply ( struct net80211_device *dev,
+ struct io_buffer *iob );
+static int net80211_send_disassoc ( struct net80211_device *dev, int reason );
+static void net80211_handle_mgmt ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal );
+/** @} */
+
+/**
+ * @defgroup net80211_frag 802.11 fragment handling functions
+ * @{
+ */
+static void net80211_free_frags ( struct net80211_device *dev, int fcid );
+static struct io_buffer *net80211_accum_frags ( struct net80211_device *dev,
+ int fcid, int nfrags, int size );
+static void net80211_rx_frag ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal );
+/** @} */
+
+/**
+ * @defgroup net80211_settings 802.11 settings handlers
+ * @{
+ */
+static int net80211_check_ssid_update ( void );
+
+/** 802.11 settings applicator
+ *
+ * When the SSID is changed, this will cause any open devices to
+ * re-associate.
+ */
+struct settings_applicator net80211_ssid_applicator __settings_applicator = {
+ .apply = net80211_check_ssid_update,
+};
+
+/** The network name to associate with
+ *
+ * If this is blank, we scan for all networks and use the one with the
+ * greatest signal strength.
+ */
+struct setting net80211_ssid_setting __setting = {
+ .name = "ssid",
+ .description = "802.11 SSID (network name)",
+ .type = &setting_type_string,
+};
+
+/** Whether to use active scanning
+ *
+ * In order to associate with a hidden SSID, it's necessary to use an
+ * active scan (send probe packets). If this setting is nonzero, an
+ * active scan on the 2.4GHz band will be used to associate.
+ */
+struct setting net80211_active_setting __setting = {
+ .name = "active-scan",
+ .description = "Use an active scan during 802.11 association",
+ .type = &setting_type_int8,
+};
+
+/** @} */
+
+
+/* ---------- net_device wrapper ---------- */
+
+/**
+ * Open 802.11 device and start association
+ *
+ * @v netdev Wrapping network device
+ * @ret rc Return status code
+ *
+ * This sets up a default conservative set of channels for probing,
+ * and starts the auto-association task unless the @c
+ * NET80211_NO_ASSOC flag is set in the wrapped 802.11 device's @c
+ * state field.
+ */
+static int net80211_netdev_open ( struct net_device *netdev )
+{
+ struct net80211_device *dev = netdev->priv;
+ int rc = 0;
+
+ if ( dev->op == &net80211_null_ops )
+ return -EFAULT;
+
+ if ( dev->op->open )
+ rc = dev->op->open ( dev );
+
+ if ( rc < 0 )
+ return rc;
+
+ if ( ! ( dev->state & NET80211_NO_ASSOC ) )
+ net80211_autoassociate ( dev );
+
+ return 0;
+}
+
+/**
+ * Close 802.11 device
+ *
+ * @v netdev Wrapping network device.
+ *
+ * If the association task is running, this will stop it.
+ */
+static void net80211_netdev_close ( struct net_device *netdev )
+{
+ struct net80211_device *dev = netdev->priv;
+
+ if ( dev->state & NET80211_WORKING )
+ process_del ( &dev->proc_assoc );
+
+ /* Send disassociation frame to AP, to be polite */
+ if ( dev->state & NET80211_ASSOCIATED )
+ net80211_send_disassoc ( dev, IEEE80211_REASON_LEAVING );
+
+ netdev_link_down ( netdev );
+ dev->state = 0;
+
+ if ( dev->op->close )
+ dev->op->close ( dev );
+}
+
+/**
+ * Transmit packet on 802.11 device
+ *
+ * @v netdev Wrapping network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * If encryption is enabled for the currently associated network, the
+ * packet will be encrypted prior to transmission.
+ */
+static int net80211_netdev_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf )
+{
+ struct net80211_device *dev = netdev->priv;
+ int rc = -ENOSYS;
+
+ if ( dev->crypto ) {
+ struct io_buffer *niob = dev->crypto->encrypt ( dev->crypto,
+ iobuf );
+ if ( ! niob )
+ return -ENOMEM; /* only reason encryption could fail */
+
+ free_iob ( iobuf );
+ iobuf = niob;
+ }
+
+ if ( dev->op->transmit )
+ rc = dev->op->transmit ( dev, iobuf );
+
+ return rc;
+}
+
+/**
+ * Poll 802.11 device for received packets and completed transmissions
+ *
+ * @v netdev Wrapping network device
+ */
+static void net80211_netdev_poll ( struct net_device *netdev )
+{
+ struct net80211_device *dev = netdev->priv;
+
+ if ( dev->op->poll )
+ dev->op->poll ( dev );
+}
+
+/**
+ * Enable or disable interrupts for 802.11 device
+ *
+ * @v netdev Wrapping network device
+ * @v enable Whether to enable interrupts
+ */
+static void net80211_netdev_irq ( struct net_device *netdev, int enable )
+{
+ struct net80211_device *dev = netdev->priv;
+
+ if ( dev->op->irq )
+ dev->op->irq ( dev, enable );
+}
+
+/** Network device operations for a wrapped 802.11 device */
+static struct net_device_operations net80211_netdev_ops = {
+ .open = net80211_netdev_open,
+ .close = net80211_netdev_close,
+ .transmit = net80211_netdev_transmit,
+ .poll = net80211_netdev_poll,
+ .irq = net80211_netdev_irq,
+};
+
+
+/* ---------- 802.11 link-layer protocol ---------- */
+
+/** 802.11 broadcast MAC address */
+static u8 net80211_ll_broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/**
+ * Determine whether a transmission rate uses ERP/OFDM
+ *
+ * @v rate Rate in 100 kbps units
+ * @ret is_erp TRUE if the rate is an ERP/OFDM rate
+ *
+ * 802.11b supports rates of 1.0, 2.0, 5.5, and 11.0 Mbps; any other
+ * rate than these on the 2.4GHz spectrum is an ERP (802.11g) rate.
+ */
+static inline int net80211_rate_is_erp ( u16 rate )
+{
+ if ( rate == 10 || rate == 20 || rate == 55 || rate == 110 )
+ return 0;
+ return 1;
+}
+
+
+/**
+ * Calculate one frame's contribution to 802.11 duration field
+ *
+ * @v dev 802.11 device
+ * @v bytes Amount of data to calculate duration for
+ * @ret dur Duration field in microseconds
+ *
+ * To avoid multiple stations attempting to transmit at once, 802.11
+ * provides that every packet shall include a duration field
+ * specifying a length of time for which the wireless medium will be
+ * reserved after it is transmitted. The duration is measured in
+ * microseconds and is calculated with respect to the current
+ * physical-layer parameters of the 802.11 device.
+ *
+ * For an unfragmented data or management frame, or the last fragment
+ * of a fragmented frame, the duration captures only the 10 data bytes
+ * of one ACK; call once with bytes = 10.
+ *
+ * For a fragment of a data or management rame that will be followed
+ * by more fragments, the duration captures an ACK, the following
+ * fragment, and its ACK; add the results of three calls, two with
+ * bytes = 10 and one with bytes set to the next fragment's size.
+ *
+ * For an RTS control frame, the duration captures the responding CTS,
+ * the frame being sent, and its ACK; add the results of three calls,
+ * two with bytes = 10 and one with bytes set to the next frame's size
+ * (assuming unfragmented).
+ *
+ * For a CTS-to-self control frame, the duration captures the frame
+ * being protected and its ACK; add the results of two calls, one with
+ * bytes = 10 and one with bytes set to the next frame's size.
+ *
+ * No other frame types are currently supported by gPXE.
+ */
+u16 net80211_duration ( struct net80211_device *dev, int bytes, u16 rate )
+{
+ struct net80211_channel *chan = &dev->channels[dev->channel];
+ u32 kbps = rate * 100;
+
+ if ( chan->band == NET80211_BAND_5GHZ || net80211_rate_is_erp ( rate ) ) {
+ /* OFDM encoding (802.11a/g) */
+ int bits_per_symbol = ( kbps * 4 ) / 1000; /* 4us/symbol */
+ int bits = 22 + ( bytes << 3 ); /* 22-bit PLCP */
+ int symbols = ( bits + bits_per_symbol - 1 ) / bits_per_symbol;
+
+ return 16 + 20 + ( symbols * 4 ); /* 16us SIFS, 20us preamble */
+ } else {
+ /* CCK encoding (802.11b) */
+ int phy_time = 144 + 48; /* preamble + PLCP */
+ int bits = bytes << 3;
+ int data_time = ( bits * 1000 + kbps - 1 ) / kbps;
+
+ if ( dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE )
+ phy_time >>= 1;
+
+ return 10 + phy_time + data_time; /* 10us SIFS */
+ }
+}
+
+/**
+ * Add 802.11 link-layer header
+ *
+ * @v netdev Wrapping network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v net_proto Network-layer protocol, in network byte order
+ * @ret rc Return status code
+ *
+ * This adds both the 802.11 frame header and the 802.2 LLC/SNAP
+ * header used on data packets.
+ *
+ * We also check here for state of the link that would make it invalid
+ * to send a data packet; every data packet must pass through here,
+ * and no non-data packet (e.g. management frame) should.
+ */
+static int net80211_ll_push ( struct net_device *netdev,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source, uint16_t net_proto )
+{
+ struct net80211_device *dev = netdev->priv;
+ struct ieee80211_frame *hdr = iob_push ( iobuf,
+ IEEE80211_LLC_HEADER_LEN +
+ IEEE80211_TYP_FRAME_HEADER_LEN );
+ struct ieee80211_llc_snap_header *lhdr =
+ ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;
+
+ /* We can't send data packets if we're not associated. */
+ if ( ! netdev_link_ok ( netdev ) ) {
+ if ( dev->assoc_rc )
+ return dev->assoc_rc;
+ return -ENETUNREACH;
+ }
+
+ hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_DATA |
+ IEEE80211_STYPE_DATA | IEEE80211_FC_TODS;
+
+ /* We don't send fragmented frames, so duration is the time
+ for an SIFS + 10-byte ACK. */
+ hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
+
+ memcpy ( hdr->addr1, dev->bssid, ETH_ALEN );
+ memcpy ( hdr->addr2, ll_source, ETH_ALEN );
+ memcpy ( hdr->addr3, ll_dest, ETH_ALEN );
+
+ hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 );
+
+ lhdr->dsap = IEEE80211_LLC_DSAP;
+ lhdr->ssap = IEEE80211_LLC_SSAP;
+ lhdr->ctrl = IEEE80211_LLC_CTRL;
+ memset ( lhdr->oui, 0x00, 3 );
+ lhdr->ethertype = net_proto;
+
+ return 0;
+}
+
+/**
+ * Remove 802.11 link-layer header
+ *
+ * @v netdev Wrapping network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Link-layer source
+ * @ret net_proto Network-layer protocol, in network byte order
+ * @ret rc Return status code
+ *
+ * This expects and removes both the 802.11 frame header and the 802.2
+ * LLC/SNAP header that are used on data packets.
+ */
+static int net80211_ll_pull ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf,
+ const void **ll_dest, const void **ll_source,
+ uint16_t * net_proto )
+{
+ struct ieee80211_frame *hdr = iobuf->data;
+ struct ieee80211_llc_snap_header *lhdr =
+ ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;
+
+ /* Bunch of sanity checks */
+ if ( iob_len ( iobuf ) < IEEE80211_TYP_FRAME_HEADER_LEN +
+ IEEE80211_LLC_HEADER_LEN ) {
+ DBGC ( netdev->priv, "802.11 %p packet too short (%zd bytes)\n",
+ netdev->priv, iob_len ( iobuf ) );
+ return -EINVAL_PKT_TOO_SHORT;
+ }
+
+ if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION ) {
+ DBGC ( netdev->priv, "802.11 %p packet invalid version %04x\n",
+ netdev->priv, hdr->fc & IEEE80211_FC_VERSION );
+ return -EINVAL_PKT_VERSION;
+ }
+
+ if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_DATA ||
+ ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA ) {
+ DBGC ( netdev->priv, "802.11 %p packet not data/data (fc=%04x)\n",
+ netdev->priv, hdr->fc );
+ return -EINVAL_PKT_NOT_DATA;
+ }
+
+ if ( ( hdr->fc & ( IEEE80211_FC_TODS | IEEE80211_FC_FROMDS ) ) !=
+ IEEE80211_FC_FROMDS ) {
+ DBGC ( netdev->priv, "802.11 %p packet not from DS (fc=%04x)\n",
+ netdev->priv, hdr->fc );
+ return -EINVAL_PKT_NOT_FROMDS;
+ }
+
+ if ( lhdr->dsap != IEEE80211_LLC_DSAP || lhdr->ssap != IEEE80211_LLC_SSAP ||
+ lhdr->ctrl != IEEE80211_LLC_CTRL || lhdr->oui[0] || lhdr->oui[1] ||
+ lhdr->oui[2] ) {
+ DBGC ( netdev->priv, "802.11 %p LLC header is not plain EtherType "
+ "encapsulator: %02x->%02x [%02x] %02x:%02x:%02x %04x\n",
+ netdev->priv, lhdr->dsap, lhdr->ssap, lhdr->ctrl,
+ lhdr->oui[0], lhdr->oui[1], lhdr->oui[2], lhdr->ethertype );
+ return -EINVAL_PKT_LLC_HEADER;
+ }
+
+ iob_pull ( iobuf, sizeof ( *hdr ) + sizeof ( *lhdr ) );
+
+ *ll_dest = hdr->addr1;
+ *ll_source = hdr->addr3;
+ *net_proto = lhdr->ethertype;
+ return 0;
+}
+
+/** 802.11 link-layer protocol */
+static struct ll_protocol net80211_ll_protocol __ll_protocol = {
+ .name = "802.11",
+ .push = net80211_ll_push,
+ .pull = net80211_ll_pull,
+ .init_addr = eth_init_addr,
+ .ntoa = eth_ntoa,
+ .mc_hash = eth_mc_hash,
+ .ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */
+ .hw_addr_len = ETH_ALEN,
+ .ll_addr_len = ETH_ALEN,
+ .ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN +
+ IEEE80211_LLC_HEADER_LEN,
+};
+
+
+/* ---------- 802.11 network management API ---------- */
+
+/**
+ * Get 802.11 device from wrapping network device
+ *
+ * @v netdev Wrapping network device
+ * @ret dev 802.11 device wrapped by network device, or NULL
+ *
+ * Returns NULL if the network device does not wrap an 802.11 device.
+ */
+struct net80211_device * net80211_get ( struct net_device *netdev )
+{
+ struct net80211_device *dev;
+
+ list_for_each_entry ( dev, &net80211_devices, list ) {
+ if ( netdev->priv == dev )
+ return netdev->priv;
+ }
+
+ return NULL;
+}
+
+/**
+ * Set state of 802.11 device keeping management frames
+ *
+ * @v dev 802.11 device
+ * @v enable Whether to keep management frames
+ * @ret oldenab Whether management frames were enabled before this call
+ *
+ * If enable is TRUE, beacon, probe, and action frames will be kept
+ * and may be retrieved by calling net80211_mgmt_dequeue().
+ */
+int net80211_keep_mgmt ( struct net80211_device *dev, int enable )
+{
+ int oldenab = dev->keep_mgmt;
+
+ dev->keep_mgmt = enable;
+ return oldenab;
+}
+
+/**
+ * Get 802.11 management frame
+ *
+ * @v dev 802.11 device
+ * @ret signal Signal strength of returned management frame
+ * @ret iob I/O buffer, or NULL if no management frame is queued
+ *
+ * Frames will only be returned by this function if
+ * net80211_keep_mgmt() has been previously called with enable set to
+ * TRUE.
+ *
+ * The calling function takes ownership of the returned I/O buffer.
+ */
+struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev,
+ int *signal )
+{
+ struct io_buffer *iobuf;
+ struct net80211_rx_info *rxi;
+
+ list_for_each_entry ( rxi, &dev->mgmt_info_queue, list ) {
+ list_del ( &rxi->list );
+ if ( signal )
+ *signal = rxi->signal;
+ free ( rxi );
+
+ list_for_each_entry ( iobuf, &dev->mgmt_queue, list ) {
+ list_del ( &iobuf->list );
+ return iobuf;
+ }
+ assert ( 0 );
+ }
+
+ return NULL;
+}
+
+/**
+ * Transmit 802.11 management frame
+ *
+ * @v dev 802.11 device
+ * @v fc Frame Control flags for management frame
+ * @v dest Destination access point
+ * @v iob I/O buffer
+ * @ret rc Return status code
+ *
+ * The @a fc argument must contain at least an IEEE 802.11 management
+ * subtype number (e.g. IEEE80211_STYPE_PROBE_REQ). If it contains
+ * IEEE80211_FC_PROTECTED, the frame will be encrypted prior to
+ * transmission.
+ *
+ * It is required that @a iob have at least 24 bytes of headroom
+ * reserved before its data start.
+ */
+int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc, u8 dest[6],
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob_push ( iob,
+ IEEE80211_TYP_FRAME_HEADER_LEN );
+
+ hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_MGMT |
+ ( fc & ~IEEE80211_FC_PROTECTED );
+ hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
+ hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 );
+
+ memcpy ( hdr->addr1, dest, ETH_ALEN ); /* DA = RA */
+ memcpy ( hdr->addr2, dev->netdev->ll_addr, ETH_ALEN ); /* SA = TA */
+ memcpy ( hdr->addr3, dest, ETH_ALEN ); /* BSSID */
+
+ if ( fc & IEEE80211_FC_PROTECTED ) {
+ if ( ! dev->crypto )
+ return -EINVAL_CRYPTO_REQUEST;
+
+ struct io_buffer *eiob = dev->crypto->encrypt ( dev->crypto,
+ iob );
+ free_iob ( iob );
+ iob = eiob;
+ }
+
+ return netdev_tx ( dev->netdev, iob );
+}
+
+
+/* ---------- Driver API ---------- */
+
+/**
+ * Allocate 802.11 device
+ *
+ * @v priv_size Size of driver-private allocation area
+ * @ret dev Newly allocated 802.11 device
+ *
+ * This function allocates a net_device with space in its private area
+ * for both the net80211_device it will wrap and the driver-private
+ * data space requested. It initializes the link-layer-specific parts
+ * of the net_device, and links the net80211_device to the net_device
+ * appropriately.
+ */
+struct net80211_device * net80211_alloc ( size_t priv_size )
+{
+ struct net80211_device *dev;
+ struct net_device *netdev =
+ alloc_netdev ( sizeof ( *dev ) + priv_size );
+
+ if ( ! netdev )
+ return NULL;
+
+ netdev->ll_protocol = &net80211_ll_protocol;
+ netdev->ll_broadcast = net80211_ll_broadcast;
+ netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN;
+ netdev_init ( netdev, &net80211_netdev_ops );
+
+ dev = netdev->priv;
+ dev->netdev = netdev;
+ dev->priv = ( u8 * ) dev + sizeof ( *dev );
+ dev->op = &net80211_null_ops;
+
+ process_init_stopped ( &dev->proc_assoc, net80211_step_associate,
+ &netdev->refcnt );
+ INIT_LIST_HEAD ( &dev->mgmt_queue );
+ INIT_LIST_HEAD ( &dev->mgmt_info_queue );
+
+ return dev;
+}
+
+/**
+ * Register 802.11 device with network stack
+ *
+ * @v dev 802.11 device
+ * @v ops 802.11 device operations
+ * @v hw 802.11 hardware information
+ *
+ * This also registers the wrapping net_device with the higher network
+ * layers.
+ */
+int net80211_register ( struct net80211_device *dev,
+ struct net80211_device_operations *ops,
+ struct net80211_hw_info *hw )
+{
+ dev->op = ops;
+ dev->hw = malloc ( sizeof ( *hw ) );
+ if ( ! dev->hw )
+ return -ENOMEM;
+
+ memcpy ( dev->hw, hw, sizeof ( *hw ) );
+ memcpy ( dev->netdev->hw_addr, hw->hwaddr, ETH_ALEN );
+
+ /* Set some sensible channel defaults for driver's open() function */
+ memcpy ( dev->channels, dev->hw->channels,
+ NET80211_MAX_CHANNELS * sizeof ( dev->channels[0] ) );
+ dev->channel = 0;
+
+ list_add_tail ( &dev->list, &net80211_devices );
+ return register_netdev ( dev->netdev );
+}
+
+/**
+ * Unregister 802.11 device from network stack
+ *
+ * @v dev 802.11 device
+ *
+ * After this call, the device operations are cleared so that they
+ * will not be called.
+ */
+void net80211_unregister ( struct net80211_device *dev )
+{
+ unregister_netdev ( dev->netdev );
+ list_del ( &dev->list );
+ dev->op = &net80211_null_ops;
+}
+
+/**
+ * Free 802.11 device
+ *
+ * @v dev 802.11 device
+ *
+ * The device should be unregistered before this function is called.
+ */
+void net80211_free ( struct net80211_device *dev )
+{
+ free ( dev->hw );
+ rc80211_free ( dev->rctl );
+ netdev_nullify ( dev->netdev );
+ netdev_put ( dev->netdev );
+}
+
+
+/* ---------- 802.11 network management workhorse code ---------- */
+
+/**
+ * Set state of 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v clear Bitmask of flags to clear
+ * @v set Bitmask of flags to set
+ * @v status Status or reason code for most recent operation
+ *
+ * If @a status represents a reason code, it should be OR'ed with
+ * NET80211_IS_REASON.
+ *
+ * Clearing authentication also clears association; clearing
+ * association also clears security handshaking state. Clearing
+ * association removes the link-up flag from the wrapping net_device,
+ * but setting it does not automatically set the flag; that is left to
+ * the judgment of higher-level code.
+ */
+static inline void net80211_set_state ( struct net80211_device *dev,
+ short clear, short set,
+ u16 status )
+{
+ /* The conditions in this function are deliberately formulated
+ to be decidable at compile-time in most cases. Since clear
+ and set are generally passed as constants, the body of this
+ function can be reduced down to a few statements by the
+ compiler. */
+
+ const int statmsk = NET80211_STATUS_MASK | NET80211_IS_REASON;
+
+ if ( clear & NET80211_PROBED )
+ clear |= NET80211_AUTHENTICATED;
+
+ if ( clear & NET80211_AUTHENTICATED )
+ clear |= NET80211_ASSOCIATED;
+
+ if ( clear & NET80211_ASSOCIATED )
+ clear |= NET80211_CRYPTO_SYNCED;
+
+ dev->state = ( dev->state & ~clear ) | set;
+ dev->state = ( dev->state & ~statmsk ) | ( status & statmsk );
+
+ if ( clear & NET80211_ASSOCIATED )
+ netdev_link_down ( dev->netdev );
+
+ if ( ( clear | set ) & NET80211_ASSOCIATED )
+ dev->op->config ( dev, NET80211_CFG_ASSOC );
+
+ if ( status != 0 ) {
+ if ( status & NET80211_IS_REASON )
+ dev->assoc_rc = -E80211_REASON ( status );
+ else
+ dev->assoc_rc = -E80211_STATUS ( status );
+ netdev_link_err ( dev->netdev, dev->assoc_rc );
+ }
+}
+
+/**
+ * Add channels to 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v start First channel number to add
+ * @v len Number of channels to add
+ * @v txpower TX power (dBm) to allow on added channels
+ *
+ * To replace the current list of channels instead of adding to it,
+ * set the nr_channels field of the 802.11 device to 0 before calling
+ * this function.
+ */
+static void net80211_add_channels ( struct net80211_device *dev, int start,
+ int len, int txpower )
+{
+ int i, chan = start;
+
+ for ( i = dev->nr_channels; len-- && i < NET80211_MAX_CHANNELS; i++ ) {
+ dev->channels[i].channel_nr = chan;
+ dev->channels[i].maxpower = txpower;
+ dev->channels[i].hw_value = 0;
+
+ if ( chan >= 1 && chan <= 14 ) {
+ dev->channels[i].band = NET80211_BAND_2GHZ;
+ if ( chan == 14 )
+ dev->channels[i].center_freq = 2484;
+ else
+ dev->channels[i].center_freq = 2407 + 5 * chan;
+ chan++;
+ } else {
+ dev->channels[i].band = NET80211_BAND_5GHZ;
+ dev->channels[i].center_freq = 5000 + 5 * chan;
+ chan += 4;
+ }
+ }
+
+ dev->nr_channels = i;
+}
+
+/**
+ * Filter 802.11 device channels for hardware capabilities
+ *
+ * @v dev 802.11 device
+ *
+ * Hardware may support fewer channels than regulatory restrictions
+ * allow; this function filters out channels in dev->channels that are
+ * not supported by the hardware list in dev->hwinfo. It also copies
+ * over the net80211_channel::hw_value and limits maximum TX power
+ * appropriately.
+ *
+ * Channels are matched based on center frequency, ignoring band and
+ * channel number.
+ *
+ * If the driver specifies no supported channels, the effect will be
+ * as though all were supported.
+ */
+static void net80211_filter_hw_channels ( struct net80211_device *dev )
+{
+ int delta = 0, i = 0;
+ int old_freq = dev->channels[dev->channel].center_freq;
+ struct net80211_channel *chan, *hwchan;
+
+ if ( ! dev->hw->nr_channels )
+ return;
+
+ dev->channel = 0;
+ for ( chan = dev->channels; chan < dev->channels + dev->nr_channels;
+ chan++, i++ ) {
+ int ok = 0;
+ for ( hwchan = dev->hw->channels;
+ hwchan < dev->hw->channels + dev->hw->nr_channels;
+ hwchan++ ) {
+ if ( hwchan->center_freq == chan->center_freq ) {
+ ok = 1;
+ break;
+ }
+ }
+
+ if ( ! ok )
+ delta++;
+ else {
+ chan->hw_value = hwchan->hw_value;
+ if ( hwchan->maxpower != 0 &&
+ chan->maxpower > hwchan->maxpower )
+ chan->maxpower = hwchan->maxpower;
+ if ( old_freq == chan->center_freq )
+ dev->channel = i - delta;
+ if ( delta )
+ chan[-delta] = *chan;
+ }
+ }
+
+ dev->nr_channels -= delta;
+
+ if ( dev->channels[dev->channel].center_freq != old_freq )
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+}
+
+/**
+ * Update 802.11 device state to reflect received capabilities field
+ *
+ * @v dev 802.11 device
+ * @v capab Capabilities field in beacon, probe, or association frame
+ * @ret rc Return status code
+ */
+static int net80211_process_capab ( struct net80211_device *dev,
+ u16 capab )
+{
+ u16 old_phy = dev->phy_flags;
+
+ if ( ( capab & ( IEEE80211_CAPAB_MANAGED | IEEE80211_CAPAB_ADHOC ) ) !=
+ IEEE80211_CAPAB_MANAGED ) {
+ DBGC ( dev, "802.11 %p cannot handle IBSS network\n", dev );
+ return -ENOSYS;
+ }
+
+ if ( capab & IEEE80211_CAPAB_SPECTRUM_MGMT ) {
+ DBGC ( dev, "802.11 %p cannot handle spectrum managed "
+ "network\n", dev );
+ return -ENOSYS;
+ }
+
+ dev->phy_flags &= ~( NET80211_PHY_USE_SHORT_PREAMBLE |
+ NET80211_PHY_USE_SHORT_SLOT );
+
+ if ( capab & IEEE80211_CAPAB_SHORT_PMBL )
+ dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE;
+
+ if ( capab & IEEE80211_CAPAB_SHORT_SLOT )
+ dev->phy_flags |= NET80211_PHY_USE_SHORT_SLOT;
+
+ if ( old_phy != dev->phy_flags )
+ dev->op->config ( dev, NET80211_CFG_PHY_PARAMS );
+
+ return 0;
+}
+
+/**
+ * Update 802.11 device state to reflect received information elements
+ *
+ * @v dev 802.11 device
+ * @v ie Pointer to first information element
+ * @v ie_end Pointer to tail of packet I/O buffer
+ * @ret rc Return status code
+ */
+static int net80211_process_ie ( struct net80211_device *dev,
+ union ieee80211_ie *ie, void *ie_end )
+{
+ u16 old_rate = dev->rates[dev->rate];
+ u16 old_phy = dev->phy_flags;
+ int have_rates = 0, i;
+ int ds_channel = 0;
+ int changed = 0;
+ int band = dev->channels[dev->channel].band;
+
+ if ( ( void * ) ie >= ie_end )
+ return 0;
+
+ for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) {
+ switch ( ie->id ) {
+ case IEEE80211_IE_SSID:
+ if ( ie->len <= 32 ) {
+ memcpy ( dev->essid, ie->ssid, ie->len );
+ dev->essid[ie->len] = 0;
+ }
+ break;
+
+ case IEEE80211_IE_RATES:
+ case IEEE80211_IE_EXT_RATES:
+ if ( ! have_rates ) {
+ dev->nr_rates = 0;
+ dev->basic_rates = 0;
+ have_rates = 1;
+ }
+ for ( i = 0; i < ie->len &&
+ dev->nr_rates < NET80211_MAX_RATES; i++ ) {
+ u8 rid = ie->rates[i];
+ u16 rate = ( rid & 0x7f ) * 5;
+
+ if ( rid & 0x80 )
+ dev->basic_rates |=
+ ( 1 << dev->nr_rates );
+
+ dev->rates[dev->nr_rates++] = rate;
+ }
+
+ break;
+
+ case IEEE80211_IE_DS_PARAM:
+ if ( dev->channel < dev->nr_channels && ds_channel ==
+ dev->channels[dev->channel].channel_nr )
+ break;
+ ds_channel = ie->ds_param.current_channel;
+ net80211_change_channel ( dev, ds_channel );
+ break;
+
+ case IEEE80211_IE_COUNTRY:
+ dev->nr_channels = 0;
+
+ DBGC ( dev, "802.11 %p setting country regulations "
+ "for %c%c\n", dev, ie->country.name[0],
+ ie->country.name[1] );
+ for ( i = 0; i < ( ie->len - 3 ) / 3; i++ ) {
+ union ieee80211_ie_country_triplet *t =
+ &ie->country.triplet[i];
+ if ( t->first > 200 ) {
+ DBGC ( dev, "802.11 %p ignoring regulatory "
+ "extension information\n", dev );
+ } else {
+ net80211_add_channels ( dev,
+ t->band.first_channel,
+ t->band.nr_channels,
+ t->band.max_txpower );
+ }
+ }
+ net80211_filter_hw_channels ( dev );
+ break;
+
+ case IEEE80211_IE_ERP_INFO:
+ dev->phy_flags &= ~( NET80211_PHY_USE_PROTECTION |
+ NET80211_PHY_USE_SHORT_PREAMBLE );
+ if ( ie->erp_info & IEEE80211_ERP_USE_PROTECTION )
+ dev->phy_flags |= NET80211_PHY_USE_PROTECTION;
+ if ( ! ( ie->erp_info & IEEE80211_ERP_BARKER_LONG ) )
+ dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE;
+ break;
+
+ case IEEE80211_IE_RSN:
+ /* XXX need to implement WPA stuff */
+ break;
+ }
+ }
+
+ if ( have_rates ) {
+ /* Allow only those rates that are also supported by
+ the hardware. */
+ int delta = 0, j;
+
+ dev->rate = 0;
+ for ( i = 0; i < dev->nr_rates; i++ ) {
+ int ok = 0;
+ for ( j = 0; j < dev->hw->nr_rates[band]; j++ ) {
+ if ( dev->hw->rates[band][j] == dev->rates[i] ){
+ ok = 1;
+ break;
+ }
+ }
+
+ if ( ! ok )
+ delta++;
+ else {
+ dev->rates[i - delta] = dev->rates[i];
+ if ( old_rate == dev->rates[i] )
+ dev->rate = i - delta;
+ }
+ }
+
+ dev->nr_rates -= delta;
+
+ /* Sort available rates - sorted subclumps tend to already
+ exist, so insertion sort works well. */
+ for ( i = 1; i < dev->nr_rates; i++ ) {
+ u16 rate = dev->rates[i];
+
+ for ( j = i - 1; j >= 0 && dev->rates[j] >= rate; j-- )
+ dev->rates[j + 1] = dev->rates[j];
+ dev->rates[j + 1] = rate;
+ }
+
+ net80211_set_rtscts_rate ( dev );
+
+ if ( dev->rates[dev->rate] != old_rate )
+ changed |= NET80211_CFG_RATE;
+ }
+
+ if ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE )
+ dev->phy_flags &= ~NET80211_PHY_USE_SHORT_PREAMBLE;
+ if ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT )
+ dev->phy_flags &= ~NET80211_PHY_USE_SHORT_SLOT;
+
+ if ( old_phy != dev->phy_flags )
+ changed |= NET80211_CFG_PHY_PARAMS;
+
+ if ( changed )
+ dev->op->config ( dev, changed );
+
+ return 0;
+}
+
+/**
+ * Create information elements for outgoing probe or association packet
+ *
+ * @v dev 802.11 device
+ * @v ie Pointer to start of information element area
+ * @ret next_ie Pointer to first byte after added information elements
+ */
+static union ieee80211_ie *
+net80211_marshal_request_info ( struct net80211_device *dev,
+ union ieee80211_ie *ie )
+{
+ int i;
+
+ ie->id = IEEE80211_IE_SSID;
+ ie->len = strlen ( dev->essid );
+ memcpy ( ie->ssid, dev->essid, ie->len );
+
+ ie = ieee80211_next_ie ( ie, NULL );
+
+ ie->id = IEEE80211_IE_RATES;
+ ie->len = dev->nr_rates;
+ for ( i = 0; i < ie->len; i++ ) {
+ ie->rates[i] = dev->rates[i] / 5;
+ if ( dev->basic_rates & ( 1 << i ) )
+ ie->rates[i] |= 0x80;
+ }
+
+ if ( ie->len > 8 ) {
+ /* 802.11 requires we use an Extended Basic Rates IE
+ for the rates beyond the eighth. */
+ int rates = ie->len;
+
+ memmove ( ( void * ) ie + 2 + 8 + 2, ( void * ) ie + 2 + 8,
+ rates - 8 );
+ ie->len = 8;
+
+ ie = ieee80211_next_ie ( ie, NULL );
+
+ ie->id = IEEE80211_IE_EXT_RATES;
+ ie->len = rates - 8;
+ }
+
+ ie = ieee80211_next_ie ( ie, NULL );
+
+ return ie;
+}
+
+/** Seconds to wait after finding a network, to possibly find better APs for it
+ *
+ * This is used when a specific SSID to scan for is specified.
+ */
+#define NET80211_PROBE_GATHER 1
+
+/** Seconds to wait after finding a network, to possibly find other networks
+ *
+ * This is used when an empty SSID is specified, to scan for all
+ * networks.
+ */
+#define NET80211_PROBE_GATHER_ALL 2
+
+/** Seconds to allow a probe to take if no network has been found */
+#define NET80211_PROBE_TIMEOUT 6
+
+/**
+ * Begin probe of 802.11 networks
+ *
+ * @v dev 802.11 device
+ * @v essid SSID to probe for, or "" to accept any (may not be NULL)
+ * @v active Whether to use active scanning
+ * @ret ctx Probe context
+ *
+ * Active scanning may only be used on channels 1-11 in the 2.4GHz
+ * band, due to gPXE's lack of a complete regulatory database. If
+ * active scanning is used, probe packets will be sent on each
+ * channel; this can allow association with hidden-SSID networks if
+ * the SSID is properly specified.
+ *
+ * A @c NULL return indicates an out-of-memory condition.
+ *
+ * The returned context must be periodically passed to
+ * net80211_probe_step() until that function returns zero.
+ */
+struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev,
+ const char *essid,
+ int active )
+{
+ struct net80211_probe_ctx *ctx = zalloc ( sizeof ( *ctx ) );
+
+ if ( ! ctx )
+ return NULL;
+
+ assert ( dev->netdev->state & NETDEV_OPEN );
+
+ ctx->dev = dev;
+ ctx->old_keep_mgmt = net80211_keep_mgmt ( dev, 1 );
+ ctx->essid = essid;
+ if ( dev->essid != ctx->essid )
+ strcpy ( dev->essid, ctx->essid );
+
+ if ( active ) {
+ struct ieee80211_probe_req *probe_req;
+ union ieee80211_ie *ie;
+
+ ctx->probe = alloc_iob ( 128 );
+ iob_reserve ( ctx->probe, IEEE80211_TYP_FRAME_HEADER_LEN );
+ probe_req = ctx->probe->data;
+
+ ie = net80211_marshal_request_info ( dev,
+ probe_req->info_element );
+ ie->id = IEEE80211_IE_REQUEST;
+ ie->len = 3;
+ ie->request[0] = IEEE80211_IE_COUNTRY;
+ ie->request[1] = IEEE80211_IE_ERP_INFO;
+ ie->request[2] = IEEE80211_IE_RSN;
+
+ ie = ieee80211_next_ie ( ie, NULL );
+
+ iob_put ( ctx->probe, ( void * ) ie - ctx->probe->data );
+ }
+
+ ctx->ticks_start = currticks();
+ ctx->ticks_beacon = 0;
+ ctx->ticks_channel = currticks();
+ ctx->hop_time = ticks_per_sec() / ( active ? 2 : 6 );
+
+ /*
+ * Channels on 2.4GHz overlap, and the most commonly used
+ * are 1, 6, and 11. We'll get a result faster if we check
+ * every 5 channels, but in order to hit all of them the
+ * number of channels must be relatively prime to 5. If it's
+ * not, tweak the hop.
+ */
+ ctx->hop_step = 5;
+ while ( dev->nr_channels % ctx->hop_step == 0 && ctx->hop_step > 1 )
+ ctx->hop_step--;
+
+ ctx->beacons = malloc ( sizeof ( *ctx->beacons ) );
+ INIT_LIST_HEAD ( ctx->beacons );
+
+ dev->channel = 0;
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+
+ return ctx;
+}
+
+/**
+ * Continue probe of 802.11 networks
+ *
+ * @v ctx Probe context returned by net80211_probe_start()
+ * @ret rc Probe status
+ *
+ * The return code will be 0 if the probe is still going on (and this
+ * function should be called again), a positive number if the probe
+ * completed successfully, or a negative error code if the probe
+ * failed for that reason.
+ *
+ * Whether the probe succeeded or failed, you must call
+ * net80211_probe_finish_all() or net80211_probe_finish_best()
+ * (depending on whether you want information on all networks or just
+ * the best-signal one) in order to release the probe context. A
+ * failed probe may still have acquired some valid data.
+ */
+int net80211_probe_step ( struct net80211_probe_ctx *ctx )
+{
+ struct net80211_device *dev = ctx->dev;
+ u32 start_timeout = NET80211_PROBE_TIMEOUT * ticks_per_sec();
+ u32 gather_timeout = ticks_per_sec();
+ u32 now = currticks();
+ struct io_buffer *iob;
+ int signal;
+ int rc;
+ char ssid[IEEE80211_MAX_SSID_LEN + 1];
+
+ gather_timeout *= ( ctx->essid[0] ? NET80211_PROBE_GATHER :
+ NET80211_PROBE_GATHER_ALL );
+
+ /* Time out if necessary */
+ if ( now >= ctx->ticks_start + start_timeout )
+ return list_empty ( ctx->beacons ) ? -ETIMEDOUT : +1;
+
+ if ( ctx->ticks_beacon > 0 && now >= ctx->ticks_start + gather_timeout )
+ return +1;
+
+ /* Change channels if necessary */
+ if ( now >= ctx->ticks_channel + ctx->hop_time ) {
+ dev->channel = ( dev->channel + ctx->hop_step )
+ % dev->nr_channels;
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+ udelay ( dev->hw->channel_change_time );
+
+ ctx->ticks_channel = now;
+
+ if ( ctx->probe ) {
+ struct io_buffer *siob = ctx->probe; /* to send */
+
+ /* make a copy for future use */
+ iob = alloc_iob ( siob->tail - siob->head );
+ iob_reserve ( iob, iob_headroom ( siob ) );
+ memcpy ( iob_put ( iob, iob_len ( siob ) ),
+ siob->data, iob_len ( siob ) );
+
+ ctx->probe = iob;
+ rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ,
+ net80211_ll_broadcast,
+ iob_disown ( siob ) );
+ if ( rc ) {
+ DBGC ( dev, "802.11 %p send probe failed: "
+ "%s\n", dev, strerror ( rc ) );
+ return rc;
+ }
+ }
+ }
+
+ /* Check for new management packets */
+ while ( ( iob = net80211_mgmt_dequeue ( dev, &signal ) ) != NULL ) {
+ struct ieee80211_frame *hdr;
+ struct ieee80211_beacon *beacon;
+ union ieee80211_ie *ie;
+ struct net80211_wlan *wlan;
+ u16 type;
+
+ hdr = iob->data;
+ type = hdr->fc & IEEE80211_FC_SUBTYPE;
+ beacon = ( struct ieee80211_beacon * ) hdr->data;
+
+ if ( type != IEEE80211_STYPE_BEACON &&
+ type != IEEE80211_STYPE_PROBE_RESP ) {
+ DBGC2 ( dev, "802.11 %p probe: non-beacon\n", dev );
+ goto drop;
+ }
+
+ if ( ( void * ) beacon->info_element >= iob->tail ) {
+ DBGC ( dev, "802.11 %p probe: beacon with no IEs\n",
+ dev );
+ goto drop;
+ }
+
+ ie = beacon->info_element;
+ while ( ie && ie->id != IEEE80211_IE_SSID )
+ ie = ieee80211_next_ie ( ie, iob->tail );
+
+ if ( ! ie ) {
+ DBGC ( dev, "802.11 %p probe: beacon with no SSID\n",
+ dev );
+ goto drop;
+ }
+
+ memcpy ( ssid, ie->ssid, ie->len );
+ ssid[ie->len] = 0;
+
+ if ( ctx->essid[0] && strcmp ( ctx->essid, ssid ) != 0 ) {
+ DBGC2 ( dev, "802.11 %p probe: beacon with wrong SSID "
+ "(%s)\n", dev, ssid );
+ goto drop;
+ }
+
+ /* See if we've got an entry for this network */
+ list_for_each_entry ( wlan, ctx->beacons, list ) {
+ if ( strcmp ( wlan->essid, ssid ) != 0 )
+ continue;
+
+ if ( signal < wlan->signal ) {
+ DBGC2 ( dev, "802.11 %p probe: beacon for %s "
+ "(%s) with weaker signal %d\n", dev,
+ ssid, eth_ntoa ( hdr->addr3 ), signal );
+ goto drop;
+ }
+
+ goto fill;
+ }
+
+ /* No entry yet - make one */
+ wlan = zalloc ( sizeof ( *wlan ) );
+ strcpy ( wlan->essid, ssid );
+ list_add_tail ( &wlan->list, ctx->beacons );
+
+ /* Whether we're using an old entry or a new one, fill
+ it with new data. */
+ fill:
+ memcpy ( wlan->bssid, hdr->addr3, ETH_ALEN );
+ wlan->signal = signal;
+ wlan->channel = dev->channels[dev->channel].channel_nr;
+
+ /* Copy this I/O buffer into a new wlan->beacon; the
+ * iob we've got probably came from the device driver
+ * and may have the full 2.4k allocation, which we
+ * don't want to keep around wasting memory.
+ */
+ free_iob ( wlan->beacon );
+ wlan->beacon = alloc_iob ( iob_len ( iob ) );
+ memcpy ( iob_put ( wlan->beacon, iob_len ( iob ) ),
+ iob->data, iob_len ( iob ) );
+
+ /* XXX actually check capab and RSN ie to
+ figure this out */
+ wlan->handshaking = NET80211_SECPROT_NONE;
+ wlan->crypto = NET80211_CRYPT_NONE;
+
+ ctx->ticks_beacon = now;
+
+ DBGC2 ( dev, "802.11 %p probe: good beacon for %s (%s)\n",
+ dev, wlan->essid, eth_ntoa ( wlan->bssid ) );
+
+ drop:
+ free_iob ( iob );
+ }
+
+ return 0;
+}
+
+
+/**
+ * Finish probe of 802.11 networks, returning best-signal network found
+ *
+ * @v ctx Probe context
+ * @ret wlan Best-signal network found, or @c NULL if none were found
+ *
+ * If net80211_probe_start() was called with a particular SSID
+ * parameter as filter, only a network with that SSID (matching
+ * case-sensitively) can be returned from this function.
+ */
+struct net80211_wlan *
+net80211_probe_finish_best ( struct net80211_probe_ctx *ctx )
+{
+ struct net80211_wlan *best = NULL, *wlan;
+
+ if ( ! ctx )
+ return NULL;
+
+ list_for_each_entry ( wlan, ctx->beacons, list ) {
+ if ( ! best || best->signal < wlan->signal )
+ best = wlan;
+ }
+
+ if ( best )
+ list_del ( &best->list );
+ else
+ DBGC ( ctx->dev, "802.11 %p probe: found nothing for '%s'\n",
+ ctx->dev, ctx->essid );
+
+ net80211_free_wlanlist ( ctx->beacons );
+
+ net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt );
+
+ if ( ctx->probe )
+ free_iob ( ctx->probe );
+
+ free ( ctx );
+
+ return best;
+}
+
+
+/**
+ * Finish probe of 802.11 networks, returning all networks found
+ *
+ * @v ctx Probe context
+ * @ret list List of net80211_wlan detailing networks found
+ *
+ * If net80211_probe_start() was called with a particular SSID
+ * parameter as filter, this will always return either an empty or a
+ * one-element list.
+ */
+struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx )
+{
+ struct list_head *beacons = ctx->beacons;
+
+ if ( ! ctx )
+ return NULL;
+
+ net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt );
+
+ if ( ctx->probe )
+ free_iob ( ctx->probe );
+
+ free ( ctx );
+
+ return beacons;
+}
+
+
+/**
+ * Free WLAN structure
+ *
+ * @v wlan WLAN structure to free
+ */
+void net80211_free_wlan ( struct net80211_wlan *wlan )
+{
+ if ( wlan ) {
+ free_iob ( wlan->beacon );
+ free ( wlan );
+ }
+}
+
+
+/**
+ * Free list of WLAN structures
+ *
+ * @v list List of WLAN structures to free
+ */
+void net80211_free_wlanlist ( struct list_head *list )
+{
+ struct net80211_wlan *wlan, *tmp;
+
+ if ( ! list )
+ return;
+
+ list_for_each_entry_safe ( wlan, tmp, list, list ) {
+ list_del ( &wlan->list );
+ net80211_free_wlan ( wlan );
+ }
+
+ free ( list );
+}
+
+
+/** Number of ticks to wait for replies to association management frames */
+#define ASSOC_TIMEOUT TICKS_PER_SEC
+
+/** Number of times to try sending a particular association management frame */
+#define ASSOC_RETRIES 2
+
+/**
+ * Step 802.11 association process
+ *
+ * @v proc Association process
+ */
+static void net80211_step_associate ( struct process *proc )
+{
+ struct net80211_device *dev =
+ container_of ( proc, struct net80211_device, proc_assoc );
+ int rc = 0;
+ int status = dev->state & NET80211_STATUS_MASK;
+
+ /*
+ * We use a sort of state machine implemented using bits in
+ * the dev->state variable. At each call, we take the
+ * logically first step that has not yet succeeded; either it
+ * has not been tried yet, it's being retried, or it failed.
+ * If it failed, we return an error indication; otherwise we
+ * perform the step. If it succeeds, RX handling code will set
+ * the appropriate status bit for us.
+ *
+ * Probe works a bit differently, since we have to step it
+ * on every call instead of waiting for a packet to arrive
+ * that will set the completion bit for us.
+ */
+
+ /* If we're waiting for a reply, check for timeout condition */
+ if ( dev->state & NET80211_WAITING ) {
+ /* Sanity check */
+ if ( ! dev->associating )
+ return;
+
+ if ( currticks() - dev->ctx.assoc->last_packet > ASSOC_TIMEOUT ) {
+ /* Timed out - fail if too many retries, or retry */
+ dev->ctx.assoc->times_tried++;
+ if ( ++dev->ctx.assoc->times_tried > ASSOC_RETRIES ) {
+ rc = -ETIMEDOUT;
+ goto fail;
+ }
+ } else {
+ /* Didn't time out - let it keep going */
+ return;
+ }
+ } else {
+ if ( dev->state & NET80211_PROBED )
+ dev->ctx.assoc->times_tried = 0;
+ }
+
+ if ( ! ( dev->state & NET80211_PROBED ) ) {
+ /* state: probe */
+
+ if ( ! dev->ctx.probe ) {
+ /* start probe */
+ int active = fetch_intz_setting ( NULL,
+ &net80211_active_setting );
+ int band = dev->hw->bands;
+
+ if ( active )
+ band &= ~NET80211_BAND_BIT_5GHZ;
+
+ rc = net80211_prepare_probe ( dev, band, active );
+ if ( rc )
+ goto fail;
+
+ dev->ctx.probe = net80211_probe_start ( dev, dev->essid,
+ active );
+ if ( ! dev->ctx.probe ) {
+ dev->assoc_rc = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ rc = net80211_probe_step ( dev->ctx.probe );
+ if ( ! rc ) {
+ return; /* still going */
+ }
+
+ dev->associating = net80211_probe_finish_best ( dev->ctx.probe );
+ dev->ctx.probe = NULL;
+ if ( ! dev->associating ) {
+ if ( rc > 0 ) /* "successful" probe found nothing */
+ rc = -ETIMEDOUT;
+ goto fail;
+ }
+
+ /* If we probed using a broadcast SSID, record that
+ fact for the settings applicator before we clobber
+ it with the specific SSID we've chosen. */
+ if ( ! dev->essid[0] )
+ dev->state |= NET80211_AUTO_SSID;
+
+ DBGC ( dev, "802.11 %p found network %s (%s)\n", dev,
+ dev->associating->essid,
+ eth_ntoa ( dev->associating->bssid ) );
+
+ dev->ctx.assoc = zalloc ( sizeof ( *dev->ctx.assoc ) );
+ if ( ! dev->ctx.assoc ) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ dev->state |= NET80211_PROBED;
+ dev->ctx.assoc->method = IEEE80211_AUTH_OPEN_SYSTEM;
+
+ return;
+ }
+
+ /* Record time of sending the packet we're about to send, for timeout */
+ dev->ctx.assoc->last_packet = currticks();
+
+ if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) {
+ /* state: prepare and authenticate */
+
+ if ( status != IEEE80211_STATUS_SUCCESS ) {
+ /* we tried authenticating already, but failed */
+ int method = dev->ctx.assoc->method;
+
+ if ( method == IEEE80211_AUTH_OPEN_SYSTEM &&
+ ( status == IEEE80211_STATUS_AUTH_CHALL_INVALID ||
+ status == IEEE80211_STATUS_AUTH_ALGO_UNSUPP ) ) {
+ /* Maybe this network uses Shared Key? */
+ dev->ctx.assoc->method =
+ IEEE80211_AUTH_SHARED_KEY;
+ } else {
+ goto fail;
+ }
+ }
+
+ DBGC ( dev, "802.11 %p authenticating with method %d\n", dev,
+ dev->ctx.assoc->method );
+
+ rc = net80211_prepare_assoc ( dev, dev->associating );
+ if ( rc )
+ goto fail;
+
+ rc = net80211_send_auth ( dev, dev->associating,
+ dev->ctx.assoc->method );
+ if ( rc )
+ goto fail;
+
+ return;
+ }
+
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) ) {
+ /* state: associate */
+
+ if ( status != IEEE80211_STATUS_SUCCESS )
+ goto fail;
+
+ DBGC ( dev, "802.11 %p associating\n", dev );
+
+ rc = net80211_send_assoc ( dev, dev->associating );
+ if ( rc )
+ goto fail;
+
+ return;
+ }
+
+ if ( ! ( dev->state & NET80211_CRYPTO_SYNCED ) ) {
+ /* state: crypto sync */
+ DBGC ( dev, "802.11 %p security handshaking\n", dev );
+
+ dev->state |= NET80211_CRYPTO_SYNCED;
+ /* XXX need to actually do something here once we
+ support WPA */
+ return;
+ }
+
+ /* state: done! */
+ netdev_link_up ( dev->netdev );
+ dev->assoc_rc = 0;
+ dev->state &= ~NET80211_WORKING;
+
+ free ( dev->ctx.assoc );
+ dev->ctx.assoc = NULL;
+
+ net80211_free_wlan ( dev->associating );
+ dev->associating = NULL;
+
+ dev->rctl = rc80211_init ( dev );
+
+ process_del ( proc );
+
+ DBGC ( dev, "802.11 %p associated with %s (%s)\n", dev,
+ dev->essid, eth_ntoa ( dev->bssid ) );
+
+ return;
+
+ fail:
+ dev->state &= ~( NET80211_WORKING | NET80211_WAITING );
+ if ( rc )
+ dev->assoc_rc = rc;
+
+ netdev_link_err ( dev->netdev, dev->assoc_rc );
+
+ /* We never reach here from the middle of a probe, so we don't
+ need to worry about freeing dev->ctx.probe. */
+
+ if ( dev->state & NET80211_PROBED ) {
+ free ( dev->ctx.assoc );
+ dev->ctx.assoc = NULL;
+ }
+
+ net80211_free_wlan ( dev->associating );
+ dev->associating = NULL;
+
+ process_del ( proc );
+
+ DBGC ( dev, "802.11 %p association failed (state=%04x): "
+ "%s\n", dev, dev->state, strerror ( dev->assoc_rc ) );
+
+ /* Try it again: */
+ net80211_autoassociate ( dev );
+}
+
+/**
+ * Check for 802.11 SSID updates
+ *
+ * This acts as a settings applicator; if the user changes netX/ssid,
+ * and netX is currently open, the association task will be invoked
+ * again.
+ */
+static int net80211_check_ssid_update ( void )
+{
+ struct net80211_device *dev;
+ char ssid[IEEE80211_MAX_SSID_LEN + 1];
+
+ list_for_each_entry ( dev, &net80211_devices, list ) {
+ if ( ! ( dev->netdev->state & NETDEV_OPEN ) )
+ continue;
+
+ fetch_string_setting ( netdev_settings ( dev->netdev ),
+ &net80211_ssid_setting, ssid,
+ IEEE80211_MAX_SSID_LEN + 1 );
+
+ if ( strcmp ( ssid, dev->essid ) != 0 &&
+ ! ( ! ssid[0] && ( dev->state & NET80211_AUTO_SSID ) ) ) {
+ DBGC ( dev, "802.11 %p updating association: "
+ "%s -> %s\n", dev, dev->essid, ssid );
+ net80211_autoassociate ( dev );
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Start 802.11 association process
+ *
+ * @v dev 802.11 device
+ *
+ * If the association process is running, it will be restarted.
+ */
+void net80211_autoassociate ( struct net80211_device *dev )
+{
+ if ( ! ( dev->state & NET80211_WORKING ) ) {
+ DBGC2 ( dev, "802.11 %p spawning association process\n", dev );
+ process_add ( &dev->proc_assoc );
+ }
+
+ /* Clean up everything an earlier association process might
+ have been in the middle of using */
+ if ( dev->associating )
+ net80211_free_wlan ( dev->associating );
+
+ if ( ! ( dev->state & NET80211_PROBED ) )
+ net80211_free_wlan (
+ net80211_probe_finish_best ( dev->ctx.probe ) );
+ else
+ free ( dev->ctx.assoc );
+
+ /* Reset to a clean state */
+ fetch_string_setting ( netdev_settings ( dev->netdev ),
+ &net80211_ssid_setting, dev->essid,
+ IEEE80211_MAX_SSID_LEN + 1 );
+ dev->ctx.probe = NULL;
+ dev->associating = NULL;
+ net80211_set_state ( dev, NET80211_PROBED, NET80211_WORKING, 0 );
+}
+
+/**
+ * Pick TX rate for RTS/CTS packets based on data rate
+ *
+ * @v dev 802.11 device
+ *
+ * The RTS/CTS rate is the fastest TX rate marked as "basic" that is
+ * not faster than the data rate.
+ */
+static void net80211_set_rtscts_rate ( struct net80211_device *dev )
+{
+ u16 datarate = dev->rates[dev->rate];
+ u16 rtsrate = 0;
+ int rts_idx = -1;
+ int i;
+
+ for ( i = 0; i < dev->nr_rates; i++ ) {
+ u16 rate = dev->rates[i];
+
+ if ( ! ( dev->basic_rates & ( 1 << i ) ) || rate > datarate )
+ continue;
+
+ if ( rate > rtsrate ) {
+ rtsrate = rate;
+ rts_idx = i;
+ }
+ }
+
+ /* If this is in initialization, we might not have any basic
+ rates; just use the first data rate in that case. */
+ if ( rts_idx < 0 )
+ rts_idx = 0;
+
+ dev->rtscts_rate = rts_idx;
+}
+
+/**
+ * Set data transmission rate for 802.11 device
+ *
+ * @v dev 802.11 device
+ * @v rate Rate to set, as index into @c dev->rates array
+ */
+void net80211_set_rate_idx ( struct net80211_device *dev, int rate )
+{
+ assert ( dev->netdev->state & NETDEV_OPEN );
+
+ if ( rate >= 0 && rate < dev->nr_rates && rate != dev->rate ) {
+ DBGC2 ( dev, "802.11 %p changing rate from %d->%d Mbps\n",
+ dev, dev->rates[dev->rate] / 10,
+ dev->rates[rate] / 10 );
+
+ dev->rate = rate;
+ net80211_set_rtscts_rate ( dev );
+ dev->op->config ( dev, NET80211_CFG_RATE );
+ }
+}
+
+/**
+ * Configure 802.11 device to transmit on a certain channel
+ *
+ * @v dev 802.11 device
+ * @v channel Channel number (1-11 for 2.4GHz) to transmit on
+ */
+int net80211_change_channel ( struct net80211_device *dev, int channel )
+{
+ int i, oldchan = dev->channel;
+
+ assert ( dev->netdev->state & NETDEV_OPEN );
+
+ for ( i = 0; i < dev->nr_channels; i++ ) {
+ if ( dev->channels[i].channel_nr == channel ) {
+ dev->channel = i;
+ break;
+ }
+ }
+
+ if ( i == dev->nr_channels )
+ return -ENOENT;
+
+ if ( i != oldchan )
+ return dev->op->config ( dev, NET80211_CFG_CHANNEL );
+
+ return 0;
+}
+
+/**
+ * Prepare 802.11 device channel and rate set for scanning
+ *
+ * @v dev 802.11 device
+ * @v band RF band(s) on which to prepare for scanning
+ * @v active Whether the scanning will be active
+ * @ret rc Return status code
+ */
+int net80211_prepare_probe ( struct net80211_device *dev, int band,
+ int active )
+{
+ assert ( dev->netdev->state & NETDEV_OPEN );
+
+ if ( active && ( band & NET80211_BAND_BIT_5GHZ ) ) {
+ DBGC ( dev, "802.11 %p cannot perform active scanning on "
+ "5GHz band\n", dev );
+ return -EINVAL_ACTIVE_SCAN;
+ }
+
+ if ( band == 0 ) {
+ /* This can happen for a 5GHz-only card with 5GHz
+ scanning masked out by an active request. */
+ DBGC ( dev, "802.11 %p asked to prepare for scanning nothing\n",
+ dev );
+ return -EINVAL_ACTIVE_SCAN;
+ }
+
+ dev->nr_channels = 0;
+
+ if ( active )
+ net80211_add_channels ( dev, 1, 11, NET80211_REG_TXPOWER );
+ else {
+ if ( band & NET80211_BAND_BIT_2GHZ )
+ net80211_add_channels ( dev, 1, 14,
+ NET80211_REG_TXPOWER );
+ if ( band & NET80211_BAND_BIT_5GHZ )
+ net80211_add_channels ( dev, 36, 8,
+ NET80211_REG_TXPOWER );
+ }
+
+ net80211_filter_hw_channels ( dev );
+
+ /* Use channel 1 for now */
+ dev->channel = 0;
+ dev->op->config ( dev, NET80211_CFG_CHANNEL );
+
+ /* Always do active probes at lowest (presumably first) speed */
+ dev->rate = 0;
+ dev->nr_rates = 1;
+ dev->rates[0] = dev->hw->rates[dev->channels[0].band][0];
+ dev->op->config ( dev, NET80211_CFG_RATE );
+
+ return 0;
+}
+
+/**
+ * Prepare 802.11 device channel and rate set for communication
+ *
+ * @v dev 802.11 device
+ * @v wlan WLAN to prepare for communication with
+ * @ret rc Return status code
+ */
+int net80211_prepare_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan )
+{
+ struct ieee80211_frame *hdr = wlan->beacon->data;
+ struct ieee80211_beacon *beacon =
+ ( struct ieee80211_beacon * ) hdr->data;
+ int rc;
+
+ assert ( dev->netdev->state & NETDEV_OPEN );
+
+ net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 );
+ memcpy ( dev->bssid, wlan->bssid, ETH_ALEN );
+ strcpy ( dev->essid, wlan->essid );
+
+ dev->last_beacon_timestamp = beacon->timestamp;
+ dev->tx_beacon_interval = 1024 * beacon->beacon_interval;
+
+ /* XXX do crypto setup here */
+
+ /* Barring an IE that tells us the channel outright, assume
+ the channel we heard this AP best on is the channel it's
+ communicating on. */
+ net80211_change_channel ( dev, wlan->channel );
+
+ rc = net80211_process_capab ( dev, beacon->capability );
+ if ( rc )
+ return rc;
+
+ rc = net80211_process_ie ( dev, beacon->info_element,
+ wlan->beacon->tail );
+ if ( rc )
+ return rc;
+
+ /* Associate at the lowest rate so we know it'll get through */
+ dev->rate = 0;
+ dev->op->config ( dev, NET80211_CFG_RATE );
+
+ return 0;
+}
+
+/**
+ * Send 802.11 initial authentication frame
+ *
+ * @v dev 802.11 device
+ * @v wlan WLAN to authenticate with
+ * @v method Authentication method
+ * @ret rc Return status code
+ *
+ * @a method may be 0 for Open System authentication or 1 for Shared
+ * Key authentication. Open System provides no security in association
+ * whatsoever, relying on encryption for confidentiality, but Shared
+ * Key actively introduces security problems and is very rarely used.
+ */
+int net80211_send_auth ( struct net80211_device *dev,
+ struct net80211_wlan *wlan, int method )
+{
+ struct io_buffer *iob = alloc_iob ( 64 );
+ struct ieee80211_auth *auth;
+
+ net80211_set_state ( dev, 0, NET80211_WAITING, 0 );
+ iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN );
+ auth = iob_put ( iob, sizeof ( *auth ) );
+ auth->algorithm = method;
+ auth->tx_seq = 1;
+ auth->status = 0;
+
+ return net80211_tx_mgmt ( dev, IEEE80211_STYPE_AUTH, wlan->bssid, iob );
+}
+
+/**
+ * Handle receipt of 802.11 authentication frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ *
+ * If the authentication method being used is Shared Key, and the
+ * frame that was received included challenge text, the frame is
+ * encrypted using the cryptographic algorithm currently in effect and
+ * sent back to the AP to complete the authentication.
+ */
+static void net80211_handle_auth ( struct net80211_device *dev,
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_auth *auth =
+ ( struct ieee80211_auth * ) hdr->data;
+
+ if ( auth->tx_seq & 1 ) {
+ DBGC ( dev, "802.11 %p authentication received improperly "
+ "directed frame (seq. %d)\n", dev, auth->tx_seq );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ IEEE80211_STATUS_FAILURE );
+ return;
+ }
+
+ if ( auth->status != IEEE80211_STATUS_SUCCESS ) {
+ DBGC ( dev, "802.11 %p authentication failed: status %d\n",
+ dev, auth->status );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ auth->status );
+ return;
+ }
+
+ if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY && ! dev->crypto ) {
+ DBGC ( dev, "802.11 %p can't perform shared-key authentication "
+ "without a cryptosystem\n", dev );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ IEEE80211_STATUS_FAILURE );
+ return;
+ }
+
+ if ( auth->algorithm == IEEE80211_AUTH_SHARED_KEY &&
+ auth->tx_seq == 2 ) {
+ /* Since the iob we got is going to be freed as soon
+ as we return, we can do some in-place
+ modification. */
+ auth->tx_seq = 3;
+ auth->status = 0;
+
+ memcpy ( hdr->addr2, hdr->addr1, ETH_ALEN );
+ memcpy ( hdr->addr1, hdr->addr3, ETH_ALEN );
+
+ netdev_tx ( dev->netdev,
+ dev->crypto->encrypt ( dev->crypto, iob ) );
+ return;
+ }
+
+ net80211_set_state ( dev, NET80211_WAITING, NET80211_AUTHENTICATED,
+ IEEE80211_STATUS_SUCCESS );
+
+ return;
+}
+
+/**
+ * Send 802.11 association frame
+ *
+ * @v dev 802.11 device
+ * @v wlan WLAN to associate with
+ * @ret rc Return status code
+ */
+int net80211_send_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan )
+{
+ struct io_buffer *iob = alloc_iob ( 128 );
+ struct ieee80211_assoc_req *assoc;
+ union ieee80211_ie *ie;
+
+ net80211_set_state ( dev, 0, NET80211_WAITING, 0 );
+
+ iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN );
+ assoc = iob->data;
+
+ assoc->capability = IEEE80211_CAPAB_MANAGED;
+ if ( ! ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE ) )
+ assoc->capability |= IEEE80211_CAPAB_SHORT_PMBL;
+ if ( ! ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT ) )
+ assoc->capability |= IEEE80211_CAPAB_SHORT_SLOT;
+ if ( wlan->crypto )
+ assoc->capability |= IEEE80211_CAPAB_PRIVACY;
+
+ assoc->listen_interval = 1;
+
+ ie = net80211_marshal_request_info ( dev, assoc->info_element );
+
+ DBGP ( "802.11 %p about to send association request:\n", dev );
+ DBGP_HD ( iob->data, ( void * ) ie - iob->data );
+
+ /* XXX add RSN ie for WPA support */
+
+ iob_put ( iob, ( void * ) ie - iob->data );
+
+ return net80211_tx_mgmt ( dev, IEEE80211_STYPE_ASSOC_REQ,
+ wlan->bssid, iob );
+}
+
+/**
+ * Handle receipt of 802.11 association reply frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ */
+static void net80211_handle_assoc_reply ( struct net80211_device *dev,
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_assoc_resp *assoc =
+ ( struct ieee80211_assoc_resp * ) hdr->data;
+
+ net80211_process_capab ( dev, assoc->capability );
+ net80211_process_ie ( dev, assoc->info_element, iob->tail );
+
+ if ( assoc->status != IEEE80211_STATUS_SUCCESS ) {
+ DBGC ( dev, "802.11 %p association failed: status %d\n",
+ dev, assoc->status );
+ net80211_set_state ( dev, NET80211_WAITING, 0,
+ assoc->status );
+ return;
+ }
+
+ /* ESSID was filled before the association request was sent */
+ memcpy ( dev->bssid, hdr->addr3, ETH_ALEN );
+ dev->aid = assoc->aid;
+
+ net80211_set_state ( dev, NET80211_WAITING, NET80211_ASSOCIATED,
+ IEEE80211_STATUS_SUCCESS );
+}
+
+
+/**
+ * Send 802.11 disassociation frame
+ *
+ * @v dev 802.11 device
+ * @v reason Reason for disassociation
+ * @ret rc Return status code
+ */
+static int net80211_send_disassoc ( struct net80211_device *dev, int reason )
+{
+ struct io_buffer *iob = alloc_iob ( 64 );
+ struct ieee80211_disassoc *disassoc;
+
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) )
+ return -EINVAL;
+
+ net80211_set_state ( dev, NET80211_ASSOCIATED, 0, 0 );
+ iob_reserve ( iob, IEEE80211_TYP_FRAME_HEADER_LEN );
+ disassoc = iob_put ( iob, sizeof ( *disassoc ) );
+ disassoc->reason = reason;
+
+ return net80211_tx_mgmt ( dev, IEEE80211_STYPE_DISASSOC, dev->bssid,
+ iob );
+}
+
+
+/** Smoothing factor (1-7) for link quality calculation */
+#define LQ_SMOOTH 7
+
+/**
+ * Update link quality information based on received beacon
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer containing beacon
+ * @ret rc Return status code
+ */
+static void net80211_update_link_quality ( struct net80211_device *dev,
+ struct io_buffer *iob )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_beacon *beacon;
+ u32 dt, rxi;
+
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) )
+ return;
+
+ beacon = ( struct ieee80211_beacon * ) hdr->data;
+ dt = ( u32 ) ( beacon->timestamp - dev->last_beacon_timestamp );
+ rxi = dev->rx_beacon_interval;
+
+ rxi = ( LQ_SMOOTH * rxi ) + ( ( 8 - LQ_SMOOTH ) * dt );
+ dev->rx_beacon_interval = rxi >> 3;
+
+ dev->last_beacon_timestamp = beacon->timestamp;
+}
+
+
+/**
+ * Handle receipt of 802.11 management frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ * @v signal Signal strength of received frame
+ */
+static void net80211_handle_mgmt ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ struct ieee80211_disassoc *disassoc;
+ u16 stype = hdr->fc & IEEE80211_FC_SUBTYPE;
+ int keep = 0;
+ int is_deauth = ( stype == IEEE80211_STYPE_DEAUTH );
+
+ if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_MGMT ) {
+ free_iob ( iob );
+ return; /* only handle management frames */
+ }
+
+ switch ( stype ) {
+ /* We reconnect on deauthentication and disassociation. */
+ case IEEE80211_STYPE_DEAUTH:
+ case IEEE80211_STYPE_DISASSOC:
+ disassoc = ( struct ieee80211_disassoc * ) hdr->data;
+ net80211_set_state ( dev, is_deauth ? NET80211_AUTHENTICATED :
+ NET80211_ASSOCIATED, 0,
+ NET80211_IS_REASON | disassoc->reason );
+ DBGC ( dev, "802.11 %p %s: reason %d\n",
+ dev, is_deauth ? "deauthenticated" : "disassociated",
+ disassoc->reason );
+
+ /* Try to reassociate, in case it's transient. */
+ net80211_autoassociate ( dev );
+
+ break;
+
+ /* We handle authentication and association. */
+ case IEEE80211_STYPE_AUTH:
+ if ( ! ( dev->state & NET80211_AUTHENTICATED ) )
+ net80211_handle_auth ( dev, iob );
+ break;
+
+ case IEEE80211_STYPE_ASSOC_RESP:
+ case IEEE80211_STYPE_REASSOC_RESP:
+ if ( ! ( dev->state & NET80211_ASSOCIATED ) )
+ net80211_handle_assoc_reply ( dev, iob );
+ break;
+
+ /* We pass probes and beacons onto network scanning
+ code. Pass actions for future extensibility. */
+ case IEEE80211_STYPE_BEACON:
+ net80211_update_link_quality ( dev, iob );
+ /* fall through */
+ case IEEE80211_STYPE_PROBE_RESP:
+ case IEEE80211_STYPE_ACTION:
+ if ( dev->keep_mgmt ) {
+ struct net80211_rx_info *rxinf;
+ rxinf = zalloc ( sizeof ( *rxinf ) );
+ if ( ! rxinf ) {
+ DBGC ( dev, "802.11 %p out of memory\n", dev );
+ break;
+ }
+ rxinf->signal = signal;
+ list_add_tail ( &iob->list, &dev->mgmt_queue );
+ list_add_tail ( &rxinf->list, &dev->mgmt_info_queue );
+ keep = 1;
+ }
+ break;
+
+ case IEEE80211_STYPE_PROBE_REQ:
+ /* Some nodes send these broadcast. Ignore them. */
+ break;
+
+ case IEEE80211_STYPE_ASSOC_REQ:
+ case IEEE80211_STYPE_REASSOC_REQ:
+ /* We should never receive these, only send them. */
+ DBGC ( dev, "802.11 %p received strange management request "
+ "(%04x)\n", dev, stype );
+ break;
+
+ default:
+ DBGC ( dev, "802.11 %p received unimplemented management "
+ "packet (%04x)\n", dev, stype );
+ break;
+ }
+
+ if ( ! keep )
+ free_iob ( iob );
+}
+
+/* ---------- Packet handling functions ---------- */
+
+/**
+ * Free buffers used by 802.11 fragment cache entry
+ *
+ * @v dev 802.11 device
+ * @v fcid Fragment cache entry index
+ *
+ * After this function, the referenced entry will be marked unused.
+ */
+static void net80211_free_frags ( struct net80211_device *dev, int fcid )
+{
+ int j;
+ struct net80211_frag_cache *frag = &dev->frags[fcid];
+
+ for ( j = 0; j < 16; j++ ) {
+ if ( frag->iob[j] ) {
+ free_iob ( frag->iob[j] );
+ frag->iob[j] = NULL;
+ }
+ }
+
+ frag->seqnr = 0;
+ frag->start_ticks = 0;
+ frag->in_use = 0;
+}
+
+/**
+ * Accumulate 802.11 fragments into one I/O buffer
+ *
+ * @v dev 802.11 device
+ * @v fcid Fragment cache entry index
+ * @v nfrags Number of fragments received
+ * @v size Sum of sizes of all fragments, including headers
+ * @ret iob I/O buffer containing reassembled packet
+ *
+ * This function does not free the fragment buffers.
+ */
+static struct io_buffer *net80211_accum_frags ( struct net80211_device *dev,
+ int fcid, int nfrags, int size )
+{
+ struct net80211_frag_cache *frag = &dev->frags[fcid];
+ int hdrsize = IEEE80211_TYP_FRAME_HEADER_LEN;
+ int nsize = size - hdrsize * ( nfrags - 1 );
+ int i;
+
+ struct io_buffer *niob = alloc_iob ( nsize );
+ struct ieee80211_frame *hdr;
+
+ /* Add the header from the first one... */
+ memcpy ( iob_put ( niob, hdrsize ), frag->iob[0]->data, hdrsize );
+
+ /* ... and all the data from all of them. */
+ for ( i = 0; i < nfrags; i++ ) {
+ int len = iob_len ( frag->iob[i] ) - hdrsize;
+ memcpy ( iob_put ( niob, len ),
+ frag->iob[i]->data + hdrsize, len );
+ }
+
+ /* Turn off the fragment bit. */
+ hdr = niob->data;
+ hdr->fc &= ~IEEE80211_FC_MORE_FRAG;
+
+ return niob;
+}
+
+/**
+ * Handle receipt of 802.11 fragment
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer containing fragment
+ * @v signal Signal strength with which fragment was received
+ */
+static void net80211_rx_frag ( struct net80211_device *dev,
+ struct io_buffer *iob, int signal )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ int fragnr = IEEE80211_FRAG ( hdr->seq );
+
+ if ( fragnr == 0 && ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
+ /* start a frag cache entry */
+ int i, newest = -1;
+ u32 curr_ticks = currticks(), newest_ticks = 0;
+ u32 timeout = ticks_per_sec() * NET80211_FRAG_TIMEOUT;
+
+ for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) {
+ if ( dev->frags[i].in_use == 0 )
+ break;
+
+ if ( dev->frags[i].start_ticks + timeout >=
+ curr_ticks ) {
+ net80211_free_frags ( dev, i );
+ break;
+ }
+
+ if ( dev->frags[i].start_ticks > newest_ticks ) {
+ newest = i;
+ newest_ticks = dev->frags[i].start_ticks;
+ }
+ }
+
+ /* If we're being sent more concurrent fragmented
+ packets than we can handle, drop the newest so the
+ older ones have time to complete. */
+ if ( i == NET80211_NR_CONCURRENT_FRAGS ) {
+ i = newest;
+ net80211_free_frags ( dev, i );
+ }
+
+ dev->frags[i].in_use = 1;
+ dev->frags[i].seqnr = IEEE80211_SEQNR ( hdr->seq );
+ dev->frags[i].start_ticks = currticks();
+ dev->frags[i].iob[0] = iob;
+ return;
+ } else {
+ int i;
+ for ( i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++ ) {
+ if ( dev->frags[i].in_use && dev->frags[i].seqnr ==
+ IEEE80211_SEQNR ( hdr->seq ) )
+ break;
+ }
+ if ( i == NET80211_NR_CONCURRENT_FRAGS ) {
+ /* Drop non-first not-in-cache fragments */
+ DBGC ( dev, "802.11 %p dropped fragment fc=%04x "
+ "seq=%04x\n", dev, hdr->fc, hdr->seq );
+ free_iob ( iob );
+ return;
+ }
+
+ dev->frags[i].iob[fragnr] = iob;
+
+ if ( ! ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
+ int j, size = 0;
+ for ( j = 0; j < fragnr; j++ ) {
+ size += iob_len ( dev->frags[i].iob[j] );
+ if ( dev->frags[i].iob[j] == NULL )
+ break;
+ }
+ if ( j == fragnr ) {
+ /* We've got everything */
+ struct io_buffer *niob =
+ net80211_accum_frags ( dev, i, fragnr,
+ size );
+ net80211_free_frags ( dev, i );
+ net80211_rx ( dev, niob, signal, 0 );
+ } else {
+ DBGC ( dev, "802.11 %p dropping fragmented "
+ "packet due to out-of-order arrival, "
+ "fc=%04x seq=%04x\n", dev, hdr->fc,
+ hdr->seq );
+ net80211_free_frags ( dev, i );
+ }
+ }
+ }
+}
+
+/**
+ * Handle receipt of 802.11 frame
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer
+ * @v signal Received signal strength
+ * @v rate Bitrate at which frame was received, in 100 kbps units
+ *
+ * If the rate or signal is unknown, 0 should be passed.
+ */
+void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
+ int signal, u16 rate )
+{
+ struct ieee80211_frame *hdr = iob->data;
+ u16 type = hdr->fc & IEEE80211_FC_TYPE;
+ if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION )
+ goto drop; /* drop invalid-version packets */
+
+ if ( type == IEEE80211_TYPE_CTRL )
+ goto drop; /* we don't handle control packets,
+ the hardware does */
+
+ if ( dev->last_rx_seq == hdr->seq )
+ goto drop; /* avoid duplicate packet */
+ dev->last_rx_seq = hdr->seq;
+
+ if ( dev->hw->flags & NET80211_HW_RX_HAS_FCS ) {
+ /* discard the FCS */
+ iob_unput ( iob, 4 );
+ }
+
+ if ( hdr->fc & IEEE80211_FC_PROTECTED ) {
+ struct io_buffer *niob;
+ if ( ! dev->crypto )
+ goto drop; /* can't decrypt packets on an open network */
+
+ niob = dev->crypto->decrypt ( dev->crypto, iob );
+ if ( ! niob )
+ goto drop; /* drop failed decryption */
+ free_iob ( iob );
+ iob = niob;
+ }
+
+ dev->last_signal = signal;
+
+ /* Fragments go into the frag cache or get dropped. */
+ if ( IEEE80211_FRAG ( hdr->seq ) != 0
+ || ( hdr->fc & IEEE80211_FC_MORE_FRAG ) ) {
+ net80211_rx_frag ( dev, iob, signal );
+ return;
+ }
+
+ /* Management frames get handled, enqueued, or dropped. */
+ if ( type == IEEE80211_TYPE_MGMT ) {
+ net80211_handle_mgmt ( dev, iob, signal );
+ return;
+ }
+
+ /* Data frames get dropped or sent to the net_device. */
+ if ( ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA )
+ goto drop; /* drop QoS, CFP, or null data packets */
+
+ /* Update rate-control algorithm */
+ if ( dev->rctl )
+ rc80211_update_rx ( dev, hdr->fc & IEEE80211_FC_RETRY, rate );
+
+ /* Pass packet onward */
+ if ( netdev_link_ok ( dev->netdev ) ) {
+ netdev_rx ( dev->netdev, iob );
+ return;
+ }
+
+ drop:
+ DBGC2 ( dev, "802.11 %p dropped packet fc=%04x seq=%04x\n", dev,
+ hdr->fc, hdr->seq );
+ free_iob ( iob );
+ return;
+}
+
+/** Indicate an error in receiving a packet
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer with received packet, or NULL
+ * @v rc Error code
+ *
+ * This logs the error with the wrapping net_device, and frees iob if
+ * it is passed.
+ */
+void net80211_rx_err ( struct net80211_device *dev,
+ struct io_buffer *iob, int rc )
+{
+ netdev_rx_err ( dev->netdev, iob, rc );
+}
+
+/** Indicate the completed transmission of a packet
+ *
+ * @v dev 802.11 device
+ * @v iob I/O buffer of transmitted packet
+ * @v retries Number of times this packet was retransmitted
+ * @v rc Error code, or 0 for success
+ *
+ * This logs an error with the wrapping net_device if one occurred,
+ * and removes and frees the I/O buffer from its TX queue. The
+ * provided retry information is used to tune our transmission rate.
+ *
+ * If the packet did not need to be retransmitted because it was
+ * properly ACKed the first time, @a retries should be 0.
+ */
+void net80211_tx_complete ( struct net80211_device *dev,
+ struct io_buffer *iob, int retries, int rc )
+{
+ /* Update rate-control algorithm */
+ if ( dev->rctl )
+ rc80211_update_tx ( dev, retries, rc );
+
+ /* Pass completion onward */
+ netdev_tx_complete_err ( dev->netdev, iob, rc );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/80211/rc80211.c b/debian/grub-extras/disabled/gpxe/src/net/80211/rc80211.c
new file mode 100644
index 0000000..5bd1914
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/80211/rc80211.c
@@ -0,0 +1,371 @@
+/*
+ * Simple 802.11 rate-control algorithm for gPXE.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <gpxe/net80211.h>
+
+/**
+ * @file
+ *
+ * Simple 802.11 rate-control algorithm
+ */
+
+/** @page rc80211 Rate control philosophy
+ *
+ * We want to maximize our transmission speed, to the extent that we
+ * can do that without dropping undue numbers of packets. We also
+ * don't want to take up very much code space, so our algorithm has to
+ * be pretty simple
+ *
+ * When we receive a packet, we know what rate it was transmitted at,
+ * and whether it had to be retransmitted to get to us.
+ *
+ * When we send a packet, we hear back how many times it had to be
+ * retried to get through, and whether it got through at all.
+ *
+ * Indications of TX success are more reliable than RX success, but RX
+ * information helps us know where to start.
+ *
+ * To handle all of this, we keep for each rate and each direction (TX
+ * and RX separately) some state information for the most recent
+ * packets on that rate and the number of packets for which we have
+ * information. The state is a 32-bit unsigned integer in which two
+ * bits represent a packet: 11 if it went through well, 10 if it went
+ * through with one retry, 01 if it went through with more than one
+ * retry, or 00 if it didn't go through at all. We define the
+ * "goodness" for a particular (rate, direction) combination as the
+ * sum of all the 2-bit fields, times 33, divided by the number of
+ * 2-bit fields containing valid information (16 except when we're
+ * starting out). The number produced is between 0 and 99; we use -1
+ * for rates with less than 4 RX packets or 1 TX, as an indicator that
+ * we do not have enough information to rely on them.
+ *
+ * In deciding which rates are best, we find the weighted average of
+ * TX and RX goodness, where the weighting is by number of packets
+ * with data and TX packets are worth 4 times as much as RX packets.
+ * The weighted average is called "net goodness" and is also a number
+ * between 0 and 99. If 3 consecutive packets fail transmission
+ * outright, we automatically ratchet down the rate; otherwise, we
+ * switch to the best rate whenever the current rate's goodness falls
+ * below some threshold, and try increasing our rate when the goodness
+ * is very high.
+ *
+ * This system is optimized for gPXE's style of usage. Because normal
+ * operation always involves receiving something, we'll make our way
+ * to the best rate pretty quickly. We tend to follow the lead of the
+ * sending AP in choosing rates, but we won't use rates for long that
+ * don't work well for us in transmission. We assume gPXE won't be
+ * running for long enough that rate patterns will change much, so we
+ * don't have to keep time counters or the like. And if this doesn't
+ * work well in practice there are many ways it could be tweaked.
+ *
+ * To avoid staying at 1Mbps for a long time, we don't track any
+ * transmitted packets until we've set our rate based on received
+ * packets.
+ */
+
+/** Two-bit packet status indicator for a packet with no retries */
+#define RC_PKT_OK 0x3
+
+/** Two-bit packet status indicator for a packet with one retry */
+#define RC_PKT_RETRIED_ONCE 0x2
+
+/** Two-bit packet status indicator for a TX packet with multiple retries
+ *
+ * It is not possible to tell whether an RX packet had one or multiple
+ * retries; we rely instead on the fact that failed RX packets won't
+ * get to us at all, so if we receive a lot of RX packets on a certain
+ * rate it must be pretty good.
+ */
+#define RC_PKT_RETRIED_MULTI 0x1
+
+/** Two-bit packet status indicator for a TX packet that was never ACKed
+ *
+ * It is not possible to tell whether an RX packet was setn if it
+ * didn't get through to us, but if we don't see one we won't increase
+ * the goodness for its rate. This asymmetry is part of why TX packets
+ * are weighted much more heavily than RX.
+ */
+#define RC_PKT_FAILED 0x0
+
+/** Number of times to weight TX packets more heavily than RX packets */
+#define RC_TX_FACTOR 4
+
+/** Number of consecutive failed TX packets that cause an automatic rate drop */
+#define RC_TX_EMERG_FAIL 3
+
+/** Minimum net goodness below which we will search for a better rate */
+#define RC_GOODNESS_MIN 85
+
+/** Maximum net goodness above which we will try to increase our rate */
+#define RC_GOODNESS_MAX 95
+
+/** Minimum (num RX + @c RC_TX_FACTOR * num TX) to use a certain rate */
+#define RC_UNCERTAINTY_THRESH 4
+
+/** TX direction */
+#define TX 0
+
+/** RX direction */
+#define RX 1
+
+/** A rate control context */
+struct rc80211_ctx
+{
+ /** Goodness state for each rate, TX and RX */
+ u32 goodness[2][NET80211_MAX_RATES];
+
+ /** Number of packets recorded for each rate */
+ u8 count[2][NET80211_MAX_RATES];
+
+ /** Indication of whether we've set the device rate yet */
+ int started;
+
+ /** Counter of all packets sent and received */
+ int packets;
+};
+
+/**
+ * Initialize rate-control algorithm
+ *
+ * @v dev 802.11 device
+ * @ret ctx Rate-control context, to be stored in @c dev->rctl
+ */
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev __unused )
+{
+ struct rc80211_ctx *ret = zalloc ( sizeof ( *ret ) );
+ return ret;
+}
+
+/**
+ * Calculate net goodness for a certain rate
+ *
+ * @v ctx Rate-control context
+ * @v rate_idx Index of rate to calculate net goodness for
+ */
+static int rc80211_calc_net_goodness ( struct rc80211_ctx *ctx,
+ int rate_idx )
+{
+ int sum[2], num[2], dir, pkt;
+
+ for ( dir = 0; dir < 2; dir++ ) {
+ u32 good = ctx->goodness[dir][rate_idx];
+
+ num[dir] = ctx->count[dir][rate_idx];
+ sum[dir] = 0;
+
+ for ( pkt = 0; pkt < num[dir]; pkt++ )
+ sum[dir] += ( good >> ( 2 * pkt ) ) & 0x3;
+ }
+
+ if ( ( num[TX] * RC_TX_FACTOR + num[RX] ) < RC_UNCERTAINTY_THRESH )
+ return -1;
+
+ return ( 33 * ( sum[TX] * RC_TX_FACTOR + sum[RX] ) /
+ ( num[TX] * RC_TX_FACTOR + num[RX] ) );
+}
+
+/**
+ * Determine the best rate to switch to and return it
+ *
+ * @v dev 802.11 device
+ * @ret rate_idx Index of the best rate to switch to
+ */
+static int rc80211_pick_best ( struct net80211_device *dev )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+ int best_net_good = 0, best_rate = -1, i;
+
+ for ( i = 0; i < dev->nr_rates; i++ ) {
+ int net_good = rc80211_calc_net_goodness ( ctx, i );
+
+ if ( net_good > best_net_good ||
+ ( best_net_good > RC_GOODNESS_MIN &&
+ net_good > RC_GOODNESS_MIN ) ) {
+ best_net_good = net_good;
+ best_rate = i;
+ }
+ }
+
+ if ( best_rate >= 0 ) {
+ int old_good = rc80211_calc_net_goodness ( ctx, dev->rate );
+ if ( old_good != best_net_good )
+ DBGC ( ctx, "802.11 RC %p switching from goodness "
+ "%d to %d\n", ctx, old_good, best_net_good );
+
+ ctx->started = 1;
+ return best_rate;
+ }
+
+ return dev->rate;
+}
+
+/**
+ * Set 802.11 device rate
+ *
+ * @v dev 802.11 device
+ * @v rate_idx Index of rate to switch to
+ *
+ * This is a thin wrapper around net80211_set_rate_idx to insert a
+ * debugging message where appropriate.
+ */
+static inline void rc80211_set_rate ( struct net80211_device *dev,
+ int rate_idx )
+{
+ DBGC ( dev->rctl, "802.11 RC %p changing rate %d->%d Mbps\n", dev->rctl,
+ dev->rates[dev->rate] / 10, dev->rates[rate_idx] / 10 );
+
+ net80211_set_rate_idx ( dev, rate_idx );
+}
+
+/**
+ * Check rate-control state and change rate if necessary
+ *
+ * @v dev 802.11 device
+ */
+static void rc80211_maybe_set_new ( struct net80211_device *dev )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+ int net_good;
+
+ net_good = rc80211_calc_net_goodness ( ctx, dev->rate );
+
+ if ( ! ctx->started ) {
+ rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
+ return;
+ }
+
+ if ( net_good < 0 ) /* insufficient data */
+ return;
+
+ if ( net_good > RC_GOODNESS_MAX && dev->rate + 1 < dev->nr_rates ) {
+ int higher = rc80211_calc_net_goodness ( ctx, dev->rate + 1 );
+ if ( higher > net_good || higher < 0 )
+ rc80211_set_rate ( dev, dev->rate + 1 );
+ else
+ rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
+ }
+
+ if ( net_good < RC_GOODNESS_MIN ) {
+ rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
+ }
+}
+
+/**
+ * Update rate-control state
+ *
+ * @v dev 802.11 device
+ * @v direction One of the direction constants TX or RX
+ * @v rate_idx Index of rate at which packet was sent or received
+ * @v retries Number of times packet was retried before success
+ * @v failed If nonzero, the packet failed to get through
+ */
+static void rc80211_update ( struct net80211_device *dev, int direction,
+ int rate_idx, int retries, int failed )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+ u32 goodness = ctx->goodness[direction][rate_idx];
+
+ if ( ctx->count[direction][rate_idx] < 16 )
+ ctx->count[direction][rate_idx]++;
+
+ goodness <<= 2;
+ if ( failed )
+ goodness |= RC_PKT_FAILED;
+ else if ( retries > 1 )
+ goodness |= RC_PKT_RETRIED_MULTI;
+ else if ( retries )
+ goodness |= RC_PKT_RETRIED_ONCE;
+ else
+ goodness |= RC_PKT_OK;
+
+ ctx->goodness[direction][rate_idx] = goodness;
+
+ ctx->packets++;
+
+ rc80211_maybe_set_new ( dev );
+}
+
+/**
+ * Update rate-control state for transmitted packet
+ *
+ * @v dev 802.11 device
+ * @v retries Number of times packet was transmitted before success
+ * @v rc Return status code for transmission
+ */
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc )
+{
+ struct rc80211_ctx *ctx = dev->rctl;
+
+ if ( ! ctx->started )
+ return;
+
+ rc80211_update ( dev, TX, dev->rate, retries, rc );
+
+ /* Check if the last RC_TX_EMERG_FAIL packets have all failed */
+ if ( ! ( ctx->goodness[TX][dev->rate] &
+ ( ( 1 << ( 2 * RC_TX_EMERG_FAIL ) ) - 1 ) ) ) {
+ if ( dev->rate == 0 )
+ DBGC ( dev->rctl, "802.11 RC %p saw %d consecutive "
+ "failed TX, but cannot lower rate any further\n",
+ dev->rctl, RC_TX_EMERG_FAIL );
+ else {
+ DBGC ( dev->rctl, "802.11 RC %p lowering rate (%d->%d "
+ "Mbps) due to %d consecutive TX failures\n",
+ dev->rctl, dev->rates[dev->rate] / 10,
+ dev->rates[dev->rate - 1] / 10,
+ RC_TX_EMERG_FAIL );
+
+ rc80211_set_rate ( dev, dev->rate - 1 );
+ }
+ }
+}
+
+/**
+ * Update rate-control state for received packet
+ *
+ * @v dev 802.11 device
+ * @v retry Whether the received packet had been retransmitted
+ * @v rate Rate at which packet was received, in 100 kbps units
+ */
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate )
+{
+ int ridx;
+
+ for ( ridx = 0; ridx < dev->nr_rates && dev->rates[ridx] != rate;
+ ridx++ )
+ ;
+ if ( ridx >= dev->nr_rates )
+ return; /* couldn't find the rate */
+
+ rc80211_update ( dev, RX, ridx, retry, 0 );
+}
+
+/**
+ * Free rate-control context
+ *
+ * @v ctx Rate-control context
+ */
+void rc80211_free ( struct rc80211_ctx *ctx )
+{
+ free ( ctx );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/aoe.c b/debian/grub-extras/disabled/gpxe/src/net/aoe.c
new file mode 100644
index 0000000..839a875
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/aoe.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <gpxe/list.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/ata.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/process.h>
+#include <gpxe/features.h>
+#include <gpxe/aoe.h>
+
+/** @file
+ *
+ * AoE protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
+
+struct net_protocol aoe_protocol;
+
+/** List of all AoE sessions */
+static LIST_HEAD ( aoe_sessions );
+
+static void aoe_free ( struct refcnt *refcnt ) {
+ struct aoe_session *aoe =
+ container_of ( refcnt, struct aoe_session, refcnt );
+
+ netdev_put ( aoe->netdev );
+ free ( aoe );
+}
+
+/**
+ * Mark current AoE command complete
+ *
+ * @v aoe AoE session
+ * @v rc Return status code
+ */
+static void aoe_done ( struct aoe_session *aoe, int rc ) {
+
+ /* Record overall command status */
+ if ( aoe->command ) {
+ aoe->command->cb.cmd_stat = aoe->status;
+ aoe->command->rc = rc;
+ aoe->command = NULL;
+ }
+
+ /* Stop retransmission timer */
+ stop_timer ( &aoe->timer );
+
+ /* Mark operation as complete */
+ aoe->rc = rc;
+}
+
+/**
+ * Send AoE command
+ *
+ * @v aoe AoE session
+ * @ret rc Return status code
+ *
+ * This transmits an AoE command packet. It does not wait for a
+ * response.
+ */
+static int aoe_send_command ( struct aoe_session *aoe ) {
+ struct ata_command *command = aoe->command;
+ struct io_buffer *iobuf;
+ struct aoehdr *aoehdr;
+ union aoecmd *aoecmd;
+ struct aoeata *aoeata;
+ unsigned int count;
+ unsigned int data_out_len;
+ unsigned int aoecmdlen;
+
+ /* Fail immediately if we have no netdev to send on */
+ if ( ! aoe->netdev ) {
+ aoe_done ( aoe, -ENETUNREACH );
+ return -ENETUNREACH;
+ }
+
+ /* If we are transmitting anything that requires a response,
+ * start the retransmission timer. Do this before attempting
+ * to allocate the I/O buffer, in case allocation itself
+ * fails.
+ */
+ start_timer ( &aoe->timer );
+
+ /* Calculate count and data_out_len for this subcommand */
+ switch ( aoe->aoe_cmd_type ) {
+ case AOE_CMD_ATA:
+ count = command->cb.count.native;
+ if ( count > AOE_MAX_COUNT )
+ count = AOE_MAX_COUNT;
+ data_out_len = ( command->data_out ?
+ ( count * ATA_SECTOR_SIZE ) : 0 );
+ aoecmdlen = sizeof ( aoecmd->ata );
+ break;
+ case AOE_CMD_CONFIG:
+ count = 0;
+ data_out_len = 0;
+ aoecmdlen = sizeof ( aoecmd->cfg );
+ break;
+ default:
+ return -ENOTSUP;
+ }
+
+ /* Create outgoing I/O buffer */
+ iobuf = alloc_iob ( ETH_HLEN + sizeof ( *aoehdr ) +
+ aoecmdlen + data_out_len );
+
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, ETH_HLEN );
+ aoehdr = iob_put ( iobuf, sizeof ( *aoehdr ) );
+ aoecmd = iob_put ( iobuf, aoecmdlen );
+ memset ( aoehdr, 0, ( sizeof ( *aoehdr ) + aoecmdlen ) );
+
+ /* Fill AoE header */
+ aoehdr->ver_flags = AOE_VERSION;
+ aoehdr->major = htons ( aoe->major );
+ aoehdr->minor = aoe->minor;
+ aoehdr->command = aoe->aoe_cmd_type;
+ aoehdr->tag = htonl ( ++aoe->tag );
+
+ /* Fill AoE payload */
+ switch ( aoe->aoe_cmd_type ) {
+ case AOE_CMD_ATA:
+ /* Fill AoE command */
+ aoeata = &aoecmd->ata;
+ linker_assert ( AOE_FL_DEV_HEAD == ATA_DEV_SLAVE,
+ __fix_ata_h__ );
+ aoeata->aflags = ( ( command->cb.lba48 ? AOE_FL_EXTENDED : 0 )|
+ ( command->cb.device & ATA_DEV_SLAVE ) |
+ ( data_out_len ? AOE_FL_WRITE : 0 ) );
+ aoeata->err_feat = command->cb.err_feat.bytes.cur;
+ aoeata->count = count;
+ aoeata->cmd_stat = command->cb.cmd_stat;
+ aoeata->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
+ if ( ! command->cb.lba48 )
+ aoeata->lba.bytes[3] |=
+ ( command->cb.device & ATA_DEV_MASK );
+
+ /* Fill data payload */
+ copy_from_user ( iob_put ( iobuf, data_out_len ),
+ command->data_out, aoe->command_offset,
+ data_out_len );
+ break;
+ case AOE_CMD_CONFIG:
+ /* Nothing to do */
+ break;
+ default:
+ assert ( 0 );
+ }
+
+ /* Send packet */
+ return net_tx ( iobuf, aoe->netdev, &aoe_protocol, aoe->target );
+}
+
+/**
+ * Handle AoE retry timer expiry
+ *
+ * @v timer AoE retry timer
+ * @v fail Failure indicator
+ */
+static void aoe_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct aoe_session *aoe =
+ container_of ( timer, struct aoe_session, timer );
+
+ if ( fail ) {
+ aoe_done ( aoe, -ETIMEDOUT );
+ } else {
+ aoe_send_command ( aoe );
+ }
+}
+
+/**
+ * Handle AoE configuration command response
+ *
+ * @v aoe AoE session
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ */
+static int aoe_rx_cfg ( struct aoe_session *aoe, const void *ll_source ) {
+
+ /* Record target MAC address */
+ memcpy ( aoe->target, ll_source, sizeof ( aoe->target ) );
+ DBGC ( aoe, "AoE %p target MAC address %s\n",
+ aoe, eth_ntoa ( aoe->target ) );
+
+ /* Mark config request as complete */
+ aoe_done ( aoe, 0 );
+
+ return 0;
+}
+
+/**
+ * Handle AoE ATA command response
+ *
+ * @v aoe AoE session
+ * @v aoeata AoE ATA command
+ * @v len Length of AoE ATA command
+ * @ret rc Return status code
+ */
+static int aoe_rx_ata ( struct aoe_session *aoe, struct aoeata *aoeata,
+ size_t len ) {
+ struct ata_command *command = aoe->command;
+ unsigned int rx_data_len;
+ unsigned int count;
+ unsigned int data_len;
+
+ /* Sanity check */
+ if ( len < sizeof ( *aoeata ) ) {
+ /* Ignore packet; allow timer to trigger retransmit */
+ return -EINVAL;
+ }
+ rx_data_len = ( len - sizeof ( *aoeata ) );
+
+ /* Calculate count and data_len for this subcommand */
+ count = command->cb.count.native;
+ if ( count > AOE_MAX_COUNT )
+ count = AOE_MAX_COUNT;
+ data_len = count * ATA_SECTOR_SIZE;
+
+ /* Merge into overall ATA status */
+ aoe->status |= aoeata->cmd_stat;
+
+ /* Copy data payload */
+ if ( command->data_in ) {
+ if ( rx_data_len > data_len )
+ rx_data_len = data_len;
+ copy_to_user ( command->data_in, aoe->command_offset,
+ aoeata->data, rx_data_len );
+ }
+
+ /* Update ATA command and offset */
+ aoe->command_offset += data_len;
+ command->cb.lba.native += count;
+ command->cb.count.native -= count;
+
+ /* Check for operation complete */
+ if ( ! command->cb.count.native ) {
+ aoe_done ( aoe, 0 );
+ return 0;
+ }
+
+ /* Transmit next portion of request */
+ stop_timer ( &aoe->timer );
+ aoe_send_command ( aoe );
+
+ return 0;
+}
+
+/**
+ * Process incoming AoE packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ *
+ */
+static int aoe_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev __unused,
+ const void *ll_source ) {
+ struct aoehdr *aoehdr = iobuf->data;
+ struct aoe_session *aoe;
+ int rc = 0;
+
+ /* Sanity checks */
+ if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
+ rc = -EPROTONOSUPPORT;
+ goto done;
+ }
+ if ( ! ( aoehdr->ver_flags & AOE_FL_RESPONSE ) ) {
+ /* Ignore AoE requests that we happen to see */
+ goto done;
+ }
+ iob_pull ( iobuf, sizeof ( *aoehdr ) );
+
+ /* Demultiplex amongst active AoE sessions */
+ list_for_each_entry ( aoe, &aoe_sessions, list ) {
+ if ( ntohs ( aoehdr->major ) != aoe->major )
+ continue;
+ if ( aoehdr->minor != aoe->minor )
+ continue;
+ if ( ntohl ( aoehdr->tag ) != aoe->tag )
+ continue;
+ if ( aoehdr->ver_flags & AOE_FL_ERROR ) {
+ aoe_done ( aoe, -EIO );
+ break;
+ }
+ switch ( aoehdr->command ) {
+ case AOE_CMD_ATA:
+ rc = aoe_rx_ata ( aoe, iobuf->data, iob_len ( iobuf ));
+ break;
+ case AOE_CMD_CONFIG:
+ rc = aoe_rx_cfg ( aoe, ll_source );
+ break;
+ default:
+ DBGC ( aoe, "AoE %p ignoring command %02x\n",
+ aoe, aoehdr->command );
+ break;
+ }
+ break;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** AoE protocol */
+struct net_protocol aoe_protocol __net_protocol = {
+ .name = "AoE",
+ .net_proto = htons ( ETH_P_AOE ),
+ .rx = aoe_rx,
+};
+
+/**
+ * Issue ATA command via an open AoE session
+ *
+ * @v ata ATA device
+ * @v command ATA command
+ * @ret rc Return status code
+ */
+static int aoe_command ( struct ata_device *ata,
+ struct ata_command *command ) {
+ struct aoe_session *aoe =
+ container_of ( ata->backend, struct aoe_session, refcnt );
+
+ aoe->command = command;
+ aoe->status = 0;
+ aoe->command_offset = 0;
+ aoe->aoe_cmd_type = AOE_CMD_ATA;
+
+ aoe_send_command ( aoe );
+
+ return 0;
+}
+
+/**
+ * Issue AoE config query for AoE target discovery
+ *
+ * @v aoe AoE session
+ * @ret rc Return status code
+ */
+static int aoe_discover ( struct aoe_session *aoe ) {
+ int rc;
+
+ aoe->status = 0;
+ aoe->aoe_cmd_type = AOE_CMD_CONFIG;
+ aoe->command = NULL;
+
+ aoe_send_command ( aoe );
+
+ aoe->rc = -EINPROGRESS;
+ while ( aoe->rc == -EINPROGRESS )
+ step();
+ rc = aoe->rc;
+
+ return rc;
+}
+
+static int aoe_detached_command ( struct ata_device *ata __unused,
+ struct ata_command *command __unused ) {
+ return -ENODEV;
+}
+
+void aoe_detach ( struct ata_device *ata ) {
+ struct aoe_session *aoe =
+ container_of ( ata->backend, struct aoe_session, refcnt );
+
+ stop_timer ( &aoe->timer );
+ ata->command = aoe_detached_command;
+ list_del ( &aoe->list );
+ ref_put ( ata->backend );
+ ata->backend = NULL;
+}
+
+static int aoe_parse_root_path ( struct aoe_session *aoe,
+ const char *root_path ) {
+ char *ptr;
+
+ if ( strncmp ( root_path, "aoe:", 4 ) != 0 )
+ return -EINVAL;
+ ptr = ( ( char * ) root_path + 4 );
+
+ if ( *ptr++ != 'e' )
+ return -EINVAL;
+
+ aoe->major = strtoul ( ptr, &ptr, 10 );
+ if ( *ptr++ != '.' )
+ return -EINVAL;
+
+ aoe->minor = strtoul ( ptr, &ptr, 10 );
+ if ( *ptr )
+ return -EINVAL;
+
+ return 0;
+}
+
+int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
+ const char *root_path ) {
+ struct aoe_session *aoe;
+ int rc;
+
+ /* Allocate and initialise structure */
+ aoe = zalloc ( sizeof ( *aoe ) );
+ if ( ! aoe )
+ return -ENOMEM;
+ aoe->refcnt.free = aoe_free;
+ aoe->netdev = netdev_get ( netdev );
+ memcpy ( aoe->target, netdev->ll_broadcast, sizeof ( aoe->target ) );
+ aoe->tag = AOE_TAG_MAGIC;
+ aoe->timer.expired = aoe_timer_expired;
+
+ /* Parse root path */
+ if ( ( rc = aoe_parse_root_path ( aoe, root_path ) ) != 0 )
+ goto err;
+
+ /* Attach parent interface, transfer reference to connection
+ * list, and return
+ */
+ ata->backend = ref_get ( &aoe->refcnt );
+ ata->command = aoe_command;
+ list_add ( &aoe->list, &aoe_sessions );
+
+ /* Send discovery packet to find the target MAC address.
+ * Ideally, this ought to be done asynchronously, but the
+ * block device interface does not yet support asynchronous
+ * operation.
+ */
+ if ( ( rc = aoe_discover( aoe ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ ref_put ( &aoe->refcnt );
+ return rc;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/arp.c b/debian/grub-extras/disabled/gpxe/src/net/arp.c
new file mode 100644
index 0000000..124a856
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/arp.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/arp.h>
+
+/** @file
+ *
+ * Address Resolution Protocol
+ *
+ * This file implements the address resolution protocol as defined in
+ * RFC826. The implementation is media-independent and
+ * protocol-independent; it is not limited to Ethernet or to IPv4.
+ *
+ */
+
+/** An ARP cache entry */
+struct arp_entry {
+ /** Network-layer protocol */
+ struct net_protocol *net_protocol;
+ /** Link-layer protocol */
+ struct ll_protocol *ll_protocol;
+ /** Network-layer address */
+ uint8_t net_addr[MAX_NET_ADDR_LEN];
+ /** Link-layer address */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+};
+
+/** Number of entries in the ARP cache
+ *
+ * This is a global cache, covering all network interfaces,
+ * network-layer protocols and link-layer protocols.
+ */
+#define NUM_ARP_ENTRIES 4
+
+/** The ARP cache */
+static struct arp_entry arp_table[NUM_ARP_ENTRIES];
+#define arp_table_end &arp_table[NUM_ARP_ENTRIES]
+
+static unsigned int next_new_arp_entry = 0;
+
+struct net_protocol arp_protocol;
+
+/**
+ * Find entry in the ARP cache
+ *
+ * @v ll_protocol Link-layer protocol
+ * @v net_protocol Network-layer protocol
+ * @v net_addr Network-layer address
+ * @ret arp ARP cache entry, or NULL if not found
+ *
+ */
+static struct arp_entry *
+arp_find_entry ( struct ll_protocol *ll_protocol,
+ struct net_protocol *net_protocol,
+ const void *net_addr ) {
+ struct arp_entry *arp;
+
+ for ( arp = arp_table ; arp < arp_table_end ; arp++ ) {
+ if ( ( arp->ll_protocol == ll_protocol ) &&
+ ( arp->net_protocol == net_protocol ) &&
+ ( memcmp ( arp->net_addr, net_addr,
+ net_protocol->net_addr_len ) == 0 ) )
+ return arp;
+ }
+ return NULL;
+}
+
+/**
+ * Look up media-specific link-layer address in the ARP cache
+ *
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v dest_net_addr Destination network-layer address
+ * @v source_net_addr Source network-layer address
+ * @ret dest_ll_addr Destination link layer address
+ * @ret rc Return status code
+ *
+ * This function will use the ARP cache to look up the link-layer
+ * address for the link-layer protocol associated with the network
+ * device and the given network-layer protocol and addresses. If
+ * found, the destination link-layer address will be filled in in @c
+ * dest_ll_addr.
+ *
+ * If no address is found in the ARP cache, an ARP request will be
+ * transmitted on the specified network device and -ENOENT will be
+ * returned.
+ */
+int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol,
+ const void *dest_net_addr, const void *source_net_addr,
+ void *dest_ll_addr ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ const struct arp_entry *arp;
+ struct io_buffer *iobuf;
+ struct arphdr *arphdr;
+ int rc;
+
+ /* Look for existing entry in ARP table */
+ arp = arp_find_entry ( ll_protocol, net_protocol, dest_net_addr );
+ if ( arp ) {
+ DBG ( "ARP cache hit: %s %s => %s %s\n",
+ net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
+ ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
+ memcpy ( dest_ll_addr, arp->ll_addr, ll_protocol->ll_addr_len);
+ return 0;
+ }
+ DBG ( "ARP cache miss: %s %s\n", net_protocol->name,
+ net_protocol->ntoa ( dest_net_addr ) );
+
+ /* Allocate ARP packet */
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) +
+ 2 * ( MAX_LL_ADDR_LEN + MAX_NET_ADDR_LEN ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
+
+ /* Build up ARP request */
+ arphdr = iob_put ( iobuf, sizeof ( *arphdr ) );
+ arphdr->ar_hrd = ll_protocol->ll_proto;
+ arphdr->ar_hln = ll_protocol->ll_addr_len;
+ arphdr->ar_pro = net_protocol->net_proto;
+ arphdr->ar_pln = net_protocol->net_addr_len;
+ arphdr->ar_op = htons ( ARPOP_REQUEST );
+ memcpy ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
+ netdev->ll_addr, ll_protocol->ll_addr_len );
+ memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
+ source_net_addr, net_protocol->net_addr_len );
+ memset ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
+ 0, ll_protocol->ll_addr_len );
+ memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
+ dest_net_addr, net_protocol->net_addr_len );
+
+ /* Transmit ARP request */
+ if ( ( rc = net_tx ( iobuf, netdev, &arp_protocol,
+ netdev->ll_broadcast ) ) != 0 )
+ return rc;
+
+ return -ENOENT;
+}
+
+/**
+ * Identify ARP protocol
+ *
+ * @v net_proto Network-layer protocol, in network-endian order
+ * @ret arp_net_protocol ARP protocol, or NULL
+ *
+ */
+static struct arp_net_protocol * arp_find_protocol ( uint16_t net_proto ) {
+ struct arp_net_protocol *arp_net_protocol;
+
+ for_each_table_entry ( arp_net_protocol, ARP_NET_PROTOCOLS ) {
+ if ( arp_net_protocol->net_protocol->net_proto == net_proto ) {
+ return arp_net_protocol;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Process incoming ARP packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ *
+ * This handles ARP requests and responses as detailed in RFC826. The
+ * method detailed within the RFC is pretty optimised, handling
+ * requests and responses with basically a single code path and
+ * avoiding the need for extraneous ARP requests; read the RFC for
+ * details.
+ */
+static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ const void *ll_source __unused ) {
+ struct arphdr *arphdr = iobuf->data;
+ struct arp_net_protocol *arp_net_protocol;
+ struct net_protocol *net_protocol;
+ struct ll_protocol *ll_protocol;
+ struct arp_entry *arp;
+ int merge = 0;
+
+ /* Identify network-layer and link-layer protocols */
+ arp_net_protocol = arp_find_protocol ( arphdr->ar_pro );
+ if ( ! arp_net_protocol )
+ goto done;
+ net_protocol = arp_net_protocol->net_protocol;
+ ll_protocol = netdev->ll_protocol;
+
+ /* Sanity checks */
+ if ( ( arphdr->ar_hrd != ll_protocol->ll_proto ) ||
+ ( arphdr->ar_hln != ll_protocol->ll_addr_len ) ||
+ ( arphdr->ar_pln != net_protocol->net_addr_len ) )
+ goto done;
+
+ /* See if we have an entry for this sender, and update it if so */
+ arp = arp_find_entry ( ll_protocol, net_protocol,
+ arp_sender_pa ( arphdr ) );
+ if ( arp ) {
+ memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ),
+ arphdr->ar_hln );
+ merge = 1;
+ DBG ( "ARP cache update: %s %s => %s %s\n",
+ net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
+ ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
+ }
+
+ /* See if we own the target protocol address */
+ if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0)
+ goto done;
+
+ /* Create new ARP table entry if necessary */
+ if ( ! merge ) {
+ arp = &arp_table[next_new_arp_entry++ % NUM_ARP_ENTRIES];
+ arp->ll_protocol = ll_protocol;
+ arp->net_protocol = net_protocol;
+ memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ),
+ arphdr->ar_hln );
+ memcpy ( arp->net_addr, arp_sender_pa ( arphdr ),
+ arphdr->ar_pln);
+ DBG ( "ARP cache add: %s %s => %s %s\n",
+ net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
+ ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
+ }
+
+ /* If it's not a request, there's nothing more to do */
+ if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) )
+ goto done;
+
+ /* Change request to a reply */
+ DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name,
+ net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
+ ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
+ arphdr->ar_op = htons ( ARPOP_REPLY );
+ memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
+ arphdr->ar_hln + arphdr->ar_pln );
+ memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
+
+ /* Send reply */
+ net_tx ( iob_disown ( iobuf ), netdev, &arp_protocol,
+ arp_target_ha ( arphdr ) );
+
+ done:
+ free_iob ( iobuf );
+ return 0;
+}
+
+/**
+ * Transcribe ARP address
+ *
+ * @v net_addr ARP address
+ * @ret string "<ARP>"
+ *
+ * This operation is meaningless for the ARP protocol.
+ */
+static const char * arp_ntoa ( const void *net_addr __unused ) {
+ return "<ARP>";
+}
+
+/** ARP protocol */
+struct net_protocol arp_protocol __net_protocol = {
+ .name = "ARP",
+ .net_proto = htons ( ETH_P_ARP ),
+ .rx = arp_rx,
+ .ntoa = arp_ntoa,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/dhcpopts.c b/debian/grub-extras/disabled/gpxe/src/net/dhcpopts.c
new file mode 100644
index 0000000..c1940f1
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/dhcpopts.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/dhcpopts.h>
+
+/** @file
+ *
+ * DHCP options
+ *
+ */
+
+/**
+ * Obtain printable version of a DHCP option tag
+ *
+ * @v tag DHCP option tag
+ * @ret name String representation of the tag
+ *
+ */
+static inline char * dhcp_tag_name ( unsigned int tag ) {
+ static char name[8];
+
+ if ( DHCP_IS_ENCAP_OPT ( tag ) ) {
+ snprintf ( name, sizeof ( name ), "%d.%d",
+ DHCP_ENCAPSULATOR ( tag ),
+ DHCP_ENCAPSULATED ( tag ) );
+ } else {
+ snprintf ( name, sizeof ( name ), "%d", tag );
+ }
+ return name;
+}
+
+/**
+ * Get pointer to DHCP option
+ *
+ * @v options DHCP options block
+ * @v offset Offset within options block
+ * @ret option DHCP option
+ */
+static inline __attribute__ (( always_inline )) struct dhcp_option *
+dhcp_option ( struct dhcp_options *options, unsigned int offset ) {
+ return ( ( struct dhcp_option * ) ( options->data + offset ) );
+}
+
+/**
+ * Get offset of a DHCP option
+ *
+ * @v options DHCP options block
+ * @v option DHCP option
+ * @ret offset Offset within options block
+ */
+static inline __attribute__ (( always_inline )) int
+dhcp_option_offset ( struct dhcp_options *options,
+ struct dhcp_option *option ) {
+ return ( ( ( void * ) option ) - options->data );
+}
+
+/**
+ * Calculate length of any DHCP option
+ *
+ * @v option DHCP option
+ * @ret len Length (including tag and length field)
+ */
+static unsigned int dhcp_option_len ( struct dhcp_option *option ) {
+ if ( ( option->tag == DHCP_END ) || ( option->tag == DHCP_PAD ) ) {
+ return 1;
+ } else {
+ return ( option->len + DHCP_OPTION_HEADER_LEN );
+ }
+}
+
+/**
+ * Find DHCP option within DHCP options block, and its encapsulator (if any)
+ *
+ * @v options DHCP options block
+ * @v tag DHCP option tag to search for
+ * @ret encap_offset Offset of encapsulating DHCP option
+ * @ret offset Offset of DHCP option, or negative error
+ *
+ * Searches for the DHCP option matching the specified tag within the
+ * DHCP option block. Encapsulated options may be searched for by
+ * using DHCP_ENCAP_OPT() to construct the tag value.
+ *
+ * If the option is encapsulated, and @c encapsulator is non-NULL, it
+ * will be filled in with the offset of the encapsulating option.
+ *
+ * This routine is designed to be paranoid. It does not assume that
+ * the option data is well-formatted, and so must guard against flaws
+ * such as options missing a @c DHCP_END terminator, or options whose
+ * length would take them beyond the end of the data block.
+ */
+static int find_dhcp_option_with_encap ( struct dhcp_options *options,
+ unsigned int tag,
+ int *encap_offset ) {
+ unsigned int original_tag __attribute__ (( unused )) = tag;
+ struct dhcp_option *option;
+ int offset = 0;
+ ssize_t remaining = options->len;
+ unsigned int option_len;
+
+ /* Sanity check */
+ if ( tag == DHCP_PAD )
+ return -ENOENT;
+
+ /* Search for option */
+ while ( remaining ) {
+ /* Calculate length of this option. Abort processing
+ * if the length is malformed (i.e. takes us beyond
+ * the end of the data block).
+ */
+ option = dhcp_option ( options, offset );
+ option_len = dhcp_option_len ( option );
+ remaining -= option_len;
+ if ( remaining < 0 )
+ break;
+ /* Check for explicit end marker */
+ if ( option->tag == DHCP_END )
+ break;
+ /* Check for matching tag */
+ if ( option->tag == tag ) {
+ DBGC ( options, "DHCPOPT %p found %s (length %d)\n",
+ options, dhcp_tag_name ( original_tag ),
+ option_len );
+ return offset;
+ }
+ /* Check for start of matching encapsulation block */
+ if ( DHCP_IS_ENCAP_OPT ( tag ) &&
+ ( option->tag == DHCP_ENCAPSULATOR ( tag ) ) ) {
+ if ( encap_offset )
+ *encap_offset = offset;
+ /* Continue search within encapsulated option block */
+ tag = DHCP_ENCAPSULATED ( tag );
+ remaining = option_len;
+ offset += DHCP_OPTION_HEADER_LEN;
+ continue;
+ }
+ offset += option_len;
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * Resize a DHCP option
+ *
+ * @v options DHCP option block
+ * @v offset Offset of option to resize
+ * @v encap_offset Offset of encapsulating offset (or -ve for none)
+ * @v old_len Old length (including header)
+ * @v new_len New length (including header)
+ * @v can_realloc Can reallocate options data if necessary
+ * @ret rc Return status code
+ */
+static int resize_dhcp_option ( struct dhcp_options *options,
+ int offset, int encap_offset,
+ size_t old_len, size_t new_len,
+ int can_realloc ) {
+ struct dhcp_option *encapsulator;
+ struct dhcp_option *option;
+ ssize_t delta = ( new_len - old_len );
+ size_t new_options_len;
+ size_t new_encapsulator_len;
+ void *new_data;
+ void *source;
+ void *dest;
+ void *end;
+
+ /* Check for sufficient space, and update length fields */
+ if ( new_len > DHCP_MAX_LEN ) {
+ DBGC ( options, "DHCPOPT %p overlength option\n", options );
+ return -ENOSPC;
+ }
+ new_options_len = ( options->len + delta );
+ if ( new_options_len > options->max_len ) {
+ /* Reallocate options block if allowed to do so. */
+ if ( can_realloc ) {
+ new_data = realloc ( options->data, new_options_len );
+ if ( ! new_data ) {
+ DBGC ( options, "DHCPOPT %p could not "
+ "reallocate to %zd bytes\n", options,
+ new_options_len );
+ return -ENOMEM;
+ }
+ options->data = new_data;
+ options->max_len = new_options_len;
+ } else {
+ DBGC ( options, "DHCPOPT %p out of space\n", options );
+ return -ENOMEM;
+ }
+ }
+ if ( encap_offset >= 0 ) {
+ encapsulator = dhcp_option ( options, encap_offset );
+ new_encapsulator_len = ( encapsulator->len + delta );
+ if ( new_encapsulator_len > DHCP_MAX_LEN ) {
+ DBGC ( options, "DHCPOPT %p overlength encapsulator\n",
+ options );
+ return -ENOSPC;
+ }
+ encapsulator->len = new_encapsulator_len;
+ }
+ options->len = new_options_len;
+
+ /* Move remainder of option data */
+ option = dhcp_option ( options, offset );
+ source = ( ( ( void * ) option ) + old_len );
+ dest = ( ( ( void * ) option ) + new_len );
+ end = ( options->data + options->max_len );
+ memmove ( dest, source, ( end - dest ) );
+
+ return 0;
+}
+
+/**
+ * Set value of DHCP option
+ *
+ * @v options DHCP option block
+ * @v tag DHCP option tag
+ * @v data New value for DHCP option
+ * @v len Length of value, in bytes
+ * @v can_realloc Can reallocate options data if necessary
+ * @ret offset Offset of DHCP option, or negative error
+ *
+ * Sets the value of a DHCP option within the options block. The
+ * option may or may not already exist. Encapsulators will be created
+ * (and deleted) as necessary.
+ *
+ * This call may fail due to insufficient space in the options block.
+ * If it does fail, and the option existed previously, the option will
+ * be left with its original value.
+ */
+static int set_dhcp_option ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len,
+ int can_realloc ) {
+ static const uint8_t empty_encapsulator[] = { DHCP_END };
+ int offset;
+ int encap_offset = -1;
+ int creation_offset = 0;
+ struct dhcp_option *option;
+ unsigned int encap_tag = DHCP_ENCAPSULATOR ( tag );
+ size_t old_len = 0;
+ size_t new_len = ( len ? ( len + DHCP_OPTION_HEADER_LEN ) : 0 );
+ int rc;
+
+ /* Sanity check */
+ if ( tag == DHCP_PAD )
+ return -ENOTTY;
+
+ /* Find old instance of this option, if any */
+ offset = find_dhcp_option_with_encap ( options, tag, &encap_offset );
+ if ( offset >= 0 ) {
+ old_len = dhcp_option_len ( dhcp_option ( options, offset ) );
+ DBGC ( options, "DHCPOPT %p resizing %s from %zd to %zd\n",
+ options, dhcp_tag_name ( tag ), old_len, new_len );
+ } else {
+ DBGC ( options, "DHCPOPT %p creating %s (length %zd)\n",
+ options, dhcp_tag_name ( tag ), new_len );
+ }
+
+ /* Ensure that encapsulator exists, if required */
+ if ( encap_tag ) {
+ if ( encap_offset < 0 )
+ encap_offset = set_dhcp_option ( options, encap_tag,
+ empty_encapsulator, 1,
+ can_realloc );
+ if ( encap_offset < 0 )
+ return encap_offset;
+ creation_offset = ( encap_offset + DHCP_OPTION_HEADER_LEN );
+ }
+
+ /* Create new option if necessary */
+ if ( offset < 0 )
+ offset = creation_offset;
+
+ /* Resize option to fit new data */
+ if ( ( rc = resize_dhcp_option ( options, offset, encap_offset,
+ old_len, new_len,
+ can_realloc ) ) != 0 )
+ return rc;
+
+ /* Copy new data into option, if applicable */
+ if ( len ) {
+ option = dhcp_option ( options, offset );
+ option->tag = tag;
+ option->len = len;
+ memcpy ( &option->data, data, len );
+ }
+
+ /* Delete encapsulator if there's nothing else left in it */
+ if ( encap_offset >= 0 ) {
+ option = dhcp_option ( options, encap_offset );
+ if ( option->len <= 1 )
+ set_dhcp_option ( options, encap_tag, NULL, 0, 0 );
+ }
+
+ return offset;
+}
+
+/**
+ * Store value of DHCP option setting
+ *
+ * @v options DHCP option block
+ * @v tag Setting tag number
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int dhcpopt_store ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len ) {
+ int offset;
+
+ offset = set_dhcp_option ( options, tag, data, len, 0 );
+ if ( offset < 0 )
+ return offset;
+ return 0;
+}
+
+/**
+ * Store value of DHCP option setting, extending options block if necessary
+ *
+ * @v options DHCP option block
+ * @v tag Setting tag number
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int dhcpopt_extensible_store ( struct dhcp_options *options, unsigned int tag,
+ const void *data, size_t len ) {
+ int offset;
+
+ offset = set_dhcp_option ( options, tag, data, len, 1 );
+ if ( offset < 0 )
+ return offset;
+ return 0;
+}
+
+/**
+ * Fetch value of DHCP option setting
+ *
+ * @v options DHCP option block
+ * @v tag Setting tag number
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+int dhcpopt_fetch ( struct dhcp_options *options, unsigned int tag,
+ void *data, size_t len ) {
+ int offset;
+ struct dhcp_option *option;
+ size_t option_len;
+
+ offset = find_dhcp_option_with_encap ( options, tag, NULL );
+ if ( offset < 0 )
+ return offset;
+
+ option = dhcp_option ( options, offset );
+ option_len = option->len;
+ if ( len > option_len )
+ len = option_len;
+ memcpy ( data, option->data, len );
+
+ return option_len;
+}
+
+/**
+ * Recalculate length of DHCP options block
+ *
+ * @v options Uninitialised DHCP option block
+ *
+ * The "used length" field will be updated based on scanning through
+ * the block to find the end of the options.
+ */
+static void dhcpopt_update_len ( struct dhcp_options *options ) {
+ struct dhcp_option *option;
+ int offset = 0;
+ ssize_t remaining = options->max_len;
+ unsigned int option_len;
+
+ /* Find last non-pad option */
+ options->len = 0;
+ while ( remaining ) {
+ option = dhcp_option ( options, offset );
+ option_len = dhcp_option_len ( option );
+ remaining -= option_len;
+ if ( remaining < 0 )
+ break;
+ offset += option_len;
+ if ( option->tag != DHCP_PAD )
+ options->len = offset;
+ }
+}
+
+/**
+ * Initialise prepopulated block of DHCP options
+ *
+ * @v options Uninitialised DHCP option block
+ * @v data Memory for DHCP option data
+ * @v max_len Length of memory for DHCP option data
+ *
+ * The memory content must already be filled with valid DHCP options.
+ * A zeroed block counts as a block of valid DHCP options.
+ */
+void dhcpopt_init ( struct dhcp_options *options, void *data,
+ size_t max_len ) {
+
+ /* Fill in fields */
+ options->data = data;
+ options->max_len = max_len;
+
+ /* Update length */
+ dhcpopt_update_len ( options );
+
+ DBGC ( options, "DHCPOPT %p created (data %p len %#zx max_len %#zx)\n",
+ options, options->data, options->len, options->max_len );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/dhcppkt.c b/debian/grub-extras/disabled/gpxe/src/net/dhcppkt.c
new file mode 100644
index 0000000..20a0e66
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/dhcppkt.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/dhcpopts.h>
+#include <gpxe/dhcppkt.h>
+
+/** @file
+ *
+ * DHCP packets
+ *
+ */
+
+/****************************************************************************
+ *
+ * DHCP packet raw interface
+ *
+ */
+
+/**
+ * Calculate used length of an IPv4 field within a DHCP packet
+ *
+ * @v data Field data
+ * @v len Length of field
+ * @ret used Used length of field
+ */
+static size_t used_len_ipv4 ( const void *data, size_t len __unused ) {
+ const struct in_addr *in = data;
+
+ return ( in->s_addr ? sizeof ( *in ) : 0 );
+}
+
+/**
+ * Calculate used length of a string field within a DHCP packet
+ *
+ * @v data Field data
+ * @v len Length of field
+ * @ret used Used length of field
+ */
+static size_t used_len_string ( const void *data, size_t len ) {
+ return strnlen ( data, len );
+}
+
+/** A dedicated field within a DHCP packet */
+struct dhcp_packet_field {
+ /** Settings tag number */
+ unsigned int tag;
+ /** Offset within DHCP packet */
+ uint16_t offset;
+ /** Length of field */
+ uint16_t len;
+ /** Calculate used length of field
+ *
+ * @v data Field data
+ * @v len Length of field
+ * @ret used Used length of field
+ */
+ size_t ( * used_len ) ( const void *data, size_t len );
+};
+
+/** Declare a dedicated field within a DHCP packet
+ *
+ * @v _tag Settings tag number
+ * @v _field Field name
+ * @v _used_len Function to calculate used length of field
+ */
+#define DHCP_PACKET_FIELD( _tag, _field, _used_len ) { \
+ .tag = (_tag), \
+ .offset = offsetof ( struct dhcphdr, _field ), \
+ .len = sizeof ( ( ( struct dhcphdr * ) 0 )->_field ), \
+ .used_len = _used_len, \
+ }
+
+/** Dedicated fields within a DHCP packet */
+static struct dhcp_packet_field dhcp_packet_fields[] = {
+ DHCP_PACKET_FIELD ( DHCP_EB_YIADDR, yiaddr, used_len_ipv4 ),
+ DHCP_PACKET_FIELD ( DHCP_EB_SIADDR, siaddr, used_len_ipv4 ),
+ DHCP_PACKET_FIELD ( DHCP_TFTP_SERVER_NAME, sname, used_len_string ),
+ DHCP_PACKET_FIELD ( DHCP_BOOTFILE_NAME, file, used_len_string ),
+};
+
+/**
+ * Get address of a DHCP packet field
+ *
+ * @v dhcphdr DHCP packet header
+ * @v field DHCP packet field
+ * @ret data Packet field data
+ */
+static inline void * dhcp_packet_field ( struct dhcphdr *dhcphdr,
+ struct dhcp_packet_field *field ) {
+ return ( ( ( void * ) dhcphdr ) + field->offset );
+}
+
+/**
+ * Find DHCP packet field corresponding to settings tag number
+ *
+ * @v tag Settings tag number
+ * @ret field DHCP packet field, or NULL
+ */
+static struct dhcp_packet_field *
+find_dhcp_packet_field ( unsigned int tag ) {
+ struct dhcp_packet_field *field;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( dhcp_packet_fields ) /
+ sizeof ( dhcp_packet_fields[0] ) ) ; i++ ) {
+ field = &dhcp_packet_fields[i];
+ if ( field->tag == tag )
+ return field;
+ }
+ return NULL;
+}
+
+/**
+ * Store value of DHCP packet setting
+ *
+ * @v dhcppkt DHCP packet
+ * @v tag Setting tag number
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len ) {
+ struct dhcp_packet_field *field;
+ void *field_data;
+ int rc;
+
+ /* If this is a special field, fill it in */
+ if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
+ if ( len > field->len )
+ return -ENOSPC;
+ field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
+ memset ( field_data, 0, field->len );
+ memcpy ( dhcp_packet_field ( dhcppkt->dhcphdr, field ),
+ data, len );
+ /* Erase any equivalent option from the options block */
+ dhcpopt_store ( &dhcppkt->options, tag, NULL, 0 );
+ return 0;
+ }
+
+ /* Otherwise, use the generic options block */
+ rc = dhcpopt_store ( &dhcppkt->options, tag, data, len );
+
+ /* Update our used-length field */
+ dhcppkt->len = ( offsetof ( struct dhcphdr, options ) +
+ dhcppkt->options.len );
+
+ return rc;
+}
+
+/**
+ * Fetch value of DHCP packet setting
+ *
+ * @v dhcppkt DHCP packet
+ * @v tag Setting tag number
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len ) {
+ struct dhcp_packet_field *field;
+ void *field_data;
+ size_t field_len = 0;
+
+ /* Identify special field, if any */
+ if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
+ field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
+ field_len = field->used_len ( field_data, field->len );
+ }
+
+ /* Return special field, if it exists and is populated */
+ if ( field_len ) {
+ if ( len > field_len )
+ len = field_len;
+ memcpy ( data, field_data, len );
+ return field_len;
+ }
+
+ /* Otherwise, use the generic options block */
+ return dhcpopt_fetch ( &dhcppkt->options, tag, data, len );
+}
+
+/****************************************************************************
+ *
+ * DHCP packet settings interface
+ *
+ */
+
+/**
+ * Store value of DHCP setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int dhcppkt_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct dhcp_packet *dhcppkt =
+ container_of ( settings, struct dhcp_packet, settings );
+
+ return dhcppkt_store ( dhcppkt, setting->tag, data, len );
+}
+
+/**
+ * Fetch value of DHCP setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int dhcppkt_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct dhcp_packet *dhcppkt =
+ container_of ( settings, struct dhcp_packet, settings );
+
+ return dhcppkt_fetch ( dhcppkt, setting->tag, data, len );
+}
+
+/** DHCP settings operations */
+static struct settings_operations dhcppkt_settings_operations = {
+ .store = dhcppkt_settings_store,
+ .fetch = dhcppkt_settings_fetch,
+};
+
+/****************************************************************************
+ *
+ * Constructor
+ *
+ */
+
+/**
+ * Initialise DHCP packet
+ *
+ * @v dhcppkt DHCP packet structure to fill in
+ * @v data DHCP packet raw data
+ * @v max_len Length of raw data buffer
+ *
+ * Initialise a DHCP packet structure from a data buffer containing a
+ * DHCP packet.
+ */
+void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct dhcphdr *data,
+ size_t len ) {
+ dhcppkt->dhcphdr = data;
+ dhcppkt->max_len = len;
+ dhcpopt_init ( &dhcppkt->options, &dhcppkt->dhcphdr->options,
+ ( len - offsetof ( struct dhcphdr, options ) ) );
+ dhcppkt->len = ( offsetof ( struct dhcphdr, options ) +
+ dhcppkt->options.len );
+ settings_init ( &dhcppkt->settings,
+ &dhcppkt_settings_operations, &dhcppkt->refcnt,
+ DHCP_SETTINGS_NAME, 0 );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/ethernet.c b/debian/grub-extras/disabled/gpxe/src/net/ethernet.c
new file mode 100644
index 0000000..bf1aec0
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/ethernet.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/in.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/ethernet.h>
+
+/** @file
+ *
+ * Ethernet protocol
+ *
+ */
+
+/** Ethernet broadcast MAC address */
+static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/**
+ * Add Ethernet link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Source link-layer address
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+static int eth_push ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf, const void *ll_dest,
+ const void *ll_source, uint16_t net_proto ) {
+ struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
+
+ /* Build Ethernet header */
+ memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN );
+ memcpy ( ethhdr->h_source, ll_source, ETH_ALEN );
+ ethhdr->h_protocol = net_proto;
+
+ return 0;
+}
+
+/**
+ * Remove Ethernet link-layer header
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret ll_dest Link-layer destination address
+ * @ret ll_source Source link-layer address
+ * @ret net_proto Network-layer protocol, in network-byte order
+ * @ret rc Return status code
+ */
+static int eth_pull ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf, const void **ll_dest,
+ const void **ll_source, uint16_t *net_proto ) {
+ struct ethhdr *ethhdr = iobuf->data;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) {
+ DBG ( "Ethernet packet too short (%zd bytes)\n",
+ iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Strip off Ethernet header */
+ iob_pull ( iobuf, sizeof ( *ethhdr ) );
+
+ /* Fill in required fields */
+ *ll_dest = ethhdr->h_dest;
+ *ll_source = ethhdr->h_source;
+ *net_proto = ethhdr->h_protocol;
+
+ return 0;
+}
+
+/**
+ * Initialise Ethernet address
+ *
+ * @v hw_addr Hardware address
+ * @v ll_addr Link-layer address
+ */
+void eth_init_addr ( const void *hw_addr, void *ll_addr ) {
+ memcpy ( ll_addr, hw_addr, ETH_ALEN );
+}
+
+/**
+ * Transcribe Ethernet address
+ *
+ * @v ll_addr Link-layer address
+ * @ret string Link-layer address in human-readable format
+ */
+const char * eth_ntoa ( const void *ll_addr ) {
+ static char buf[18]; /* "00:00:00:00:00:00" */
+ const uint8_t *eth_addr = ll_addr;
+
+ snprintf ( buf, sizeof (buf), "%02x:%02x:%02x:%02x:%02x:%02x",
+ eth_addr[0], eth_addr[1], eth_addr[2],
+ eth_addr[3], eth_addr[4], eth_addr[5] );
+ return buf;
+}
+
+/**
+ * Hash multicast address
+ *
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
+ */
+int eth_mc_hash ( unsigned int af, const void *net_addr, void *ll_addr ) {
+ const uint8_t *net_addr_bytes = net_addr;
+ uint8_t *ll_addr_bytes = ll_addr;
+
+ switch ( af ) {
+ case AF_INET:
+ ll_addr_bytes[0] = 0x01;
+ ll_addr_bytes[1] = 0x00;
+ ll_addr_bytes[2] = 0x5e;
+ ll_addr_bytes[3] = net_addr_bytes[1] & 0x7f;
+ ll_addr_bytes[4] = net_addr_bytes[2];
+ ll_addr_bytes[5] = net_addr_bytes[3];
+ return 0;
+ default:
+ return -ENOTSUP;
+ }
+}
+
+/** Ethernet protocol */
+struct ll_protocol ethernet_protocol __ll_protocol = {
+ .name = "Ethernet",
+ .ll_proto = htons ( ARPHRD_ETHER ),
+ .hw_addr_len = ETH_ALEN,
+ .ll_addr_len = ETH_ALEN,
+ .ll_header_len = ETH_HLEN,
+ .push = eth_push,
+ .pull = eth_pull,
+ .init_addr = eth_init_addr,
+ .ntoa = eth_ntoa,
+ .mc_hash = eth_mc_hash,
+};
+
+/**
+ * Allocate Ethernet device
+ *
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * alloc_etherdev ( size_t priv_size ) {
+ struct net_device *netdev;
+
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ethernet_protocol;
+ netdev->ll_broadcast = eth_broadcast;
+ netdev->max_pkt_len = ETH_FRAME_LEN;
+ }
+ return netdev;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/fakedhcp.c b/debian/grub-extras/disabled/gpxe/src/net/fakedhcp.c
new file mode 100644
index 0000000..ad3f046
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/fakedhcp.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <gpxe/settings.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/dhcppkt.h>
+#include <gpxe/fakedhcp.h>
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+/**
+ * Copy settings to DHCP packet
+ *
+ * @v dest Destination DHCP packet
+ * @v source Source settings block
+ * @v encapsulator Encapsulating setting tag number, or zero
+ * @ret rc Return status code
+ */
+static int copy_encap_settings ( struct dhcp_packet *dest,
+ struct settings *source,
+ unsigned int encapsulator ) {
+ struct setting setting = { .name = "" };
+ unsigned int subtag;
+ unsigned int tag;
+ int len;
+ int check_len;
+ int rc;
+
+ for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
+ tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
+ switch ( tag ) {
+ case DHCP_EB_ENCAP:
+ case DHCP_VENDOR_ENCAP:
+ /* Process encapsulated settings */
+ if ( ( rc = copy_encap_settings ( dest, source,
+ tag ) ) != 0 )
+ return rc;
+ break;
+ default:
+ /* Copy setting, if present */
+ setting.tag = tag;
+ len = fetch_setting_len ( source, &setting );
+ if ( len < 0 )
+ break;
+ {
+ char buf[len];
+
+ check_len = fetch_setting ( source, &setting,
+ buf, sizeof (buf));
+ assert ( check_len == len );
+ if ( ( rc = dhcppkt_store ( dest, tag, buf,
+ sizeof(buf) )) !=0)
+ return rc;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Copy settings to DHCP packet
+ *
+ * @v dest Destination DHCP packet
+ * @v source Source settings block
+ * @ret rc Return status code
+ */
+static int copy_settings ( struct dhcp_packet *dest,
+ struct settings *source ) {
+ return copy_encap_settings ( dest, source, 0 );
+}
+
+/**
+ * Create fake DHCPDISCOVER packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ struct in_addr ciaddr = { 0 };
+ int rc;
+
+ if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
+ ciaddr, data, max_len ) ) != 0 ) {
+ DBG ( "Could not create DHCPDISCOVER: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create fake DHCPACK packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ int rc;
+
+ /* Create base DHCPACK packet */
+ if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
+ data, max_len ) ) != 0 ) {
+ DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in globally-scoped settings, then netdev-specific
+ * settings. Do it in this order so that netdev-specific
+ * settings take precedence regardless of stated priorities.
+ */
+ if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) {
+ DBG ( "Could not set DHCPACK global settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ if ( ( rc = copy_settings ( &dhcppkt,
+ netdev_settings ( netdev ) ) ) != 0 ) {
+ DBG ( "Could not set DHCPACK netdev settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create fake PXE Boot Server ACK packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakepxebsack ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ struct settings *proxy_settings;
+ struct settings *pxebs_settings;
+ int rc;
+
+ /* Identify available settings */
+ proxy_settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
+ pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
+ if ( ( ! proxy_settings ) && ( ! pxebs_settings ) ) {
+ /* No PXE boot server; return the regular DHCPACK */
+ return create_fakedhcpack ( netdev, data, max_len );
+ }
+
+ /* Create base DHCPACK packet */
+ if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
+ data, max_len ) ) != 0 ) {
+ DBG ( "Could not create PXE BS ACK: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in ProxyDHCP options */
+ if ( proxy_settings &&
+ ( ( rc = copy_settings ( &dhcppkt, proxy_settings ) ) != 0 ) ) {
+ DBG ( "Could not copy ProxyDHCP settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in BootServerDHCP options, if present */
+ if ( pxebs_settings &&
+ ( ( rc = copy_settings ( &dhcppkt, pxebs_settings ) ) != 0 ) ) {
+ DBG ( "Could not copy PXE BS settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/icmp.c b/debian/grub-extras/disabled/gpxe/src/net/icmp.c
new file mode 100644
index 0000000..749c345
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/icmp.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/in.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/icmp.h>
+
+/** @file
+ *
+ * ICMP protocol
+ *
+ */
+
+struct tcpip_protocol icmp_protocol __tcpip_protocol;
+
+/**
+ * Process a received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
+static int icmp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ uint16_t pshdr_csum __unused ) {
+ struct icmp_header *icmp = iobuf->data;
+ size_t len = iob_len ( iobuf );
+ unsigned int csum;
+ int rc;
+
+ /* Sanity check */
+ if ( len < sizeof ( *icmp ) ) {
+ DBG ( "ICMP packet too short at %zd bytes (min %zd bytes)\n",
+ len, sizeof ( *icmp ) );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Verify checksum */
+ csum = tcpip_chksum ( icmp, len );
+ if ( csum != 0 ) {
+ DBG ( "ICMP checksum incorrect (is %04x, should be 0000)\n",
+ csum );
+ DBG_HD ( icmp, len );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* We respond only to pings */
+ if ( icmp->type != ICMP_ECHO_REQUEST ) {
+ DBG ( "ICMP ignoring type %d\n", icmp->type );
+ rc = 0;
+ goto done;
+ }
+
+ DBG ( "ICMP responding to ping\n" );
+
+ /* Change type to response and recalculate checksum */
+ icmp->type = ICMP_ECHO_RESPONSE;
+ icmp->chksum = 0;
+ icmp->chksum = tcpip_chksum ( icmp, len );
+
+ /* Transmit the response */
+ if ( ( rc = tcpip_tx ( iob_disown ( iobuf ), &icmp_protocol, st_dest,
+ st_src, NULL, NULL ) ) != 0 ) {
+ DBG ( "ICMP could not transmit ping response: %s\n",
+ strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** ICMP TCP/IP protocol */
+struct tcpip_protocol icmp_protocol __tcpip_protocol = {
+ .name = "ICMP",
+ .rx = icmp_rx,
+ .tcpip_proto = IP_ICMP,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband.c
new file mode 100644
index 0000000..cd7deae
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband.c
@@ -0,0 +1,923 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/list.h>
+#include <gpxe/if_arp.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/ipoib.h>
+#include <gpxe/process.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_mi.h>
+#include <gpxe/ib_sma.h>
+
+/** @file
+ *
+ * Infiniband protocol
+ *
+ */
+
+/** List of Infiniband devices */
+struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
+
+/** List of open Infiniband devices, in reverse order of opening */
+static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
+
+/***************************************************************************
+ *
+ * Completion queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v num_cqes Number of completion queue entries
+ * @v op Completion queue operations
+ * @ret cq New completion queue
+ */
+struct ib_completion_queue *
+ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
+ struct ib_completion_queue_operations *op ) {
+ struct ib_completion_queue *cq;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
+
+ /* Allocate and initialise data structure */
+ cq = zalloc ( sizeof ( *cq ) );
+ if ( ! cq )
+ goto err_alloc_cq;
+ cq->ibdev = ibdev;
+ list_add ( &cq->list, &ibdev->cqs );
+ cq->num_cqes = num_cqes;
+ INIT_LIST_HEAD ( &cq->work_queues );
+ cq->op = op;
+
+ /* Perform device-specific initialisation and get CQN */
+ if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not initialise completion "
+ "queue: %s\n", ibdev, strerror ( rc ) );
+ goto err_dev_create_cq;
+ }
+
+ DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
+ "with CQN %#lx\n", ibdev, num_cqes, cq,
+ ib_cq_get_drvdata ( cq ), cq->cqn );
+ return cq;
+
+ ibdev->op->destroy_cq ( ibdev, cq );
+ err_dev_create_cq:
+ list_del ( &cq->list );
+ free ( cq );
+ err_alloc_cq:
+ return NULL;
+}
+
+/**
+ * Destroy completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+void ib_destroy_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
+ ibdev, cq->cqn );
+ assert ( list_empty ( &cq->work_queues ) );
+ ibdev->op->destroy_cq ( ibdev, cq );
+ list_del ( &cq->list );
+ free ( cq );
+}
+
+/**
+ * Poll completion queue
+ *
+ * @v ibdev Infiniband device
+ * @v cq Completion queue
+ */
+void ib_poll_cq ( struct ib_device *ibdev,
+ struct ib_completion_queue *cq ) {
+ struct ib_work_queue *wq;
+
+ /* Poll completion queue */
+ ibdev->op->poll_cq ( ibdev, cq );
+
+ /* Refill receive work queues */
+ list_for_each_entry ( wq, &cq->work_queues, list ) {
+ if ( ! wq->is_send )
+ ib_refill_recv ( ibdev, wq->qp );
+ }
+}
+
+/***************************************************************************
+ *
+ * Work queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Create queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v type Queue pair type
+ * @v num_send_wqes Number of send work queue entries
+ * @v send_cq Send completion queue
+ * @v num_recv_wqes Number of receive work queue entries
+ * @v recv_cq Receive completion queue
+ * @ret qp Queue pair
+ *
+ * The queue pair will be left in the INIT state; you must call
+ * ib_modify_qp() before it is ready to use for sending and receiving.
+ */
+struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
+ enum ib_queue_pair_type type,
+ unsigned int num_send_wqes,
+ struct ib_completion_queue *send_cq,
+ unsigned int num_recv_wqes,
+ struct ib_completion_queue *recv_cq ) {
+ struct ib_queue_pair *qp;
+ size_t total_size;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
+
+ /* Allocate and initialise data structure */
+ total_size = ( sizeof ( *qp ) +
+ ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
+ ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
+ qp = zalloc ( total_size );
+ if ( ! qp )
+ goto err_alloc_qp;
+ qp->ibdev = ibdev;
+ list_add ( &qp->list, &ibdev->qps );
+ qp->type = type;
+ qp->send.qp = qp;
+ qp->send.is_send = 1;
+ qp->send.cq = send_cq;
+ list_add ( &qp->send.list, &send_cq->work_queues );
+ qp->send.psn = ( random() & 0xffffffUL );
+ qp->send.num_wqes = num_send_wqes;
+ qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
+ qp->recv.qp = qp;
+ qp->recv.cq = recv_cq;
+ list_add ( &qp->recv.list, &recv_cq->work_queues );
+ qp->recv.psn = ( random() & 0xffffffUL );
+ qp->recv.num_wqes = num_recv_wqes;
+ qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
+ ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
+ INIT_LIST_HEAD ( &qp->mgids );
+
+ /* Perform device-specific initialisation and get QPN */
+ if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
+ "%s\n", ibdev, strerror ( rc ) );
+ goto err_dev_create_qp;
+ }
+ DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
+ ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
+ DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
+ ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
+ qp->recv.iobufs );
+ DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
+ ibdev, qp->qpn, num_recv_wqes, qp->recv.iobufs,
+ ( ( ( void * ) qp ) + total_size ) );
+
+ /* Calculate externally-visible QPN */
+ switch ( type ) {
+ case IB_QPT_SMI:
+ qp->ext_qpn = IB_QPN_SMI;
+ break;
+ case IB_QPT_GSI:
+ qp->ext_qpn = IB_QPN_GSI;
+ break;
+ default:
+ qp->ext_qpn = qp->qpn;
+ break;
+ }
+ if ( qp->ext_qpn != qp->qpn ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx has external QPN %#lx\n",
+ ibdev, qp->qpn, qp->ext_qpn );
+ }
+
+ return qp;
+
+ ibdev->op->destroy_qp ( ibdev, qp );
+ err_dev_create_qp:
+ list_del ( &qp->send.list );
+ list_del ( &qp->recv.list );
+ list_del ( &qp->list );
+ free ( qp );
+ err_alloc_qp:
+ return NULL;
+}
+
+/**
+ * Modify queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av New address vector, if applicable
+ * @ret rc Return status code
+ */
+int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p modifying QPN %#lx\n", ibdev, qp->qpn );
+
+ if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not modify QPN %#lx: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Destroy queue pair
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
+ struct io_buffer *iobuf;
+ unsigned int i;
+
+ DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
+ ibdev, qp->qpn );
+
+ assert ( list_empty ( &qp->mgids ) );
+
+ /* Perform device-specific destruction */
+ ibdev->op->destroy_qp ( ibdev, qp );
+
+ /* Complete any remaining I/O buffers with errors */
+ for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
+ if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
+ ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
+ }
+ for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
+ if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
+ ib_complete_recv ( ibdev, qp, NULL, iobuf,
+ -ECANCELED );
+ }
+ }
+
+ /* Remove work queues from completion queue */
+ list_del ( &qp->send.list );
+ list_del ( &qp->recv.list );
+
+ /* Free QP */
+ list_del ( &qp->list );
+ free ( qp );
+}
+
+/**
+ * Find queue pair by QPN
+ *
+ * @v ibdev Infiniband device
+ * @v qpn Queue pair number
+ * @ret qp Queue pair, or NULL
+ */
+struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
+ unsigned long qpn ) {
+ struct ib_queue_pair *qp;
+
+ list_for_each_entry ( qp, &ibdev->qps, list ) {
+ if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
+ return qp;
+ }
+ return NULL;
+}
+
+/**
+ * Find queue pair by multicast GID
+ *
+ * @v ibdev Infiniband device
+ * @v gid Multicast GID
+ * @ret qp Queue pair, or NULL
+ */
+struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
+ struct ib_gid *gid ) {
+ struct ib_queue_pair *qp;
+ struct ib_multicast_gid *mgid;
+
+ list_for_each_entry ( qp, &ibdev->qps, list ) {
+ list_for_each_entry ( mgid, &qp->mgids, list ) {
+ if ( memcmp ( &mgid->gid, gid,
+ sizeof ( mgid->gid ) ) == 0 ) {
+ return qp;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Find work queue belonging to completion queue
+ *
+ * @v cq Completion queue
+ * @v qpn Queue pair number
+ * @v is_send Find send work queue (rather than receive)
+ * @ret wq Work queue, or NULL if not found
+ */
+struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
+ unsigned long qpn, int is_send ) {
+ struct ib_work_queue *wq;
+
+ list_for_each_entry ( wq, &cq->work_queues, list ) {
+ if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
+ return wq;
+ }
+ return NULL;
+}
+
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
+ struct ib_address_vector av_copy;
+ int rc;
+
+ /* Check queue fill level */
+ if ( qp->send.fill >= qp->send.num_wqes ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
+ ibdev, qp->qpn );
+ return -ENOBUFS;
+ }
+
+ /* Use default address vector if none specified */
+ if ( ! av )
+ av = &qp->av;
+
+ /* Make modifiable copy of address vector */
+ memcpy ( &av_copy, av, sizeof ( av_copy ) );
+ av = &av_copy;
+
+ /* Fill in optional parameters in address vector */
+ if ( ! av->qkey )
+ av->qkey = qp->qkey;
+ if ( ! av->rate )
+ av->rate = IB_RATE_2_5;
+
+ /* Post to hardware */
+ if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ qp->send.fill++;
+ return 0;
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ int rc;
+
+ /* Check packet length */
+ if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx wrong RX buffer size (%zd)\n",
+ ibdev, qp->qpn, iob_tailroom ( iobuf ) );
+ return -EINVAL;
+ }
+
+ /* Check queue fill level */
+ if ( qp->recv.fill >= qp->recv.num_wqes ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
+ ibdev, qp->qpn );
+ return -ENOBUFS;
+ }
+
+ /* Post to hardware */
+ if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ qp->recv.fill++;
+ return 0;
+}
+
+/**
+ * Complete send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+
+ if ( qp->send.cq->op->complete_send ) {
+ qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ free_iob ( iobuf );
+ }
+ qp->send.fill--;
+}
+
+/**
+ * Complete receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+
+ if ( qp->recv.cq->op->complete_recv ) {
+ qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc );
+ } else {
+ free_iob ( iobuf );
+ }
+ qp->recv.fill--;
+}
+
+/**
+ * Refill receive work queue
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ */
+void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
+ struct io_buffer *iobuf;
+ int rc;
+
+ /* Keep filling while unfilled entries remain */
+ while ( qp->recv.fill < qp->recv.num_wqes ) {
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE );
+ if ( ! iobuf ) {
+ /* Non-fatal; we will refill on next attempt */
+ return;
+ }
+
+ /* Post I/O buffer */
+ if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
+ ibdev, strerror ( rc ) );
+ free_iob ( iobuf );
+ /* Give up */
+ return;
+ }
+ }
+}
+
+/***************************************************************************
+ *
+ * Link control
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Open port
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+int ib_open ( struct ib_device *ibdev ) {
+ int rc;
+
+ /* Increment device open request counter */
+ if ( ibdev->open_count++ > 0 ) {
+ /* Device was already open; do nothing */
+ return 0;
+ }
+
+ /* Create subnet management interface */
+ ibdev->smi = ib_create_mi ( ibdev, IB_QPT_SMI );
+ if ( ! ibdev->smi ) {
+ DBGC ( ibdev, "IBDEV %p could not create SMI\n", ibdev );
+ rc = -ENOMEM;
+ goto err_create_smi;
+ }
+
+ /* Create subnet management agent */
+ if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not create SMA: %s\n",
+ ibdev, strerror ( rc ) );
+ goto err_create_sma;
+ }
+
+ /* Create general services interface */
+ ibdev->gsi = ib_create_mi ( ibdev, IB_QPT_GSI );
+ if ( ! ibdev->gsi ) {
+ DBGC ( ibdev, "IBDEV %p could not create GSI\n", ibdev );
+ rc = -ENOMEM;
+ goto err_create_gsi;
+ }
+
+ /* Open device */
+ if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not open: %s\n",
+ ibdev, strerror ( rc ) );
+ goto err_open;
+ }
+
+ /* Add to head of open devices list */
+ list_add ( &ibdev->open_list, &open_ib_devices );
+
+ assert ( ibdev->open_count == 1 );
+ return 0;
+
+ ibdev->op->close ( ibdev );
+ err_open:
+ ib_destroy_mi ( ibdev, ibdev->gsi );
+ err_create_gsi:
+ ib_destroy_sma ( ibdev, ibdev->smi );
+ err_create_sma:
+ ib_destroy_mi ( ibdev, ibdev->smi );
+ err_create_smi:
+ assert ( ibdev->open_count == 1 );
+ ibdev->open_count = 0;
+ return rc;
+}
+
+/**
+ * Close port
+ *
+ * @v ibdev Infiniband device
+ */
+void ib_close ( struct ib_device *ibdev ) {
+
+ /* Decrement device open request counter */
+ ibdev->open_count--;
+
+ /* Close device if this was the last remaining requested opening */
+ if ( ibdev->open_count == 0 ) {
+ list_del ( &ibdev->open_list );
+ ib_destroy_mi ( ibdev, ibdev->gsi );
+ ib_destroy_sma ( ibdev, ibdev->smi );
+ ib_destroy_mi ( ibdev, ibdev->smi );
+ ibdev->op->close ( ibdev );
+ }
+}
+
+/***************************************************************************
+ *
+ * Multicast
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Attach to multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ * @ret rc Return status code
+ *
+ * Note that this function handles only the local device's attachment
+ * to the multicast GID; it does not issue the relevant MADs to join
+ * the multicast group on the subnet.
+ */
+int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *gid ) {
+ struct ib_multicast_gid *mgid;
+ int rc;
+
+ /* Add to software multicast GID list */
+ mgid = zalloc ( sizeof ( *mgid ) );
+ if ( ! mgid ) {
+ rc = -ENOMEM;
+ goto err_alloc_mgid;
+ }
+ memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
+ list_add ( &mgid->list, &qp->mgids );
+
+ /* Add to hardware multicast GID list */
+ if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
+ goto err_dev_mcast_attach;
+
+ return 0;
+
+ err_dev_mcast_attach:
+ list_del ( &mgid->list );
+ free ( mgid );
+ err_alloc_mgid:
+ return rc;
+}
+
+/**
+ * Detach from multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v gid Multicast GID
+ */
+void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *gid ) {
+ struct ib_multicast_gid *mgid;
+
+ /* Remove from hardware multicast GID list */
+ ibdev->op->mcast_detach ( ibdev, qp, gid );
+
+ /* Remove from software multicast GID list */
+ list_for_each_entry ( mgid, &qp->mgids, list ) {
+ if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
+ list_del ( &mgid->list );
+ free ( mgid );
+ break;
+ }
+ }
+}
+
+/***************************************************************************
+ *
+ * Miscellaneous
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Get Infiniband HCA information
+ *
+ * @v ibdev Infiniband device
+ * @ret hca_guid HCA GUID
+ * @ret num_ports Number of ports
+ */
+int ib_get_hca_info ( struct ib_device *ibdev,
+ struct ib_gid_half *hca_guid ) {
+ struct ib_device *tmp;
+ int num_ports = 0;
+
+ /* Search for IB devices with the same physical device to
+ * identify port count and a suitable Node GUID.
+ */
+ for_each_ibdev ( tmp ) {
+ if ( tmp->dev != ibdev->dev )
+ continue;
+ if ( num_ports == 0 ) {
+ memcpy ( hca_guid, &tmp->gid.u.half[1],
+ sizeof ( *hca_guid ) );
+ }
+ num_ports++;
+ }
+ return num_ports;
+}
+
+/**
+ * Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set port information MAD
+ */
+int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
+ int rc;
+
+ /* Adapters with embedded SMAs do not need to support this method */
+ if ( ! ibdev->op->set_port_info ) {
+ DBGC ( ibdev, "IBDEV %p does not support setting port "
+ "information\n", ibdev );
+ return -ENOTSUP;
+ }
+
+ if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not set port information: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+};
+
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mad Set partition key table MAD
+ */
+int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) {
+ int rc;
+
+ /* Adapters with embedded SMAs do not need to support this method */
+ if ( ! ibdev->op->set_pkey_table ) {
+ DBGC ( ibdev, "IBDEV %p does not support setting partition "
+ "key table\n", ibdev );
+ return -ENOTSUP;
+ }
+
+ if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not set partition key table: "
+ "%s\n", ibdev, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+};
+
+/***************************************************************************
+ *
+ * Event queues
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Handle Infiniband link state change
+ *
+ * @v ibdev Infiniband device
+ */
+void ib_link_state_changed ( struct ib_device *ibdev ) {
+
+ /* Notify IPoIB of link state change */
+ ipoib_link_state_changed ( ibdev );
+}
+
+/**
+ * Poll event queue
+ *
+ * @v ibdev Infiniband device
+ */
+void ib_poll_eq ( struct ib_device *ibdev ) {
+ struct ib_completion_queue *cq;
+
+ /* Poll device's event queue */
+ ibdev->op->poll_eq ( ibdev );
+
+ /* Poll all completion queues */
+ list_for_each_entry ( cq, &ibdev->cqs, list )
+ ib_poll_cq ( ibdev, cq );
+}
+
+/**
+ * Single-step the Infiniband event queue
+ *
+ * @v process Infiniband event queue process
+ */
+static void ib_step ( struct process *process __unused ) {
+ struct ib_device *ibdev;
+
+ for_each_ibdev ( ibdev )
+ ib_poll_eq ( ibdev );
+}
+
+/** Infiniband event queue process */
+struct process ib_process __permanent_process = {
+ .list = LIST_HEAD_INIT ( ib_process.list ),
+ .step = ib_step,
+};
+
+/***************************************************************************
+ *
+ * Infiniband device creation/destruction
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Allocate Infiniband device
+ *
+ * @v priv_size Size of driver private data area
+ * @ret ibdev Infiniband device, or NULL
+ */
+struct ib_device * alloc_ibdev ( size_t priv_size ) {
+ struct ib_device *ibdev;
+ void *drv_priv;
+ size_t total_len;
+
+ total_len = ( sizeof ( *ibdev ) + priv_size );
+ ibdev = zalloc ( total_len );
+ if ( ibdev ) {
+ drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
+ ib_set_drvdata ( ibdev, drv_priv );
+ INIT_LIST_HEAD ( &ibdev->cqs );
+ INIT_LIST_HEAD ( &ibdev->qps );
+ ibdev->lid = IB_LID_NONE;
+ ibdev->pkey = IB_PKEY_NONE;
+ }
+ return ibdev;
+}
+
+/**
+ * Register Infiniband device
+ *
+ * @v ibdev Infiniband device
+ * @ret rc Return status code
+ */
+int register_ibdev ( struct ib_device *ibdev ) {
+ int rc;
+
+ /* Add to device list */
+ ibdev_get ( ibdev );
+ list_add_tail ( &ibdev->list, &ib_devices );
+
+ /* Add IPoIB device */
+ if ( ( rc = ipoib_probe ( ibdev ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not add IPoIB device: %s\n",
+ ibdev, strerror ( rc ) );
+ goto err_ipoib_probe;
+ }
+
+ DBGC ( ibdev, "IBDEV %p registered (phys %s)\n", ibdev,
+ ibdev->dev->name );
+ return 0;
+
+ err_ipoib_probe:
+ list_del ( &ibdev->list );
+ ibdev_put ( ibdev );
+ return rc;
+}
+
+/**
+ * Unregister Infiniband device
+ *
+ * @v ibdev Infiniband device
+ */
+void unregister_ibdev ( struct ib_device *ibdev ) {
+
+ /* Close device */
+ ipoib_remove ( ibdev );
+
+ /* Remove from device list */
+ list_del ( &ibdev->list );
+ ibdev_put ( ibdev );
+ DBGC ( ibdev, "IBDEV %p unregistered\n", ibdev );
+}
+
+/**
+ * Find Infiniband device by GID
+ *
+ * @v gid GID
+ * @ret ibdev Infiniband device, or NULL
+ */
+struct ib_device * find_ibdev ( struct ib_gid *gid ) {
+ struct ib_device *ibdev;
+
+ for_each_ibdev ( ibdev ) {
+ if ( memcmp ( gid, &ibdev->gid, sizeof ( *gid ) ) == 0 )
+ return ibdev;
+ }
+ return NULL;
+}
+
+/**
+ * Get most recently opened Infiniband device
+ *
+ * @ret ibdev Most recently opened Infiniband device, or NULL
+ */
+struct ib_device * last_opened_ibdev ( void ) {
+ struct ib_device *ibdev;
+
+ list_for_each_entry ( ibdev, &open_ib_devices, open_list ) {
+ assert ( ibdev->open_count != 0 );
+ return ibdev;
+ }
+
+ return NULL;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cm.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cm.c
new file mode 100644
index 0000000..30a3691
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cm.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_mi.h>
+#include <gpxe/ib_pathrec.h>
+#include <gpxe/ib_cm.h>
+
+/**
+ * @file
+ *
+ * Infiniband communication management
+ *
+ */
+
+/** List of connections */
+static LIST_HEAD ( ib_cm_conns );
+
+/**
+ * Send "ready to use" response
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v conn Connection
+ * @v av Address vector
+ * @ret rc Return status code
+ */
+static int ib_cm_send_rtu ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_connection *conn,
+ struct ib_address_vector *av ) {
+ union ib_mad mad;
+ struct ib_cm_ready_to_use *ready =
+ &mad.cm.cm_data.ready_to_use;
+ int rc;
+
+ /* Construct "ready to use" response */
+ memset ( &mad, 0, sizeof ( mad ) );
+ mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
+ mad.hdr.class_version = IB_CM_CLASS_VERSION;
+ mad.hdr.method = IB_MGMT_METHOD_SEND;
+ mad.hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
+ ready->local_id = htonl ( conn->local_id );
+ ready->remote_id = htonl ( conn->remote_id );
+ if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
+ DBGC ( conn, "CM %p could not send RTU: %s\n",
+ conn, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle duplicate connection replies
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ *
+ * If a "ready to use" MAD is lost, the peer may resend the connection
+ * reply. We have to respond to these with duplicate "ready to use"
+ * MADs, otherwise the peer may time out and drop the connection.
+ */
+static void ib_cm_connect_rep ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_cm_connect_reply *connect_rep =
+ &mad->cm.cm_data.connect_reply;
+ struct ib_connection *conn;
+ int rc;
+
+ /* Identify connection */
+ list_for_each_entry ( conn, &ib_cm_conns, list ) {
+ if ( ntohl ( connect_rep->remote_id ) != conn->local_id )
+ continue;
+ /* Try to send "ready to use" reply */
+ if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
+ /* Ignore errors */
+ return;
+ }
+ return;
+ }
+
+ DBG ( "CM unidentified connection %08x\n",
+ ntohl ( connect_rep->remote_id ) );
+}
+
+/** Communication management agents */
+struct ib_mad_agent ib_cm_agent[] __ib_mad_agent = {
+ {
+ .mgmt_class = IB_MGMT_CLASS_CM,
+ .class_version = IB_CM_CLASS_VERSION,
+ .attr_id = htons ( IB_CM_ATTR_CONNECT_REPLY ),
+ .handle = ib_cm_connect_rep,
+ },
+};
+
+/**
+ * Convert connection rejection reason to return status code
+ *
+ * @v reason Rejection reason (in network byte order)
+ * @ret rc Return status code
+ */
+static int ib_cm_rejection_reason_to_rc ( uint16_t reason ) {
+ switch ( reason ) {
+ case htons ( IB_CM_REJECT_BAD_SERVICE_ID ) :
+ return -ENODEV;
+ case htons ( IB_CM_REJECT_STALE_CONN ) :
+ return -EALREADY;
+ case htons ( IB_CM_REJECT_CONSUMER ) :
+ return -ENOTTY;
+ default:
+ return -EPERM;
+ }
+}
+
+/**
+ * Handle connection request transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ */
+static void ib_cm_req_complete ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_connection *conn = ib_madx_get_ownerdata ( madx );
+ struct ib_queue_pair *qp = conn->qp;
+ struct ib_cm_common *common = &mad->cm.cm_data.common;
+ struct ib_cm_connect_reply *connect_rep =
+ &mad->cm.cm_data.connect_reply;
+ struct ib_cm_connect_reject *connect_rej =
+ &mad->cm.cm_data.connect_reject;
+ void *private_data = NULL;
+ size_t private_data_len = 0;
+
+ /* Report failures */
+ if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
+ rc = -EIO;
+ if ( rc != 0 ) {
+ DBGC ( conn, "CM %p connection request failed: %s\n",
+ conn, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Record remote communication ID */
+ conn->remote_id = ntohl ( common->local_id );
+
+ /* Handle response */
+ switch ( mad->hdr.attr_id ) {
+
+ case htons ( IB_CM_ATTR_CONNECT_REPLY ) :
+ /* Extract fields */
+ qp->av.qpn = ( ntohl ( connect_rep->local_qpn ) >> 8 );
+ qp->send.psn = ( ntohl ( connect_rep->starting_psn ) >> 8 );
+ private_data = &connect_rep->private_data;
+ private_data_len = sizeof ( connect_rep->private_data );
+ DBGC ( conn, "CM %p connected to QPN %lx PSN %x\n",
+ conn, qp->av.qpn, qp->send.psn );
+
+ /* Modify queue pair */
+ if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( conn, "CM %p could not modify queue pair: %s\n",
+ conn, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Send "ready to use" reply */
+ if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
+ /* Treat as non-fatal */
+ rc = 0;
+ }
+ break;
+
+ case htons ( IB_CM_ATTR_CONNECT_REJECT ) :
+ /* Extract fields */
+ DBGC ( conn, "CM %p connection rejected (reason %d)\n",
+ conn, ntohs ( connect_rej->reason ) );
+ /* Private data is valid only for a Consumer Reject */
+ if ( connect_rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
+ private_data = &connect_rej->private_data;
+ private_data_len = sizeof (connect_rej->private_data);
+ }
+ rc = ib_cm_rejection_reason_to_rc ( connect_rej->reason );
+ break;
+
+ default:
+ DBGC ( conn, "CM %p unexpected response (attribute %04x)\n",
+ conn, ntohs ( mad->hdr.attr_id ) );
+ rc = -ENOTSUP;
+ break;
+ }
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_madx ( ibdev, ibdev->gsi, madx );
+ conn->madx = NULL;
+
+ /* Hand off to the upper completion handler */
+ conn->op->changed ( ibdev, qp, conn, rc, private_data,
+ private_data_len );
+}
+
+/** Connection request operations */
+static struct ib_mad_transaction_operations ib_cm_req_op = {
+ .complete = ib_cm_req_complete,
+};
+
+/**
+ * Handle connection path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ * @v rc Status code
+ * @v av Address vector, or NULL on error
+ */
+static void ib_cm_path_complete ( struct ib_device *ibdev,
+ struct ib_path *path, int rc,
+ struct ib_address_vector *av ) {
+ struct ib_connection *conn = ib_path_get_ownerdata ( path );
+ struct ib_queue_pair *qp = conn->qp;
+ union ib_mad mad;
+ struct ib_cm_connect_request *connect_req =
+ &mad.cm.cm_data.connect_request;
+ size_t private_data_len;
+
+ /* Report failures */
+ if ( rc != 0 ) {
+ DBGC ( conn, "CM %p path lookup failed: %s\n",
+ conn, strerror ( rc ) );
+ conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
+ goto out;
+ }
+
+ /* Update queue pair peer path */
+ memcpy ( &qp->av, av, sizeof ( qp->av ) );
+
+ /* Construct connection request */
+ memset ( &mad, 0, sizeof ( mad ) );
+ mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
+ mad.hdr.class_version = IB_CM_CLASS_VERSION;
+ mad.hdr.method = IB_MGMT_METHOD_SEND;
+ mad.hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
+ connect_req->local_id = htonl ( conn->local_id );
+ memcpy ( &connect_req->service_id, &conn->service_id,
+ sizeof ( connect_req->service_id ) );
+ ib_get_hca_info ( ibdev, &connect_req->local_ca );
+ connect_req->local_qpn__responder_resources =
+ htonl ( ( qp->qpn << 8 ) | 1 );
+ connect_req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
+ connect_req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
+ htonl ( ( 0x14 << 3 ) | ( IB_CM_TRANSPORT_RC << 1 ) |
+ ( 0 << 0 ) );
+ connect_req->starting_psn__local_timeout__retry_count =
+ htonl ( ( qp->recv.psn << 8 ) | ( 0x14 << 3 ) |
+ ( 0x07 << 0 ) );
+ connect_req->pkey = htons ( ibdev->pkey );
+ connect_req->payload_mtu__rdc_exists__rnr_retry =
+ ( ( IB_MTU_2048 << 4 ) | ( 1 << 3 ) | ( 0x07 << 0 ) );
+ connect_req->max_cm_retries__srq =
+ ( ( 0x0f << 4 ) | ( 0 << 3 ) );
+ connect_req->primary.local_lid = htons ( ibdev->lid );
+ connect_req->primary.remote_lid = htons ( conn->qp->av.lid );
+ memcpy ( &connect_req->primary.local_gid, &ibdev->gid,
+ sizeof ( connect_req->primary.local_gid ) );
+ memcpy ( &connect_req->primary.remote_gid, &conn->qp->av.gid,
+ sizeof ( connect_req->primary.remote_gid ) );
+ connect_req->primary.flow_label__rate =
+ htonl ( ( 0 << 12 ) | ( conn->qp->av.rate << 0 ) );
+ connect_req->primary.hop_limit = 0;
+ connect_req->primary.sl__subnet_local =
+ ( ( conn->qp->av.sl << 4 ) | ( 1 << 3 ) );
+ connect_req->primary.local_ack_timeout = ( 0x13 << 3 );
+ private_data_len = conn->private_data_len;
+ if ( private_data_len > sizeof ( connect_req->private_data ) )
+ private_data_len = sizeof ( connect_req->private_data );
+ memcpy ( &connect_req->private_data, &conn->private_data,
+ private_data_len );
+
+ /* Create connection request */
+ conn->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
+ &ib_cm_req_op );
+ if ( ! conn->madx ) {
+ DBGC ( conn, "CM %p could not create connection request\n",
+ conn );
+ conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
+ goto out;
+ }
+ ib_madx_set_ownerdata ( conn->madx, conn );
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_path ( ibdev, path );
+ conn->path = NULL;
+}
+
+/** Connection path operations */
+static struct ib_path_operations ib_cm_path_op = {
+ .complete = ib_cm_path_complete,
+};
+
+/**
+ * Create connection to remote QP
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v dgid Target GID
+ * @v service_id Target service ID
+ * @v private_data Connection request private data
+ * @v private_data_len Length of connection request private data
+ * @v op Connection operations
+ * @ret conn Connection
+ */
+struct ib_connection *
+ib_create_conn ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_gid *dgid, struct ib_gid_half *service_id,
+ void *private_data, size_t private_data_len,
+ struct ib_connection_operations *op ) {
+ struct ib_connection *conn;
+
+ /* Allocate and initialise request */
+ conn = zalloc ( sizeof ( *conn ) + private_data_len );
+ if ( ! conn )
+ goto err_alloc_conn;
+ conn->ibdev = ibdev;
+ conn->qp = qp;
+ memset ( &qp->av, 0, sizeof ( qp->av ) );
+ qp->av.gid_present = 1;
+ memcpy ( &qp->av.gid, dgid, sizeof ( qp->av.gid ) );
+ conn->local_id = random();
+ memcpy ( &conn->service_id, service_id, sizeof ( conn->service_id ) );
+ conn->op = op;
+ conn->private_data_len = private_data_len;
+ memcpy ( &conn->private_data, private_data, private_data_len );
+
+ /* Create path */
+ conn->path = ib_create_path ( ibdev, &qp->av, &ib_cm_path_op );
+ if ( ! conn->path )
+ goto err_create_path;
+ ib_path_set_ownerdata ( conn->path, conn );
+
+ /* Add to list of connections */
+ list_add ( &conn->list, &ib_cm_conns );
+
+ DBGC ( conn, "CM %p created for IBDEV %p QPN %lx\n",
+ conn, ibdev, qp->qpn );
+ DBGC ( conn, "CM %p connecting to %08x:%08x:%08x:%08x %08x:%08x\n",
+ conn, ntohl ( dgid->u.dwords[0] ), ntohl ( dgid->u.dwords[1] ),
+ ntohl ( dgid->u.dwords[2] ), ntohl ( dgid->u.dwords[3] ),
+ ntohl ( service_id->u.dwords[0] ),
+ ntohl ( service_id->u.dwords[1] ) );
+
+ return conn;
+
+ ib_destroy_path ( ibdev, conn->path );
+ err_create_path:
+ free ( conn );
+ err_alloc_conn:
+ return NULL;
+}
+
+/**
+ * Destroy connection to remote QP
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v conn Connection
+ */
+void ib_destroy_conn ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp __unused,
+ struct ib_connection *conn ) {
+
+ list_del ( &conn->list );
+ if ( conn->madx )
+ ib_destroy_madx ( ibdev, ibdev->gsi, conn->madx );
+ if ( conn->path )
+ ib_destroy_path ( ibdev, conn->path );
+ free ( conn );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cmrc.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cmrc.c
new file mode 100644
index 0000000..2d64811
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_cmrc.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/xfer.h>
+#include <gpxe/process.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_cm.h>
+#include <gpxe/ib_cmrc.h>
+
+/**
+ * @file
+ *
+ * Infiniband Communication-managed Reliable Connections
+ *
+ */
+
+/** CMRC number of send WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_CMRC_NUM_SEND_WQES 4
+
+/** CMRC number of receive WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_CMRC_NUM_RECV_WQES 2
+
+/** CMRC number of completion queue entries
+ *
+ * This is a policy decision
+ */
+#define IB_CMRC_NUM_CQES 8
+
+/** An Infiniband Communication-Managed Reliable Connection */
+struct ib_cmrc_connection {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+ /** Infiniband device */
+ struct ib_device *ibdev;
+ /** Completion queue */
+ struct ib_completion_queue *cq;
+ /** Queue pair */
+ struct ib_queue_pair *qp;
+ /** Connection */
+ struct ib_connection *conn;
+ /** Destination GID */
+ struct ib_gid dgid;
+ /** Service ID */
+ struct ib_gid_half service_id;
+ /** QP is connected */
+ int connected;
+ /** Shutdown process */
+ struct process shutdown;
+};
+
+/**
+ * Shut down CMRC connection gracefully
+ *
+ * @v process Process
+ *
+ * The Infiniband data structures are not reference-counted or
+ * guarded. It is therefore unsafe to shut them down while we may be
+ * in the middle of a callback from the Infiniband stack (e.g. in a
+ * receive completion handler).
+ *
+ * This shutdown process will run some time after the call to
+ * ib_cmrc_close(), after control has returned out of the Infiniband
+ * core, and will shut down the Infiniband interfaces cleanly.
+ *
+ * The shutdown process holds an implicit reference on the CMRC
+ * connection, ensuring that the structure is not freed before the
+ * shutdown process has run.
+ */
+static void ib_cmrc_shutdown ( struct process *process ) {
+ struct ib_cmrc_connection *cmrc =
+ container_of ( process, struct ib_cmrc_connection, shutdown );
+
+ DBGC ( cmrc, "CMRC %p shutting down\n", cmrc );
+
+ /* Shut down Infiniband interface */
+ ib_destroy_conn ( cmrc->ibdev, cmrc->qp, cmrc->conn );
+ ib_destroy_qp ( cmrc->ibdev, cmrc->qp );
+ ib_destroy_cq ( cmrc->ibdev, cmrc->cq );
+ ib_close ( cmrc->ibdev );
+
+ /* Remove process from run queue */
+ process_del ( &cmrc->shutdown );
+
+ /* Drop the remaining reference */
+ ref_put ( &cmrc->refcnt );
+}
+
+/**
+ * Close CMRC connection
+ *
+ * @v cmrc Communication-Managed Reliable Connection
+ * @v rc Reason for close
+ */
+static void ib_cmrc_close ( struct ib_cmrc_connection *cmrc, int rc ) {
+
+ /* Close data transfer interface */
+ xfer_nullify ( &cmrc->xfer );
+ xfer_close ( &cmrc->xfer, rc );
+
+ /* Schedule shutdown process */
+ process_add ( &cmrc->shutdown );
+}
+
+/**
+ * Handle change of CMRC connection status
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v conn Connection
+ * @v rc_cm Connection status code
+ * @v private_data Private data, if available
+ * @v private_data_len Length of private data
+ */
+static void ib_cmrc_changed ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_connection *conn __unused, int rc_cm,
+ void *private_data, size_t private_data_len ) {
+ struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
+ int rc_xfer;
+
+ /* Record connection status */
+ if ( rc_cm == 0 ) {
+ DBGC ( cmrc, "CMRC %p connected\n", cmrc );
+ cmrc->connected = 1;
+ } else {
+ DBGC ( cmrc, "CMRC %p disconnected: %s\n",
+ cmrc, strerror ( rc_cm ) );
+ cmrc->connected = 0;
+ }
+
+ /* Pass up any private data */
+ DBGC2 ( cmrc, "CMRC %p received private data:\n", cmrc );
+ DBGC2_HDA ( cmrc, 0, private_data, private_data_len );
+ if ( private_data &&
+ ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
+ private_data_len ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not deliver private data: %s\n",
+ cmrc, strerror ( rc_xfer ) );
+ ib_cmrc_close ( cmrc, rc_xfer );
+ return;
+ }
+
+ /* If we are disconnected, close the upper connection */
+ if ( rc_cm != 0 ) {
+ ib_cmrc_close ( cmrc, rc_cm );
+ return;
+ }
+}
+
+/** CMRC connection operations */
+static struct ib_connection_operations ib_cmrc_conn_op = {
+ .changed = ib_cmrc_changed,
+};
+
+/**
+ * Handle CMRC send completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ib_cmrc_complete_send ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc ) {
+ struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
+
+ /* Free the completed I/O buffer */
+ free_iob ( iobuf );
+
+ /* Close the connection on any send errors */
+ if ( rc != 0 ) {
+ DBGC ( cmrc, "CMRC %p send error: %s\n",
+ cmrc, strerror ( rc ) );
+ ib_cmrc_close ( cmrc, rc );
+ return;
+ }
+}
+
+/**
+ * Handle CMRC receive completion
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ib_cmrc_complete_recv ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf, int rc ) {
+ struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
+
+ /* Close the connection on any receive errors */
+ if ( rc != 0 ) {
+ DBGC ( cmrc, "CMRC %p receive error: %s\n",
+ cmrc, strerror ( rc ) );
+ free_iob ( iobuf );
+ ib_cmrc_close ( cmrc, rc );
+ return;
+ }
+
+ DBGC2 ( cmrc, "CMRC %p received:\n", cmrc );
+ DBGC2_HDA ( cmrc, 0, iobuf->data, iob_len ( iobuf ) );
+
+ /* Pass up data */
+ if ( ( rc = xfer_deliver_iob ( &cmrc->xfer, iobuf ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not deliver data: %s\n",
+ cmrc, strerror ( rc ) );
+ ib_cmrc_close ( cmrc, rc );
+ return;
+ }
+}
+
+/** Infiniband CMRC completion operations */
+static struct ib_completion_queue_operations ib_cmrc_completion_ops = {
+ .complete_send = ib_cmrc_complete_send,
+ .complete_recv = ib_cmrc_complete_recv,
+};
+
+/**
+ * Send data via CMRC
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int ib_cmrc_xfer_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct ib_cmrc_connection *cmrc =
+ container_of ( xfer, struct ib_cmrc_connection, xfer );
+ int rc;
+
+ /* If no connection has yet been attempted, send this datagram
+ * as the CM REQ private data. Otherwise, send it via the QP.
+ */
+ if ( ! cmrc->connected ) {
+
+ /* Abort if we have already sent a CM connection request */
+ if ( cmrc->conn ) {
+ DBGC ( cmrc, "CMRC %p attempt to send before "
+ "connection is complete\n", cmrc );
+ rc = -EIO;
+ goto out;
+ }
+
+ /* Send via CM connection request */
+ cmrc->conn = ib_create_conn ( cmrc->ibdev, cmrc->qp,
+ &cmrc->dgid, &cmrc->service_id,
+ iobuf->data, iob_len ( iobuf ),
+ &ib_cmrc_conn_op );
+ if ( ! cmrc->conn ) {
+ DBGC ( cmrc, "CMRC %p could not connect\n", cmrc );
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ } else {
+
+ /* Send via QP */
+ if ( ( rc = ib_post_send ( cmrc->ibdev, cmrc->qp, NULL,
+ iob_disown ( iobuf ) ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not send: %s\n",
+ cmrc, strerror ( rc ) );
+ goto out;
+ }
+
+ }
+ return 0;
+
+ out:
+ /* Free the I/O buffer if necessary */
+ free_iob ( iobuf );
+
+ /* Close the connection on any errors */
+ if ( rc != 0 )
+ ib_cmrc_close ( cmrc, rc );
+
+ return rc;
+}
+
+/**
+ * Check CMRC flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ */
+static size_t ib_cmrc_xfer_window ( struct xfer_interface *xfer ) {
+ struct ib_cmrc_connection *cmrc =
+ container_of ( xfer, struct ib_cmrc_connection, xfer );
+
+ /* We indicate a window only when we are successfully
+ * connected.
+ */
+ return ( cmrc->connected ? IB_MAX_PAYLOAD_SIZE : 0 );
+}
+
+/**
+ * Close CMRC data-transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void ib_cmrc_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct ib_cmrc_connection *cmrc =
+ container_of ( xfer, struct ib_cmrc_connection, xfer );
+
+ DBGC ( cmrc, "CMRC %p closed: %s\n", cmrc, strerror ( rc ) );
+ ib_cmrc_close ( cmrc, rc );
+}
+
+/** CMRC data transfer interface operations */
+static struct xfer_interface_operations ib_cmrc_xfer_operations = {
+ .close = ib_cmrc_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = ib_cmrc_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = ib_cmrc_xfer_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/**
+ * Open CMRC connection
+ *
+ * @v xfer Data transfer interface
+ * @v ibdev Infiniband device
+ * @v dgid Destination GID
+ * @v service_id Service ID
+ * @ret rc Returns status code
+ */
+int ib_cmrc_open ( struct xfer_interface *xfer, struct ib_device *ibdev,
+ struct ib_gid *dgid, struct ib_gid_half *service_id ) {
+ struct ib_cmrc_connection *cmrc;
+ int rc;
+
+ /* Allocate and initialise structure */
+ cmrc = zalloc ( sizeof ( *cmrc ) );
+ if ( ! cmrc ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ xfer_init ( &cmrc->xfer, &ib_cmrc_xfer_operations, &cmrc->refcnt );
+ cmrc->ibdev = ibdev;
+ memcpy ( &cmrc->dgid, dgid, sizeof ( cmrc->dgid ) );
+ memcpy ( &cmrc->service_id, service_id, sizeof ( cmrc->service_id ) );
+ process_init_stopped ( &cmrc->shutdown, ib_cmrc_shutdown,
+ &cmrc->refcnt );
+
+ /* Open Infiniband device */
+ if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
+ DBGC ( cmrc, "CMRC %p could not open device: %s\n",
+ cmrc, strerror ( rc ) );
+ goto err_open;
+ }
+
+ /* Create completion queue */
+ cmrc->cq = ib_create_cq ( ibdev, IB_CMRC_NUM_CQES,
+ &ib_cmrc_completion_ops );
+ if ( ! cmrc->cq ) {
+ DBGC ( cmrc, "CMRC %p could not create completion queue\n",
+ cmrc );
+ rc = -ENOMEM;
+ goto err_create_cq;
+ }
+
+ /* Create queue pair */
+ cmrc->qp = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES,
+ cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq );
+ if ( ! cmrc->qp ) {
+ DBGC ( cmrc, "CMRC %p could not create queue pair\n", cmrc );
+ rc = -ENOMEM;
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( cmrc->qp, cmrc );
+ DBGC ( cmrc, "CMRC %p using QPN %lx\n", cmrc, cmrc->qp->qpn );
+
+ /* Attach to parent interface, transfer reference (implicitly)
+ * to our shutdown process, and return.
+ */
+ xfer_plug_plug ( &cmrc->xfer, xfer );
+ return 0;
+
+ ib_destroy_qp ( ibdev, cmrc->qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, cmrc->cq );
+ err_create_cq:
+ ib_close ( ibdev );
+ err_open:
+ ref_put ( &cmrc->refcnt );
+ err_alloc:
+ return rc;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mcast.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mcast.c
new file mode 100644
index 0000000..5cb395d
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mcast.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/list.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_mi.h>
+#include <gpxe/ib_mcast.h>
+
+/** @file
+ *
+ * Infiniband multicast groups
+ *
+ */
+
+/**
+ * Generate multicast membership MAD
+ *
+ * @v ibdev Infiniband device
+ * @v gid Multicast GID
+ * @v join Join (rather than leave) group
+ * @v mad MAD to fill in
+ */
+static void ib_mcast_mad ( struct ib_device *ibdev, struct ib_gid *gid,
+ int join, union ib_mad *mad ) {
+ struct ib_mad_sa *sa = &mad->sa;
+
+ /* Construct multicast membership record request */
+ memset ( sa, 0, sizeof ( *sa ) );
+ sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
+ sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
+ sa->mad_hdr.method =
+ ( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
+ sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
+ sa->sa_hdr.comp_mask[1] =
+ htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
+ IB_SA_MCMEMBER_REC_JOIN_STATE );
+ sa->sa_data.mc_member_record.scope__join_state = 1;
+ memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
+ sizeof ( sa->sa_data.mc_member_record.mgid ) );
+ memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
+ sizeof ( sa->sa_data.mc_member_record.port_gid ) );
+}
+
+/**
+ * Handle multicast membership record join response
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ */
+static void ib_mcast_complete ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi __unused,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av __unused ) {
+ struct ib_mc_membership *membership = ib_madx_get_ownerdata ( madx );
+ struct ib_queue_pair *qp = membership->qp;
+ struct ib_gid *gid = &membership->gid;
+ struct ib_mc_member_record *mc_member_record =
+ &mad->sa.sa_data.mc_member_record;
+ int joined;
+ unsigned long qkey;
+
+ /* Report failures */
+ if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
+ rc = -ENOTCONN;
+ if ( rc != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx join failed: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Extract values from MAD */
+ joined = ( mad->hdr.method == IB_MGMT_METHOD_GET_RESP );
+ qkey = ntohl ( mc_member_record->qkey );
+ DBGC ( ibdev, "IBDEV %p QPN %lx %s %08x:%08x:%08x:%08x qkey %lx\n",
+ ibdev, qp->qpn, ( joined ? "joined" : "left" ),
+ ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
+ ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ),
+ qkey );
+
+ /* Set queue key */
+ qp->qkey = qkey;
+ if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ goto out;
+ }
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_madx ( ibdev, mi, madx );
+ membership->madx = NULL;
+
+ /* Hand off to upper completion handler */
+ membership->complete ( ibdev, qp, membership, rc, mad );
+}
+
+/** Multicast membership management transaction completion operations */
+static struct ib_mad_transaction_operations ib_mcast_op = {
+ .complete = ib_mcast_complete,
+};
+
+/**
+ * Join multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ * @v gid Multicast GID to join
+ * @v joined Join completion handler
+ * @ret rc Return status code
+ */
+int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership, struct ib_gid *gid,
+ void ( * complete ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership,
+ int rc, union ib_mad *mad ) ) {
+ union ib_mad mad;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p QPN %lx joining %08x:%08x:%08x:%08x\n",
+ ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
+ ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
+ ntohl ( gid->u.dwords[3] ) );
+
+ /* Initialise structure */
+ membership->qp = qp;
+ memcpy ( &membership->gid, gid, sizeof ( membership->gid ) );
+ membership->complete = complete;
+
+ /* Attach queue pair to multicast GID */
+ if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not attach: %s\n",
+ ibdev, qp->qpn, strerror ( rc ) );
+ goto err_mcast_attach;
+ }
+
+ /* Initiate multicast membership join */
+ ib_mcast_mad ( ibdev, gid, 1, &mad );
+ membership->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
+ &ib_mcast_op );
+ if ( ! membership->madx ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not create join "
+ "transaction\n", ibdev, qp->qpn );
+ rc = -ENOMEM;
+ goto err_create_madx;
+ }
+ ib_madx_set_ownerdata ( membership->madx, membership );
+
+ return 0;
+
+ ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
+ err_create_madx:
+ ib_mcast_detach ( ibdev, qp, gid );
+ err_mcast_attach:
+ return rc;
+}
+
+/**
+ * Leave multicast group
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v membership Multicast group membership
+ */
+void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_mc_membership *membership ) {
+ struct ib_gid *gid = &membership->gid;
+ union ib_mad mad;
+ int rc;
+
+ DBGC ( ibdev, "IBDEV %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
+ ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
+ ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
+ ntohl ( gid->u.dwords[3] ) );
+
+ /* Detach from multicast GID */
+ ib_mcast_detach ( ibdev, qp, &membership->gid );
+
+ /* Cancel multicast membership join, if applicable */
+ if ( membership->madx ) {
+ ib_destroy_madx ( ibdev, ibdev->gsi, membership->madx );
+ membership->madx = NULL;
+ }
+
+ /* Send a single group leave MAD */
+ ib_mcast_mad ( ibdev, &membership->gid, 0, &mad );
+ if ( ( rc = ib_mi_send ( ibdev, ibdev->gsi, &mad, NULL ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %lx could not send leave request: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ }
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mi.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mi.c
new file mode 100644
index 0000000..7511fd8
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_mi.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/ib_mi.h>
+
+/**
+ * @file
+ *
+ * Infiniband management interfaces
+ *
+ */
+
+/** Management interface number of send WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_MI_NUM_SEND_WQES 4
+
+/** Management interface number of receive WQEs
+ *
+ * This is a policy decision.
+ */
+#define IB_MI_NUM_RECV_WQES 2
+
+/** Management interface number of completion queue entries
+ *
+ * This is a policy decision
+ */
+#define IB_MI_NUM_CQES 8
+
+/** TID magic signature */
+#define IB_MI_TID_MAGIC ( ( 'g' << 24 ) | ( 'P' << 16 ) | ( 'X' << 8 ) | 'E' )
+
+/** TID to use for next MAD */
+static unsigned int next_tid;
+
+/**
+ * Handle received MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ * @ret rc Return status code
+ */
+static int ib_mi_handle ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_mad_hdr *hdr = &mad->hdr;
+ struct ib_mad_transaction *madx;
+ struct ib_mad_agent *agent;
+
+ /* Look for a matching transaction by TID */
+ list_for_each_entry ( madx, &mi->madx, list ) {
+ if ( memcmp ( &hdr->tid, &madx->mad.hdr.tid,
+ sizeof ( hdr->tid ) ) != 0 )
+ continue;
+ /* Found a matching transaction */
+ madx->op->complete ( ibdev, mi, madx, 0, mad, av );
+ return 0;
+ }
+
+ /* If there is no matching transaction, look for a listening agent */
+ for_each_table_entry ( agent, IB_MAD_AGENTS ) {
+ if ( ( ( agent->mgmt_class & IB_MGMT_CLASS_MASK ) !=
+ ( hdr->mgmt_class & IB_MGMT_CLASS_MASK ) ) ||
+ ( agent->class_version != hdr->class_version ) ||
+ ( agent->attr_id != hdr->attr_id ) )
+ continue;
+ /* Found a matching agent */
+ agent->handle ( ibdev, mi, mad, av );
+ return 0;
+ }
+
+ /* Otherwise, ignore it */
+ DBGC ( mi, "MI %p RX TID %08x%08x ignored\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ) );
+ return -ENOTSUP;
+}
+
+/**
+ * Complete receive via management interface
+ *
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+static void ib_mi_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+ struct ib_mad_interface *mi = ib_qp_get_ownerdata ( qp );
+ union ib_mad *mad;
+ struct ib_mad_hdr *hdr;
+
+ /* Ignore errors */
+ if ( rc != 0 ) {
+ DBGC ( mi, "MI %p RX error: %s\n", mi, strerror ( rc ) );
+ goto out;
+ }
+
+ /* Sanity checks */
+ if ( iob_len ( iobuf ) != sizeof ( *mad ) ) {
+ DBGC ( mi, "MI %p RX bad size (%zd bytes)\n",
+ mi, iob_len ( iobuf ) );
+ DBGC_HDA ( mi, 0, iobuf->data, iob_len ( iobuf ) );
+ goto out;
+ }
+ mad = iobuf->data;
+ hdr = &mad->hdr;
+ if ( hdr->base_version != IB_MGMT_BASE_VERSION ) {
+ DBGC ( mi, "MI %p RX unsupported base version %x\n",
+ mi, hdr->base_version );
+ DBGC_HDA ( mi, 0, mad, sizeof ( *mad ) );
+ goto out;
+ }
+ DBGC ( mi, "MI %p RX TID %08x%08x (%02x,%02x,%02x,%04x) status "
+ "%04x\n", mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
+ hdr->mgmt_class, hdr->class_version, hdr->method,
+ ntohs ( hdr->attr_id ), ntohs ( hdr->status ) );
+ DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) );
+
+ /* Handle MAD */
+ if ( ( rc = ib_mi_handle ( ibdev, mi, mad, av ) ) != 0 )
+ goto out;
+
+ out:
+ free_iob ( iobuf );
+}
+
+/** Management interface completion operations */
+static struct ib_completion_queue_operations ib_mi_completion_ops = {
+ .complete_recv = ib_mi_complete_recv,
+};
+
+/**
+ * Transmit MAD
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad MAD
+ * @v av Destination address vector
+ * @ret rc Return status code
+ */
+int ib_mi_send ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av ) {
+ struct ib_mad_hdr *hdr = &mad->hdr;
+ struct io_buffer *iobuf;
+ int rc;
+
+ /* Set common fields */
+ hdr->base_version = IB_MGMT_BASE_VERSION;
+ if ( ( hdr->tid[0] == 0 ) && ( hdr->tid[1] == 0 ) ) {
+ hdr->tid[0] = htonl ( IB_MI_TID_MAGIC );
+ hdr->tid[1] = htonl ( ++next_tid );
+ }
+ DBGC ( mi, "MI %p TX TID %08x%08x (%02x,%02x,%02x,%04x) status "
+ "%04x\n", mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
+ hdr->mgmt_class, hdr->class_version, hdr->method,
+ ntohs ( hdr->attr_id ), ntohs ( hdr->status ) );
+ DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) );
+
+ /* Construct directed route portion of response, if necessary */
+ if ( hdr->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ) {
+ struct ib_mad_smp *smp = &mad->smp;
+ unsigned int hop_pointer;
+ unsigned int hop_count;
+
+ smp->mad_hdr.status |= htons ( IB_SMP_STATUS_D_INBOUND );
+ hop_pointer = smp->mad_hdr.class_specific.smp.hop_pointer;
+ hop_count = smp->mad_hdr.class_specific.smp.hop_count;
+ assert ( hop_count == hop_pointer );
+ if ( hop_pointer < ( sizeof ( smp->return_path.hops ) /
+ sizeof ( smp->return_path.hops[0] ) ) ) {
+ smp->return_path.hops[hop_pointer] = ibdev->port;
+ } else {
+ DBGC ( mi, "MI %p TX TID %08x%08x invalid hop pointer "
+ "%d\n", mi, ntohl ( hdr->tid[0] ),
+ ntohl ( hdr->tid[1] ), hop_pointer );
+ return -EINVAL;
+ }
+ }
+
+ /* Construct I/O buffer */
+ iobuf = alloc_iob ( sizeof ( *mad ) );
+ if ( ! iobuf ) {
+ DBGC ( mi, "MI %p could not allocate buffer for TID "
+ "%08x%08x\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ) );
+ return -ENOMEM;
+ }
+ memcpy ( iob_put ( iobuf, sizeof ( *mad ) ), mad, sizeof ( *mad ) );
+
+ /* Send I/O buffer */
+ if ( ( rc = ib_post_send ( ibdev, mi->qp, av, iobuf ) ) != 0 ) {
+ DBGC ( mi, "MI %p TX TID %08x%08x failed: %s\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ),
+ strerror ( rc ) );
+ free_iob ( iobuf );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle management transaction timer expiry
+ *
+ * @v timer Retry timer
+ * @v expired Failure indicator
+ */
+static void ib_mi_timer_expired ( struct retry_timer *timer, int expired ) {
+ struct ib_mad_transaction *madx =
+ container_of ( timer, struct ib_mad_transaction, timer );
+ struct ib_mad_interface *mi = madx->mi;
+ struct ib_device *ibdev = mi->ibdev;
+ struct ib_mad_hdr *hdr = &madx->mad.hdr;
+
+ /* Abandon transaction if we have tried too many times */
+ if ( expired ) {
+ DBGC ( mi, "MI %p abandoning TID %08x%08x\n",
+ mi, ntohl ( hdr->tid[0] ), ntohl ( hdr->tid[1] ) );
+ madx->op->complete ( ibdev, mi, madx, -ETIMEDOUT, NULL, NULL );
+ return;
+ }
+
+ /* Restart retransmission timer */
+ start_timer ( timer );
+
+ /* Resend MAD */
+ ib_mi_send ( ibdev, mi, &madx->mad, &madx->av );
+}
+
+/**
+ * Create management transaction
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad MAD to send
+ * @v av Destination address, or NULL to use SM's GSI
+ * @v op Management transaction operations
+ * @ret madx Management transaction, or NULL
+ */
+struct ib_mad_transaction *
+ib_create_madx ( struct ib_device *ibdev, struct ib_mad_interface *mi,
+ union ib_mad *mad, struct ib_address_vector *av,
+ struct ib_mad_transaction_operations *op ) {
+ struct ib_mad_transaction *madx;
+
+ /* Allocate and initialise structure */
+ madx = zalloc ( sizeof ( *madx ) );
+ if ( ! madx )
+ return NULL;
+ madx->mi = mi;
+ madx->timer.expired = ib_mi_timer_expired;
+ madx->op = op;
+
+ /* Determine address vector */
+ if ( av ) {
+ memcpy ( &madx->av, av, sizeof ( madx->av ) );
+ } else {
+ madx->av.lid = ibdev->sm_lid;
+ madx->av.sl = ibdev->sm_sl;
+ madx->av.qpn = IB_QPN_GSI;
+ madx->av.qkey = IB_QKEY_GSI;
+ }
+
+ /* Copy MAD */
+ memcpy ( &madx->mad, mad, sizeof ( madx->mad ) );
+
+ /* Add to list and start timer to send initial MAD */
+ list_add ( &madx->list, &mi->madx );
+ start_timer_nodelay ( &madx->timer );
+
+ return madx;
+}
+
+/**
+ * Destroy management transaction
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ */
+void ib_destroy_madx ( struct ib_device *ibdev __unused,
+ struct ib_mad_interface *mi __unused,
+ struct ib_mad_transaction *madx ) {
+
+ /* Stop timer and remove from list */
+ stop_timer ( &madx->timer );
+ list_del ( &madx->list );
+
+ /* Free transaction */
+ free ( madx );
+}
+
+/**
+ * Create management interface
+ *
+ * @v ibdev Infiniband device
+ * @v type Queue pair type
+ * @ret mi Management agent, or NULL
+ */
+struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev,
+ enum ib_queue_pair_type type ) {
+ struct ib_mad_interface *mi;
+ int rc;
+
+ /* Allocate and initialise fields */
+ mi = zalloc ( sizeof ( *mi ) );
+ if ( ! mi )
+ goto err_alloc;
+ mi->ibdev = ibdev;
+ INIT_LIST_HEAD ( &mi->madx );
+
+ /* Create completion queue */
+ mi->cq = ib_create_cq ( ibdev, IB_MI_NUM_CQES, &ib_mi_completion_ops );
+ if ( ! mi->cq ) {
+ DBGC ( mi, "MI %p could not allocate completion queue\n", mi );
+ goto err_create_cq;
+ }
+
+ /* Create queue pair */
+ mi->qp = ib_create_qp ( ibdev, type, IB_MI_NUM_SEND_WQES, mi->cq,
+ IB_MI_NUM_RECV_WQES, mi->cq );
+ if ( ! mi->qp ) {
+ DBGC ( mi, "MI %p could not allocate queue pair\n", mi );
+ goto err_create_qp;
+ }
+ ib_qp_set_ownerdata ( mi->qp, mi );
+ DBGC ( mi, "MI %p (%s) running on QPN %#lx\n",
+ mi, ( ( type == IB_QPT_SMI ) ? "SMI" : "GSI" ), mi->qp->qpn );
+
+ /* Set queue key */
+ mi->qp->qkey = ( ( type == IB_QPT_SMI ) ? IB_QKEY_SMI : IB_QKEY_GSI );
+ if ( ( rc = ib_modify_qp ( ibdev, mi->qp ) ) != 0 ) {
+ DBGC ( mi, "MI %p could not set queue key: %s\n",
+ mi, strerror ( rc ) );
+ goto err_modify_qp;
+ }
+
+ /* Fill receive ring */
+ ib_refill_recv ( ibdev, mi->qp );
+ return mi;
+
+ err_modify_qp:
+ ib_destroy_qp ( ibdev, mi->qp );
+ err_create_qp:
+ ib_destroy_cq ( ibdev, mi->cq );
+ err_create_cq:
+ free ( mi );
+ err_alloc:
+ return NULL;
+}
+
+/**
+ * Destroy management interface
+ *
+ * @v mi Management interface
+ */
+void ib_destroy_mi ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
+ struct ib_mad_transaction *madx;
+ struct ib_mad_transaction *tmp;
+
+ /* Flush any outstanding requests */
+ list_for_each_entry_safe ( madx, tmp, &mi->madx, list ) {
+ DBGC ( mi, "MI %p destroyed while TID %08x%08x in progress\n",
+ mi, ntohl ( madx->mad.hdr.tid[0] ),
+ ntohl ( madx->mad.hdr.tid[1] ) );
+ madx->op->complete ( ibdev, mi, madx, -ECANCELED, NULL, NULL );
+ }
+
+ ib_destroy_qp ( ibdev, mi->qp );
+ ib_destroy_cq ( ibdev, mi->cq );
+ free ( mi );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_packet.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_packet.c
new file mode 100644
index 0000000..08820ef
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_packet.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_packet.h>
+
+/**
+ * @file
+ *
+ * Infiniband Packet Formats
+ *
+ */
+
+/**
+ * Add IB headers
+ *
+ * @v ibdev Infiniband device
+ * @v iobuf I/O buffer to contain headers
+ * @v qp Queue pair
+ * @v payload_len Payload length
+ * @v av Address vector
+ */
+int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair *qp, size_t payload_len,
+ const struct ib_address_vector *av ) {
+ struct ib_local_route_header *lrh;
+ struct ib_global_route_header *grh;
+ struct ib_base_transport_header *bth;
+ struct ib_datagram_extended_transport_header *deth;
+ size_t orig_iob_len = iob_len ( iobuf );
+ size_t pad_len;
+ size_t lrh_len;
+ size_t grh_len;
+ unsigned int vl;
+ unsigned int lnh;
+
+ DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n",
+ ibdev, ibdev->lid, qp->ext_qpn, av->lid, av->qpn, av->qkey );
+
+ /* Calculate packet length */
+ pad_len = ( (-payload_len) & 0x3 );
+ payload_len += pad_len;
+ payload_len += 4; /* ICRC */
+
+ /* Reserve space for headers */
+ orig_iob_len = iob_len ( iobuf );
+ deth = iob_push ( iobuf, sizeof ( *deth ) );
+ bth = iob_push ( iobuf, sizeof ( *bth ) );
+ grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
+ grh = ( av->gid_present ?
+ iob_push ( iobuf, sizeof ( *grh ) ) : NULL );
+ lrh = iob_push ( iobuf, sizeof ( *lrh ) );
+ lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
+
+ /* Construct LRH */
+ vl = ( ( qp->ext_qpn == IB_QPN_SMI ) ? IB_VL_SMP : IB_VL_DEFAULT );
+ lrh->vl__lver = ( vl << 4 );
+ lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH );
+ lrh->sl__lnh = ( ( av->sl << 4 ) | lnh );
+ lrh->dlid = htons ( av->lid );
+ lrh->length = htons ( lrh_len >> 2 );
+ lrh->slid = htons ( ibdev->lid );
+
+ /* Construct GRH, if required */
+ if ( grh ) {
+ grh->ipver__tclass__flowlabel =
+ htonl ( IB_GRH_IPVER_IPv6 << 28 );
+ grh->paylen = htons ( grh_len );
+ grh->nxthdr = IB_GRH_NXTHDR_IBA;
+ grh->hoplmt = 0;
+ memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) );
+ memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) );
+ }
+
+ /* Construct BTH */
+ bth->opcode = BTH_OPCODE_UD_SEND;
+ bth->se__m__padcnt__tver = ( pad_len << 4 );
+ bth->pkey = htons ( ibdev->pkey );
+ bth->dest_qp = htonl ( av->qpn );
+ bth->ack__psn = htonl ( ( qp->send.psn++ ) & 0xffffffUL );
+
+ /* Construct DETH */
+ deth->qkey = htonl ( av->qkey );
+ deth->src_qp = htonl ( qp->ext_qpn );
+
+ DBGCP_HDA ( ibdev, 0, iobuf->data,
+ ( iob_len ( iobuf ) - orig_iob_len ) );
+
+ return 0;
+}
+
+/**
+ * Remove IB headers
+ *
+ * @v ibdev Infiniband device
+ * @v iobuf I/O buffer containing headers
+ * @v qp Queue pair to fill in, or NULL
+ * @v payload_len Payload length to fill in, or NULL
+ * @v av Address vector to fill in
+ */
+int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair **qp, size_t *payload_len,
+ struct ib_address_vector *av ) {
+ struct ib_local_route_header *lrh;
+ struct ib_global_route_header *grh;
+ struct ib_base_transport_header *bth;
+ struct ib_datagram_extended_transport_header *deth;
+ size_t orig_iob_len = iob_len ( iobuf );
+ unsigned int lnh;
+ size_t pad_len;
+ unsigned long qpn;
+ unsigned int lid;
+
+ /* Clear return values */
+ if ( qp )
+ *qp = NULL;
+ if ( payload_len )
+ *payload_len = 0;
+ memset ( av, 0, sizeof ( *av ) );
+
+ /* Extract LRH */
+ if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for LRH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ lrh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *lrh ) );
+ av->lid = ntohs ( lrh->slid );
+ av->sl = ( lrh->sl__lnh >> 4 );
+ lnh = ( lrh->sl__lnh & 0x3 );
+ lid = ntohs ( lrh->dlid );
+
+ /* Reject unsupported packets */
+ if ( ! ( ( lnh == IB_LNH_BTH ) || ( lnh == IB_LNH_GRH ) ) ) {
+ DBGC ( ibdev, "IBDEV %p RX unsupported LNH %x\n",
+ ibdev, lnh );
+ return -ENOTSUP;
+ }
+
+ /* Extract GRH, if present */
+ if ( lnh == IB_LNH_GRH ) {
+ if ( iob_len ( iobuf ) < sizeof ( *grh ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) "
+ "for GRH\n", ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ av->gid_present = 1;
+ memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ } else {
+ grh = NULL;
+ }
+
+ /* Extract BTH */
+ if ( iob_len ( iobuf ) < sizeof ( *bth ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for BTH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ bth = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *bth ) );
+ if ( bth->opcode != BTH_OPCODE_UD_SEND ) {
+ DBGC ( ibdev, "IBDEV %p unsupported BTH opcode %x\n",
+ ibdev, bth->opcode );
+ return -ENOTSUP;
+ }
+ qpn = ntohl ( bth->dest_qp );
+
+ /* Extract DETH */
+ if ( iob_len ( iobuf ) < sizeof ( *deth ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for DETH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ deth = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *deth ) );
+ av->qpn = ntohl ( deth->src_qp );
+ av->qkey = ntohl ( deth->qkey );
+
+ /* Calculate payload length, if applicable */
+ if ( payload_len ) {
+ pad_len = ( ( bth->se__m__padcnt__tver >> 4 ) & 0x3 );
+ *payload_len = ( ( ntohs ( lrh->length ) << 2 )
+ - ( orig_iob_len - iob_len ( iobuf ) )
+ - pad_len - 4 /* ICRC */ );
+ }
+
+ /* Determine destination QP, if applicable */
+ if ( qp ) {
+ if ( IB_LID_MULTICAST ( lid ) && grh ) {
+ if ( ! ( *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ))){
+ DBGC ( ibdev, "IBDEV %p RX for unknown MGID "
+ "%08x:%08x:%08x:%08x\n", ibdev,
+ ntohl ( grh->dgid.u.dwords[0] ),
+ ntohl ( grh->dgid.u.dwords[1] ),
+ ntohl ( grh->dgid.u.dwords[2] ),
+ ntohl ( grh->dgid.u.dwords[3] ) );
+ return -ENODEV;
+ }
+ } else {
+ if ( ! ( *qp = ib_find_qp_qpn ( ibdev, qpn ) ) ) {
+ DBGC ( ibdev, "IBDEV %p RX for nonexistent "
+ "QPN %lx\n", ibdev, qpn );
+ return -ENODEV;
+ }
+ }
+ assert ( *qp );
+ }
+
+ DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08x)\n",
+ ibdev, lid, ( IB_LID_MULTICAST( lid ) ?
+ ( qp ? (*qp)->ext_qpn : -1UL ) : qpn ),
+ av->lid, av->qpn, ntohl ( deth->qkey ) );
+ DBGCP_HDA ( ibdev, 0,
+ ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ),
+ ( orig_iob_len - iob_len ( iobuf ) ) );
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_pathrec.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_pathrec.c
new file mode 100644
index 0000000..136e628
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_pathrec.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_mi.h>
+#include <gpxe/ib_pathrec.h>
+
+/** @file
+ *
+ * Infiniband path lookups
+ *
+ */
+
+/**
+ * Handle path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v madx Management transaction
+ * @v rc Status code
+ * @v mad Received MAD (or NULL on error)
+ * @v av Source address vector (or NULL on error)
+ */
+static void ib_path_complete ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ struct ib_mad_transaction *madx,
+ int rc, union ib_mad *mad,
+ struct ib_address_vector *av __unused ) {
+ struct ib_path *path = ib_madx_get_ownerdata ( madx );
+ struct ib_gid *dgid = &path->av.gid;
+ struct ib_path_record *pathrec = &mad->sa.sa_data.path_record;
+
+ /* Report failures */
+ if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
+ rc = -ENETUNREACH;
+ if ( rc != 0 ) {
+ DBGC ( ibdev, "IBDEV %p path lookup for %08x:%08x:%08x:%08x "
+ "failed: %s\n", ibdev, htonl ( dgid->u.dwords[0] ),
+ htonl ( dgid->u.dwords[1] ),
+ htonl ( dgid->u.dwords[2] ),
+ htonl ( dgid->u.dwords[3] ), strerror ( rc ) );
+ goto out;
+ }
+
+ /* Extract values from MAD */
+ path->av.lid = ntohs ( pathrec->dlid );
+ path->av.sl = ( pathrec->reserved__sl & 0x0f );
+ path->av.rate = ( pathrec->rate_selector__rate & 0x3f );
+ DBGC ( ibdev, "IBDEV %p path to %08x:%08x:%08x:%08x is %04x sl %d "
+ "rate %d\n", ibdev, htonl ( dgid->u.dwords[0] ),
+ htonl ( dgid->u.dwords[1] ), htonl ( dgid->u.dwords[2] ),
+ htonl ( dgid->u.dwords[3] ), path->av.lid, path->av.sl,
+ path->av.rate );
+
+ out:
+ /* Destroy the completed transaction */
+ ib_destroy_madx ( ibdev, mi, madx );
+ path->madx = NULL;
+
+ /* Hand off to upper completion handler */
+ path->op->complete ( ibdev, path, rc, &path->av );
+}
+
+/** Path transaction completion operations */
+static struct ib_mad_transaction_operations ib_path_op = {
+ .complete = ib_path_complete,
+};
+
+/**
+ * Create path
+ *
+ * @v ibdev Infiniband device
+ * @v av Address vector to complete
+ * @v op Path operations
+ * @ret path Path
+ */
+struct ib_path *
+ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
+ struct ib_path_operations *op ) {
+ struct ib_path *path;
+ union ib_mad mad;
+ struct ib_mad_sa *sa = &mad.sa;
+
+ /* Allocate and initialise structure */
+ path = zalloc ( sizeof ( *path ) );
+ if ( ! path )
+ goto err_alloc_path;
+ path->ibdev = ibdev;
+ memcpy ( &path->av, av, sizeof ( path->av ) );
+ path->op = op;
+
+ /* Construct path request */
+ memset ( sa, 0, sizeof ( *sa ) );
+ sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
+ sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
+ sa->mad_hdr.method = IB_MGMT_METHOD_GET;
+ sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
+ sa->sa_hdr.comp_mask[1] =
+ htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
+ memcpy ( &sa->sa_data.path_record.dgid, &path->av.gid,
+ sizeof ( sa->sa_data.path_record.dgid ) );
+ memcpy ( &sa->sa_data.path_record.sgid, &ibdev->gid,
+ sizeof ( sa->sa_data.path_record.sgid ) );
+
+ /* Create management transaction */
+ path->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
+ &ib_path_op );
+ if ( ! path->madx )
+ goto err_create_madx;
+ ib_madx_set_ownerdata ( path->madx, path );
+
+ return path;
+
+ ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
+ err_create_madx:
+ free ( path );
+ err_alloc_path:
+ return NULL;
+}
+
+/**
+ * Destroy path
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ */
+void ib_destroy_path ( struct ib_device *ibdev, struct ib_path *path ) {
+
+ if ( path->madx )
+ ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
+ free ( path );
+}
+
+/** Number of path cache entries
+ *
+ * Must be a power of two.
+ */
+#define IB_NUM_CACHED_PATHS 4
+
+/** A cached path */
+struct ib_cached_path {
+ /** Path */
+ struct ib_path *path;
+};
+
+/** Path cache */
+static struct ib_cached_path ib_path_cache[IB_NUM_CACHED_PATHS];
+
+/** Oldest path cache entry index */
+static unsigned int ib_path_cache_idx;
+
+/**
+ * Find path cache entry
+ *
+ * @v ibdev Infiniband device
+ * @v dgid Destination GID
+ * @ret path Path cache entry, or NULL
+ */
+static struct ib_cached_path *
+ib_find_path_cache_entry ( struct ib_device *ibdev, struct ib_gid *dgid ) {
+ struct ib_cached_path *cached;
+ unsigned int i;
+
+ for ( i = 0 ; i < IB_NUM_CACHED_PATHS ; i++ ) {
+ cached = &ib_path_cache[i];
+ if ( ! cached->path )
+ continue;
+ if ( cached->path->ibdev != ibdev )
+ continue;
+ if ( memcmp ( &cached->path->av.gid, dgid,
+ sizeof ( cached->path->av.gid ) ) != 0 )
+ continue;
+ return cached;
+ }
+
+ return NULL;
+}
+
+/**
+ * Handle cached path transaction completion
+ *
+ * @v ibdev Infiniband device
+ * @v path Path
+ * @v rc Status code
+ * @v av Address vector, or NULL on error
+ */
+static void ib_cached_path_complete ( struct ib_device *ibdev,
+ struct ib_path *path, int rc,
+ struct ib_address_vector *av __unused ) {
+ struct ib_cached_path *cached = ib_path_get_ownerdata ( path );
+
+ /* If the transaction failed, erase the cache entry */
+ if ( rc != 0 ) {
+ /* Destroy the old cache entry */
+ ib_destroy_path ( ibdev, path );
+ memset ( cached, 0, sizeof ( *cached ) );
+ return;
+ }
+
+ /* Do not destroy the completed transaction; we still need to
+ * refer to the resolved path.
+ */
+}
+
+/** Cached path transaction completion operations */
+static struct ib_path_operations ib_cached_path_op = {
+ .complete = ib_cached_path_complete,
+};
+
+/**
+ * Resolve path
+ *
+ * @v ibdev Infiniband device
+ * @v av Address vector to complete
+ * @ret rc Return status code
+ *
+ * This provides a non-transactional way to resolve a path, via a
+ * cache similar to ARP.
+ */
+int ib_resolve_path ( struct ib_device *ibdev, struct ib_address_vector *av ) {
+ struct ib_gid *gid = &av->gid;
+ struct ib_cached_path *cached;
+ unsigned int cache_idx;
+
+ /* Sanity check */
+ if ( ! av->gid_present ) {
+ DBGC ( ibdev, "IBDEV %p attempt to look up path "
+ "without GID\n", ibdev );
+ return -EINVAL;
+ }
+
+ /* Look in cache for a matching entry */
+ cached = ib_find_path_cache_entry ( ibdev, gid );
+ if ( cached && cached->path->av.lid ) {
+ /* Populated entry found */
+ av->lid = cached->path->av.lid;
+ av->rate = cached->path->av.rate;
+ av->sl = cached->path->av.sl;
+ DBGC2 ( ibdev, "IBDEV %p cache hit for %08x:%08x:%08x:%08x\n",
+ ibdev, htonl ( gid->u.dwords[0] ),
+ htonl ( gid->u.dwords[1] ), htonl ( gid->u.dwords[2] ),
+ htonl ( gid->u.dwords[3] ) );
+ return 0;
+ }
+ DBGC ( ibdev, "IBDEV %p cache miss for %08x:%08x:%08x:%08x%s\n",
+ ibdev, htonl ( gid->u.dwords[0] ), htonl ( gid->u.dwords[1] ),
+ htonl ( gid->u.dwords[2] ), htonl ( gid->u.dwords[3] ),
+ ( cached ? " (in progress)" : "" ) );
+
+ /* If lookup is already in progress, do nothing */
+ if ( cached )
+ return -ENOENT;
+
+ /* Locate a new cache entry to use */
+ cache_idx = ( (ib_path_cache_idx++) % IB_NUM_CACHED_PATHS );
+ cached = &ib_path_cache[cache_idx];
+
+ /* Destroy the old cache entry */
+ if ( cached->path )
+ ib_destroy_path ( ibdev, cached->path );
+ memset ( cached, 0, sizeof ( *cached ) );
+
+ /* Create new path */
+ cached->path = ib_create_path ( ibdev, av, &ib_cached_path_op );
+ if ( ! cached->path ) {
+ DBGC ( ibdev, "IBDEV %p could not create path\n",
+ ibdev );
+ return -ENOMEM;
+ }
+ ib_path_set_ownerdata ( cached->path, cached );
+
+ /* Not found yet */
+ return -ENOENT;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_sma.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_sma.c
new file mode 100644
index 0000000..eb4f987
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_sma.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/ib_mi.h>
+#include <gpxe/ib_sma.h>
+
+/**
+ * @file
+ *
+ * Infiniband Subnet Management Agent
+ *
+ */
+
+/**
+ * Node information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_node_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_node_info *node_info = &mad->smp.smp_data.node_info;
+ int rc;
+
+ /* Fill in information */
+ memset ( node_info, 0, sizeof ( *node_info ) );
+ node_info->base_version = IB_MGMT_BASE_VERSION;
+ node_info->class_version = IB_SMP_CLASS_VERSION;
+ node_info->node_type = IB_NODE_TYPE_HCA;
+ node_info->num_ports = ib_get_hca_info ( ibdev, &node_info->sys_guid );
+ memcpy ( &node_info->node_guid, &node_info->sys_guid,
+ sizeof ( node_info->node_guid ) );
+ memcpy ( &node_info->port_guid, &ibdev->gid.u.half[1],
+ sizeof ( node_info->port_guid ) );
+ node_info->partition_cap = htons ( 1 );
+ node_info->local_port_num = ibdev->port;
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send NodeInfo GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Node description
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_node_desc ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc;
+ struct ib_gid_half *guid = &ibdev->gid.u.half[1];
+ int rc;
+
+ /* Fill in information */
+ memset ( node_desc, 0, sizeof ( *node_desc ) );
+ snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ),
+ "gPXE %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)",
+ guid->u.bytes[0], guid->u.bytes[1], guid->u.bytes[2],
+ guid->u.bytes[3], guid->u.bytes[4], guid->u.bytes[5],
+ guid->u.bytes[6], guid->u.bytes[7], ibdev->dev->name );
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send NodeDesc GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * GUID information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_guid_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info;
+ int rc;
+
+ /* Fill in information */
+ memset ( guid_info, 0, sizeof ( *guid_info ) );
+ memcpy ( guid_info->guid[0], &ibdev->gid.u.half[1],
+ sizeof ( guid_info->guid[0] ) );
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send GuidInfo GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Set port information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @ret rc Return status code
+ */
+static int ib_sma_set_port_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad ) {
+ const struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
+ unsigned int link_width_enabled;
+ unsigned int link_speed_enabled;
+ int rc;
+
+ /* Set parameters */
+ memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix,
+ sizeof ( ibdev->gid.u.half[0] ) );
+ ibdev->lid = ntohs ( port_info->lid );
+ ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
+ if ( ( link_width_enabled = port_info->link_width_enabled ) )
+ ibdev->link_width_enabled = link_width_enabled;
+ if ( ( link_speed_enabled =
+ ( port_info->link_speed_active__link_speed_enabled & 0xf ) ) )
+ ibdev->link_speed_enabled = link_speed_enabled;
+ ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
+ DBGC ( mi, "SMA %p set LID %04x SMLID %04x link width %02x speed "
+ "%02x\n", mi, ibdev->lid, ibdev->sm_lid,
+ ibdev->link_width_enabled, ibdev->link_speed_enabled );
+
+ /* Update parameters on device */
+ if ( ( rc = ib_set_port_info ( ibdev, mad ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not set port information: %s\n",
+ mi, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Port information
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_port_info ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
+ int rc;
+
+ /* Set parameters if applicable */
+ if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
+ if ( ( rc = ib_sma_set_port_info ( ibdev, mi, mad ) ) != 0 ) {
+ mad->hdr.status =
+ htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
+ /* Fall through to generate GetResponse */
+ }
+ }
+
+ /* Fill in information */
+ memset ( port_info, 0, sizeof ( *port_info ) );
+ memcpy ( port_info->gid_prefix, &ibdev->gid.u.half[0],
+ sizeof ( port_info->gid_prefix ) );
+ port_info->lid = ntohs ( ibdev->lid );
+ port_info->mastersm_lid = ntohs ( ibdev->sm_lid );
+ port_info->local_port_num = ibdev->port;
+ port_info->link_width_enabled = ibdev->link_width_enabled;
+ port_info->link_width_supported = ibdev->link_width_supported;
+ port_info->link_width_active = ibdev->link_width_active;
+ port_info->link_speed_supported__port_state =
+ ( ( ibdev->link_speed_supported << 4 ) | ibdev->port_state );
+ port_info->port_phys_state__link_down_def_state =
+ ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) |
+ IB_PORT_PHYS_STATE_POLLING );
+ port_info->link_speed_active__link_speed_enabled =
+ ( ( ibdev->link_speed_active << 4 ) |
+ ibdev->link_speed_enabled );
+ port_info->neighbour_mtu__mastersm_sl =
+ ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl );
+ port_info->vl_cap__init_type = ( IB_VL_0 << 4 );
+ port_info->init_type_reply__mtu_cap = IB_MTU_2048;
+ port_info->operational_vls__enforcement = ( IB_VL_0 << 4 );
+ port_info->guid_cap = 1;
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send PortInfo GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/**
+ * Set partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @ret rc Return status code
+ */
+static int ib_sma_set_pkey_table ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad ) {
+ struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
+ int rc;
+
+ /* Set parameters */
+ ibdev->pkey = ntohs ( pkey_table->pkey[0] );
+ DBGC ( mi, "SMA %p set pkey %04x\n", mi, ibdev->pkey );
+
+ /* Update parameters on device */
+ if ( ( rc = ib_set_pkey_table ( ibdev, mad ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not set pkey table: %s\n",
+ mi, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @v mad Received MAD
+ * @v av Source address vector
+ */
+static void ib_sma_pkey_table ( struct ib_device *ibdev,
+ struct ib_mad_interface *mi,
+ union ib_mad *mad,
+ struct ib_address_vector *av ) {
+ struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
+ int rc;
+
+ /* Set parameters, if applicable */
+ if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
+ if ( ( rc = ib_sma_set_pkey_table ( ibdev, mi, mad ) ) != 0 ) {
+ mad->hdr.status =
+ htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
+ /* Fall through to generate GetResponse */
+ }
+ }
+
+ /* Fill in information */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ memset ( pkey_table, 0, sizeof ( *pkey_table ) );
+ pkey_table->pkey[0] = htons ( ibdev->pkey );
+
+ /* Send GetResponse */
+ mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
+ if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
+ DBGC ( mi, "SMA %p could not send PKeyTable GetResponse: %s\n",
+ mi, strerror ( rc ) );
+ return;
+ }
+}
+
+/** Subnet management agent */
+struct ib_mad_agent ib_sma_agent[] __ib_mad_agent = {
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_NODE_INFO ),
+ .handle = ib_sma_node_info,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_NODE_DESC ),
+ .handle = ib_sma_node_desc,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_GUID_INFO ),
+ .handle = ib_sma_guid_info,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ),
+ .handle = ib_sma_port_info,
+ },
+ {
+ .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
+ .class_version = IB_SMP_CLASS_VERSION,
+ .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ),
+ .handle = ib_sma_pkey_table,
+ },
+};
+
+/**
+ * Create subnet management agent and interface
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ * @ret rc Return status code
+ */
+int ib_create_sma ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
+
+ /* Nothing to do */
+ DBGC ( ibdev, "IBDEV %p SMA using SMI %p\n", ibdev, mi );
+
+ return 0;
+}
+
+/**
+ * Destroy subnet management agent and interface
+ *
+ * @v ibdev Infiniband device
+ * @v mi Management interface
+ */
+void ib_destroy_sma ( struct ib_device *ibdev __unused,
+ struct ib_mad_interface *mi __unused ) {
+ /* Nothing to do */
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_smc.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_smc.c
new file mode 100644
index 0000000..d308dd9
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_smc.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_smc.h>
+
+/**
+ * @file
+ *
+ * Infiniband Subnet Management Client
+ *
+ */
+
+/**
+ * Get port information
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_port_info ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Construct MAD */
+ memset ( mad, 0, sizeof ( *mad ) );
+ mad->hdr.base_version = IB_MGMT_BASE_VERSION;
+ mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+ mad->hdr.class_version = 1;
+ mad->hdr.method = IB_MGMT_METHOD_GET;
+ mad->hdr.attr_id = htons ( IB_SMP_ATTR_PORT_INFO );
+ mad->hdr.attr_mod = htonl ( ibdev->port );
+
+ if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not get port info: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get GUID information
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_guid_info ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Construct MAD */
+ memset ( mad, 0, sizeof ( *mad ) );
+ mad->hdr.base_version = IB_MGMT_BASE_VERSION;
+ mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+ mad->hdr.class_version = 1;
+ mad->hdr.method = IB_MGMT_METHOD_GET;
+ mad->hdr.attr_id = htons ( IB_SMP_ATTR_GUID_INFO );
+
+ if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not get GUID info: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get partition key table
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @v mad Management datagram to fill in
+ * @ret rc Return status code
+ */
+static int ib_smc_get_pkey_table ( struct ib_device *ibdev,
+ ib_local_mad_t local_mad,
+ union ib_mad *mad ) {
+ int rc;
+
+ /* Construct MAD */
+ memset ( mad, 0, sizeof ( *mad ) );
+ mad->hdr.base_version = IB_MGMT_BASE_VERSION;
+ mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+ mad->hdr.class_version = 1;
+ mad->hdr.method = IB_MGMT_METHOD_GET;
+ mad->hdr.attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE );
+
+ if ( ( rc = local_mad ( ibdev, mad ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p could not get pkey table: %s\n",
+ ibdev, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+}
+
+/**
+ * Get MAD parameters
+ *
+ * @v ibdev Infiniband device
+ * @v local_mad Method for issuing local MADs
+ * @ret rc Return status code
+ */
+int ib_smc_update ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
+ union ib_mad mad;
+ struct ib_port_info *port_info = &mad.smp.smp_data.port_info;
+ struct ib_guid_info *guid_info = &mad.smp.smp_data.guid_info;
+ struct ib_pkey_table *pkey_table = &mad.smp.smp_data.pkey_table;
+ int rc;
+
+ /* Port info gives us the link state, the first half of the
+ * port GID and the SM LID.
+ */
+ if ( ( rc = ib_smc_get_port_info ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix,
+ sizeof ( ibdev->gid.u.half[0] ) );
+ ibdev->lid = ntohs ( port_info->lid );
+ ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
+ ibdev->link_width_enabled = port_info->link_width_enabled;
+ ibdev->link_width_supported = port_info->link_width_supported;
+ ibdev->link_width_active = port_info->link_width_active;
+ ibdev->link_speed_supported =
+ ( port_info->link_speed_supported__port_state >> 4 );
+ ibdev->port_state =
+ ( port_info->link_speed_supported__port_state & 0xf );
+ ibdev->link_speed_active =
+ ( port_info->link_speed_active__link_speed_enabled >> 4 );
+ ibdev->link_speed_enabled =
+ ( port_info->link_speed_active__link_speed_enabled & 0xf );
+ ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
+
+ /* GUID info gives us the second half of the port GID */
+ if ( ( rc = ib_smc_get_guid_info ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ memcpy ( &ibdev->gid.u.half[1], guid_info->guid[0],
+ sizeof ( ibdev->gid.u.half[1] ) );
+
+ /* Get partition key */
+ if ( ( rc = ib_smc_get_pkey_table ( ibdev, local_mad, &mad ) ) != 0 )
+ return rc;
+ ibdev->pkey = ntohs ( pkey_table->pkey[0] );
+
+ DBGC ( ibdev, "IBDEV %p port GID is %08x:%08x:%08x:%08x\n", ibdev,
+ htonl ( ibdev->gid.u.dwords[0] ),
+ htonl ( ibdev->gid.u.dwords[1] ),
+ htonl ( ibdev->gid.u.dwords[2] ),
+ htonl ( ibdev->gid.u.dwords[3] ) );
+
+ return 0;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_srp.c b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_srp.c
new file mode 100644
index 0000000..4191c86
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/infiniband/ib_srp.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <stdlib.h>
+#include <errno.h>
+#include <gpxe/srp.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_cmrc.h>
+#include <gpxe/ib_srp.h>
+
+/**
+ * @file
+ *
+ * SCSI RDMA Protocol over Infiniband
+ *
+ */
+
+/* Disambiguate the various possible EINVALs */
+#define EINVAL_BYTE_STRING_LEN ( EINVAL | EUNIQ_01 )
+#define EINVAL_BYTE_STRING ( EINVAL | EUNIQ_02 )
+#define EINVAL_INTEGER ( EINVAL | EUNIQ_03 )
+#define EINVAL_RP_TOO_SHORT ( EINVAL | EUNIQ_04 )
+
+/** IB SRP parse flags */
+enum ib_srp_parse_flags {
+ IB_SRP_PARSE_REQUIRED = 0x0000,
+ IB_SRP_PARSE_OPTIONAL = 0x8000,
+ IB_SRP_PARSE_FLAG_MASK = 0xf000,
+};
+
+/** IB SRP root path parameters */
+struct ib_srp_root_path {
+ /** SCSI LUN */
+ struct scsi_lun *lun;
+ /** SRP port IDs */
+ struct srp_port_ids *port_ids;
+ /** IB SRP parameters */
+ struct ib_srp_parameters *ib;
+};
+
+/**
+ * Parse IB SRP root path byte-string value
+ *
+ * @v rp_comp Root path component string
+ * @v default_value Default value to use if component string is empty
+ * @ret value Value
+ */
+static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
+ unsigned int size_flags ) {
+ size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
+ size_t rp_comp_len = strlen ( rp_comp );
+ char buf[3];
+ char *buf_end;
+
+ /* Allow optional components to be empty */
+ if ( ( rp_comp_len == 0 ) &&
+ ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
+ return 0;
+
+ /* Check string length */
+ if ( rp_comp_len != ( 2 * size ) )
+ return -EINVAL_BYTE_STRING_LEN;
+
+ /* Parse byte string */
+ for ( ; size ; size--, rp_comp += 2, bytes++ ) {
+ memcpy ( buf, rp_comp, 2 );
+ buf[2] = '\0';
+ *bytes = strtoul ( buf, &buf_end, 16 );
+ if ( buf_end != &buf[2] )
+ return -EINVAL_BYTE_STRING;
+ }
+ return 0;
+}
+
+/**
+ * Parse IB SRP root path integer value
+ *
+ * @v rp_comp Root path component string
+ * @v default_value Default value to use if component string is empty
+ * @ret value Value
+ */
+static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
+ int value;
+ char *end;
+
+ value = strtoul ( rp_comp, &end, 16 );
+ if ( *end )
+ return -EINVAL_INTEGER;
+
+ if ( end == rp_comp )
+ return default_value;
+
+ return value;
+}
+
+/**
+ * Parse IB SRP root path literal component
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_literal ( const char *rp_comp __unused,
+ struct ib_srp_root_path *rp __unused ) {
+ /* Ignore */
+ return 0;
+}
+
+/**
+ * Parse IB SRP root path source GID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_sgid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ struct ib_device *ibdev;
+
+ /* Default to the GID of the last opened Infiniband device */
+ if ( ( ibdev = last_opened_ibdev() ) != NULL )
+ memcpy ( &rp->ib->sgid, &ibdev->gid, sizeof ( rp->ib->sgid ) );
+
+ return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
+ ( sizeof ( rp->ib->sgid ) |
+ IB_SRP_PARSE_OPTIONAL ) );
+}
+
+/**
+ * Parse IB SRP root path initiator identifier extension
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ struct ib_srp_initiator_port_id *port_id =
+ ib_srp_initiator_port_id ( rp->port_ids );
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
+ ( sizeof ( port_id->id_ext ) |
+ IB_SRP_PARSE_OPTIONAL ) );
+}
+
+/**
+ * Parse IB SRP root path initiator HCA GUID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ struct ib_srp_initiator_port_id *port_id =
+ ib_srp_initiator_port_id ( rp->port_ids );
+
+ /* Default to the GUID portion of the source GID */
+ memcpy ( &port_id->hca_guid, &rp->ib->sgid.u.half[1],
+ sizeof ( port_id->hca_guid ) );
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->hca_guid.u.bytes,
+ ( sizeof ( port_id->hca_guid ) |
+ IB_SRP_PARSE_OPTIONAL ) );
+}
+
+/**
+ * Parse IB SRP root path destination GID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_dgid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ return ib_srp_parse_byte_string ( rp_comp, rp->ib->dgid.u.bytes,
+ ( sizeof ( rp->ib->dgid ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/**
+ * Parse IB SRP root path partition key
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_pkey ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ int pkey;
+
+ if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_NONE ) ) < 0 )
+ return pkey;
+ rp->ib->pkey = pkey;
+ return 0;
+}
+
+/**
+ * Parse IB SRP root path service ID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_service_id ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ return ib_srp_parse_byte_string ( rp_comp, rp->ib->service_id.u.bytes,
+ ( sizeof ( rp->ib->service_id ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/**
+ * Parse IB SRP root path LUN
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_lun ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ return scsi_parse_lun ( rp_comp, rp->lun );
+}
+
+/**
+ * Parse IB SRP root path target identifier extension
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_target_id_ext ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ struct ib_srp_target_port_id *port_id =
+ ib_srp_target_port_id ( rp->port_ids );
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
+ ( sizeof ( port_id->id_ext ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/**
+ * Parse IB SRP root path target I/O controller GUID
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
+ struct ib_srp_root_path *rp ) {
+ struct ib_srp_target_port_id *port_id =
+ ib_srp_target_port_id ( rp->port_ids );
+
+ return ib_srp_parse_byte_string ( rp_comp, port_id->ioc_guid.u.bytes,
+ ( sizeof ( port_id->ioc_guid ) |
+ IB_SRP_PARSE_REQUIRED ) );
+}
+
+/** IB SRP root path component parser */
+struct ib_srp_root_path_parser {
+ /**
+ * Parse IB SRP root path component
+ *
+ * @v rp_comp Root path component string
+ * @v rp IB SRP root path
+ * @ret rc Return status code
+ */
+ int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
+};
+
+/** IB SRP root path components */
+static struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
+ { ib_srp_parse_literal },
+ { ib_srp_parse_sgid },
+ { ib_srp_parse_initiator_id_ext },
+ { ib_srp_parse_initiator_hca_guid },
+ { ib_srp_parse_dgid },
+ { ib_srp_parse_pkey },
+ { ib_srp_parse_service_id },
+ { ib_srp_parse_lun },
+ { ib_srp_parse_target_id_ext },
+ { ib_srp_parse_target_ioc_guid },
+};
+
+/** Number of IB SRP root path components */
+#define IB_SRP_NUM_RP_COMPONENTS \
+ ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
+
+/**
+ * Parse IB SRP root path
+ *
+ * @v srp SRP device
+ * @v rp_string Root path
+ * @ret rc Return status code
+ */
+static int ib_srp_parse_root_path ( struct srp_device *srp,
+ const char *rp_string ) {
+ struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
+ struct ib_srp_root_path rp = {
+ .lun = &srp->lun,
+ .port_ids = &srp->port_ids,
+ .ib = ib_params,
+ };
+ char rp_string_copy[ strlen ( rp_string ) + 1 ];
+ char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
+ char *rp_string_tmp = rp_string_copy;
+ unsigned int i = 0;
+ int rc;
+
+ /* Split root path into component parts */
+ strcpy ( rp_string_copy, rp_string );
+ while ( 1 ) {
+ rp_comp[i++] = rp_string_tmp;
+ if ( i == IB_SRP_NUM_RP_COMPONENTS )
+ break;
+ for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
+ if ( ! *rp_string_tmp ) {
+ DBGC ( srp, "SRP %p root path \"%s\" too "
+ "short\n", srp, rp_string );
+ return -EINVAL_RP_TOO_SHORT;
+ }
+ }
+ *(rp_string_tmp++) = '\0';
+ }
+
+ /* Parse root path components */
+ for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
+ if ( ( rc = ib_srp_rp_parser[i].parse ( rp_comp[i],
+ &rp ) ) != 0 ) {
+ DBGC ( srp, "SRP %p could not parse \"%s\" in root "
+ "path \"%s\": %s\n", srp, rp_comp[i],
+ rp_string, strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Connect IB SRP session
+ *
+ * @v srp SRP device
+ * @ret rc Return status code
+ */
+static int ib_srp_connect ( struct srp_device *srp ) {
+ struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
+ struct ib_device *ibdev;
+ int rc;
+
+ /* Identify Infiniband device */
+ ibdev = find_ibdev ( &ib_params->sgid );
+ if ( ! ibdev ) {
+ DBGC ( srp, "SRP %p could not identify Infiniband device\n",
+ srp );
+ return -ENODEV;
+ }
+
+ /* Configure remaining SRP parameters */
+ srp->memory_handle = ibdev->rdma_key;
+
+ /* Open CMRC socket */
+ if ( ( rc = ib_cmrc_open ( &srp->socket, ibdev, &ib_params->dgid,
+ &ib_params->service_id ) ) != 0 ) {
+ DBGC ( srp, "SRP %p could not open CMRC socket: %s\n",
+ srp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/** IB SRP transport type */
+struct srp_transport_type ib_srp_transport = {
+ .priv_len = sizeof ( struct ib_srp_parameters ),
+ .parse_root_path = ib_srp_parse_root_path,
+ .connect = ib_srp_connect,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/iobpad.c b/debian/grub-extras/disabled/gpxe/src/net/iobpad.c
new file mode 100644
index 0000000..cbae221
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/iobpad.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * I/O buffer padding
+ *
+ */
+
+#include <string.h>
+#include <gpxe/iobuf.h>
+
+/**
+ * Pad I/O buffer
+ *
+ * @v iobuf I/O buffer
+ * @v min_len Minimum length
+ *
+ * This function pads and aligns I/O buffers, for devices that
+ * aren't capable of padding in hardware, or that require specific
+ * alignment in TX buffers. The packet data will end up aligned to a
+ * multiple of @c IOB_ALIGN.
+ *
+ * @c min_len must not exceed @v IOB_ZLEN.
+ */
+void iob_pad ( struct io_buffer *iobuf, size_t min_len ) {
+ void *data;
+ size_t len;
+ size_t headroom;
+ signed int pad_len;
+
+ assert ( min_len <= IOB_ZLEN );
+
+ /* Move packet data to start of I/O buffer. This will both
+ * align the data (since I/O buffers are aligned to
+ * IOB_ALIGN) and give us sufficient space for the
+ * zero-padding
+ */
+ data = iobuf->data;
+ len = iob_len ( iobuf );
+ headroom = iob_headroom ( iobuf );
+ iob_push ( iobuf, headroom );
+ memmove ( iobuf->data, data, len );
+ iob_unput ( iobuf, headroom );
+
+ /* Pad to minimum packet length */
+ pad_len = ( min_len - iob_len ( iobuf ) );
+ if ( pad_len > 0 )
+ memset ( iob_put ( iobuf, pad_len ), 0, pad_len );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/ipv4.c b/debian/grub-extras/disabled/gpxe/src/net/ipv4.c
new file mode 100644
index 0000000..d0c2015
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/ipv4.c
@@ -0,0 +1,635 @@
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/list.h>
+#include <gpxe/in.h>
+#include <gpxe/arp.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/ip.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/settings.h>
+
+/** @file
+ *
+ * IPv4 protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* Unique IP datagram identification number */
+static uint16_t next_ident = 0;
+
+struct net_protocol ipv4_protocol;
+
+/** List of IPv4 miniroutes */
+struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
+
+/** List of fragment reassembly buffers */
+static LIST_HEAD ( frag_buffers );
+
+/**
+ * Add IPv4 minirouting table entry
+ *
+ * @v netdev Network device
+ * @v address IPv4 address
+ * @v netmask Subnet mask
+ * @v gateway Gateway address (or @c INADDR_NONE for no gateway)
+ * @ret miniroute Routing table entry, or NULL
+ */
+static struct ipv4_miniroute * __malloc
+add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address,
+ struct in_addr netmask, struct in_addr gateway ) {
+ struct ipv4_miniroute *miniroute;
+
+ DBG ( "IPv4 add %s", inet_ntoa ( address ) );
+ DBG ( "/%s ", inet_ntoa ( netmask ) );
+ if ( gateway.s_addr != INADDR_NONE )
+ DBG ( "gw %s ", inet_ntoa ( gateway ) );
+ DBG ( "via %s\n", netdev->name );
+
+ /* Allocate and populate miniroute structure */
+ miniroute = malloc ( sizeof ( *miniroute ) );
+ if ( ! miniroute ) {
+ DBG ( "IPv4 could not add miniroute\n" );
+ return NULL;
+ }
+
+ /* Record routing information */
+ miniroute->netdev = netdev_get ( netdev );
+ miniroute->address = address;
+ miniroute->netmask = netmask;
+ miniroute->gateway = gateway;
+
+ /* Add to end of list if we have a gateway, otherwise
+ * to start of list.
+ */
+ if ( gateway.s_addr != INADDR_NONE ) {
+ list_add_tail ( &miniroute->list, &ipv4_miniroutes );
+ } else {
+ list_add ( &miniroute->list, &ipv4_miniroutes );
+ }
+
+ return miniroute;
+}
+
+/**
+ * Delete IPv4 minirouting table entry
+ *
+ * @v miniroute Routing table entry
+ */
+static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
+
+ DBG ( "IPv4 del %s", inet_ntoa ( miniroute->address ) );
+ DBG ( "/%s ", inet_ntoa ( miniroute->netmask ) );
+ if ( miniroute->gateway.s_addr != INADDR_NONE )
+ DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) );
+ DBG ( "via %s\n", miniroute->netdev->name );
+
+ netdev_put ( miniroute->netdev );
+ list_del ( &miniroute->list );
+ free ( miniroute );
+}
+
+/**
+ * Perform IPv4 routing
+ *
+ * @v dest Final destination address
+ * @ret dest Next hop destination address
+ * @ret miniroute Routing table entry to use, or NULL if no route
+ *
+ * If the route requires use of a gateway, the next hop destination
+ * address will be overwritten with the gateway address.
+ */
+static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) {
+ struct ipv4_miniroute *miniroute;
+ int local;
+ int has_gw;
+
+ /* Never attempt to route the broadcast address */
+ if ( dest->s_addr == INADDR_BROADCAST )
+ return NULL;
+
+ /* Find first usable route in routing table */
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ local = ( ( ( dest->s_addr ^ miniroute->address.s_addr )
+ & miniroute->netmask.s_addr ) == 0 );
+ has_gw = ( miniroute->gateway.s_addr != INADDR_NONE );
+ if ( local || has_gw ) {
+ if ( ! local )
+ *dest = miniroute->gateway;
+ return miniroute;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Fragment reassembly counter timeout
+ *
+ * @v timer Retry timer
+ * @v over If asserted, the timer is greater than @c MAX_TIMEOUT
+ */
+static void ipv4_frag_expired ( struct retry_timer *timer __unused,
+ int over ) {
+ if ( over ) {
+ DBG ( "Fragment reassembly timeout" );
+ /* Free the fragment buffer */
+ }
+}
+
+/**
+ * Free fragment buffer
+ *
+ * @v fragbug Fragment buffer
+ */
+static void free_fragbuf ( struct frag_buffer *fragbuf ) {
+ free ( fragbuf );
+}
+
+/**
+ * Fragment reassembler
+ *
+ * @v iobuf I/O buffer, fragment of the datagram
+ * @ret frag_iob Reassembled packet, or NULL
+ */
+static struct io_buffer * ipv4_reassemble ( struct io_buffer * iobuf ) {
+ struct iphdr *iphdr = iobuf->data;
+ struct frag_buffer *fragbuf;
+
+ /**
+ * Check if the fragment belongs to any fragment series
+ */
+ list_for_each_entry ( fragbuf, &frag_buffers, list ) {
+ if ( fragbuf->ident == iphdr->ident &&
+ fragbuf->src.s_addr == iphdr->src.s_addr ) {
+ /**
+ * Check if the packet is the expected fragment
+ *
+ * The offset of the new packet must be equal to the
+ * length of the data accumulated so far (the length of
+ * the reassembled I/O buffer
+ */
+ if ( iob_len ( fragbuf->frag_iob ) ==
+ ( iphdr->frags & IP_MASK_OFFSET ) ) {
+ /**
+ * Append the contents of the fragment to the
+ * reassembled I/O buffer
+ */
+ iob_pull ( iobuf, sizeof ( *iphdr ) );
+ memcpy ( iob_put ( fragbuf->frag_iob,
+ iob_len ( iobuf ) ),
+ iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iobuf );
+
+ /** Check if the fragment series is over */
+ if ( ! ( iphdr->frags & IP_MASK_MOREFRAGS ) ) {
+ iobuf = fragbuf->frag_iob;
+ free_fragbuf ( fragbuf );
+ return iobuf;
+ }
+
+ } else {
+ /* Discard the fragment series */
+ free_fragbuf ( fragbuf );
+ free_iob ( iobuf );
+ }
+ return NULL;
+ }
+ }
+
+ /** Check if the fragment is the first in the fragment series */
+ if ( iphdr->frags & IP_MASK_MOREFRAGS &&
+ ( ( iphdr->frags & IP_MASK_OFFSET ) == 0 ) ) {
+
+ /** Create a new fragment buffer */
+ fragbuf = ( struct frag_buffer* ) malloc ( sizeof( *fragbuf ) );
+ fragbuf->ident = iphdr->ident;
+ fragbuf->src = iphdr->src;
+
+ /* Set up the reassembly I/O buffer */
+ fragbuf->frag_iob = alloc_iob ( IP_FRAG_IOB_SIZE );
+ iob_pull ( iobuf, sizeof ( *iphdr ) );
+ memcpy ( iob_put ( fragbuf->frag_iob, iob_len ( iobuf ) ),
+ iobuf->data, iob_len ( iobuf ) );
+ free_iob ( iobuf );
+
+ /* Set the reassembly timer */
+ fragbuf->frag_timer.timeout = IP_FRAG_TIMEOUT;
+ fragbuf->frag_timer.expired = ipv4_frag_expired;
+ start_timer ( &fragbuf->frag_timer );
+
+ /* Add the fragment buffer to the list of fragment buffers */
+ list_add ( &fragbuf->list, &frag_buffers );
+ }
+
+ return NULL;
+}
+
+/**
+ * Add IPv4 pseudo-header checksum to existing checksum
+ *
+ * @v iobuf I/O buffer
+ * @v csum Existing checksum
+ * @ret csum Updated checksum
+ */
+static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) {
+ struct ipv4_pseudo_header pshdr;
+ struct iphdr *iphdr = iobuf->data;
+ size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+
+ /* Build pseudo-header */
+ pshdr.src = iphdr->src;
+ pshdr.dest = iphdr->dest;
+ pshdr.zero_padding = 0x00;
+ pshdr.protocol = iphdr->protocol;
+ pshdr.len = htons ( iob_len ( iobuf ) - hdrlen );
+
+ /* Update the checksum value */
+ return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
+}
+
+/**
+ * Determine link-layer address
+ *
+ * @v dest IPv4 destination address
+ * @v src IPv4 source address
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address buffer
+ * @ret rc Return status code
+ */
+static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
+ struct net_device *netdev, uint8_t *ll_dest ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+
+ if ( dest.s_addr == INADDR_BROADCAST ) {
+ /* Broadcast address */
+ memcpy ( ll_dest, netdev->ll_broadcast,
+ ll_protocol->ll_addr_len );
+ return 0;
+ } else if ( IN_MULTICAST ( ntohl ( dest.s_addr ) ) ) {
+ return ll_protocol->mc_hash ( AF_INET, &dest, ll_dest );
+ } else {
+ /* Unicast address: resolve via ARP */
+ return arp_resolve ( netdev, &ipv4_protocol, &dest,
+ &src, ll_dest );
+ }
+}
+
+/**
+ * Transmit IP packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip Transport-layer protocol
+ * @v st_src Source network-layer address
+ * @v st_dest Destination network-layer address
+ * @v netdev Network device to use if no route found, or NULL
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Status
+ *
+ * This function expects a transport-layer segment and prepends the IP header
+ */
+static int ipv4_tx ( struct io_buffer *iobuf,
+ struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev,
+ uint16_t *trans_csum ) {
+ struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
+ struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
+ struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
+ struct ipv4_miniroute *miniroute;
+ struct in_addr next_hop;
+ uint8_t ll_dest[MAX_LL_ADDR_LEN];
+ int rc;
+
+ /* Fill up the IP header, except source address */
+ memset ( iphdr, 0, sizeof ( *iphdr ) );
+ iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
+ iphdr->service = IP_TOS;
+ iphdr->len = htons ( iob_len ( iobuf ) );
+ iphdr->ident = htons ( ++next_ident );
+ iphdr->ttl = IP_TTL;
+ iphdr->protocol = tcpip_protocol->tcpip_proto;
+ iphdr->dest = sin_dest->sin_addr;
+
+ /* Use routing table to identify next hop and transmitting netdev */
+ next_hop = iphdr->dest;
+ if ( sin_src )
+ iphdr->src = sin_src->sin_addr;
+ if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
+ ( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) &&
+ ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
+ iphdr->src = miniroute->address;
+ netdev = miniroute->netdev;
+ }
+ if ( ! netdev ) {
+ DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
+ rc = -ENETUNREACH;
+ goto err;
+ }
+
+ /* Determine link-layer destination address */
+ if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev,
+ ll_dest ) ) != 0 ) {
+ DBG ( "IPv4 has no link-layer address for %s: %s\n",
+ inet_ntoa ( next_hop ), strerror ( rc ) );
+ goto err;
+ }
+
+ /* Fix up checksums */
+ if ( trans_csum )
+ *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum );
+ iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
+
+ /* Print IP4 header for debugging */
+ DBG ( "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
+ DBG ( "%s len %d proto %d id %04x csum %04x\n",
+ inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ), iphdr->protocol,
+ ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
+
+ /* Hand off to link layer */
+ if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest ) ) != 0 ) {
+ DBG ( "IPv4 could not transmit packet via %s: %s\n",
+ netdev->name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+
+ err:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Process incoming packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer destination source
+ *
+ * This function expects an IP4 network datagram. It processes the headers
+ * and sends it to the transport layer.
+ */
+static int ipv4_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused,
+ const void *ll_source __unused ) {
+ struct iphdr *iphdr = iobuf->data;
+ size_t hdrlen;
+ size_t len;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr_tcpip st;
+ } src, dest;
+ uint16_t csum;
+ uint16_t pshdr_csum;
+ int rc;
+
+ /* Sanity check the IPv4 header */
+ if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
+ DBG ( "IPv4 packet too short at %zd bytes (min %zd bytes)\n",
+ iob_len ( iobuf ), sizeof ( *iphdr ) );
+ goto err;
+ }
+ if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
+ DBG ( "IPv4 version %#02x not supported\n", iphdr->verhdrlen );
+ goto err;
+ }
+ hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+ if ( hdrlen < sizeof ( *iphdr ) ) {
+ DBG ( "IPv4 header too short at %zd bytes (min %zd bytes)\n",
+ hdrlen, sizeof ( *iphdr ) );
+ goto err;
+ }
+ if ( hdrlen > iob_len ( iobuf ) ) {
+ DBG ( "IPv4 header too long at %zd bytes "
+ "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
+ goto err;
+ }
+ if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
+ DBG ( "IPv4 checksum incorrect (is %04x including checksum "
+ "field, should be 0000)\n", csum );
+ goto err;
+ }
+ len = ntohs ( iphdr->len );
+ if ( len < hdrlen ) {
+ DBG ( "IPv4 length too short at %zd bytes "
+ "(header is %zd bytes)\n", len, hdrlen );
+ goto err;
+ }
+ if ( len > iob_len ( iobuf ) ) {
+ DBG ( "IPv4 length too long at %zd bytes "
+ "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
+ goto err;
+ }
+
+ /* Print IPv4 header for debugging */
+ DBG ( "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
+ DBG ( "%s len %d proto %d id %04x csum %04x\n",
+ inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol,
+ ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
+
+ /* Truncate packet to correct length, calculate pseudo-header
+ * checksum and then strip off the IPv4 header.
+ */
+ iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
+ pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
+ iob_pull ( iobuf, hdrlen );
+
+ /* Fragment reassembly */
+ if ( ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) ) ||
+ ( ( iphdr->frags & htons ( IP_MASK_OFFSET ) ) != 0 ) ) {
+ /* Pass the fragment to ipv4_reassemble() which either
+ * returns a fully reassembled I/O buffer or NULL.
+ */
+ iobuf = ipv4_reassemble ( iobuf );
+ if ( ! iobuf )
+ return 0;
+ }
+
+ /* Construct socket addresses and hand off to transport layer */
+ memset ( &src, 0, sizeof ( src ) );
+ src.sin.sin_family = AF_INET;
+ src.sin.sin_addr = iphdr->src;
+ memset ( &dest, 0, sizeof ( dest ) );
+ dest.sin.sin_family = AF_INET;
+ dest.sin.sin_addr = iphdr->dest;
+ if ( ( rc = tcpip_rx ( iobuf, iphdr->protocol, &src.st,
+ &dest.st, pshdr_csum ) ) != 0 ) {
+ DBG ( "IPv4 received packet rejected by stack: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+
+ err:
+ free_iob ( iobuf );
+ return -EINVAL;
+}
+
+/**
+ * Check existence of IPv4 address for ARP
+ *
+ * @v netdev Network device
+ * @v net_addr Network-layer address
+ * @ret rc Return status code
+ */
+static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
+ const struct in_addr *address = net_addr;
+ struct ipv4_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ if ( ( miniroute->netdev == netdev ) &&
+ ( miniroute->address.s_addr == address->s_addr ) ) {
+ /* Found matching address */
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+/**
+ * Convert IPv4 address to dotted-quad notation
+ *
+ * @v in IP address
+ * @ret string IP address in dotted-quad notation
+ */
+char * inet_ntoa ( struct in_addr in ) {
+ static char buf[16]; /* "xxx.xxx.xxx.xxx" */
+ uint8_t *bytes = ( uint8_t * ) &in;
+
+ snprintf ( buf, sizeof (buf), "%d.%d.%d.%d",
+ bytes[0], bytes[1], bytes[2], bytes[3] );
+ return buf;
+}
+
+/**
+ * Transcribe IP address
+ *
+ * @v net_addr IP address
+ * @ret string IP address in dotted-quad notation
+ *
+ */
+static const char * ipv4_ntoa ( const void *net_addr ) {
+ return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
+}
+
+/** IPv4 protocol */
+struct net_protocol ipv4_protocol __net_protocol = {
+ .name = "IP",
+ .net_proto = htons ( ETH_P_IP ),
+ .net_addr_len = sizeof ( struct in_addr ),
+ .rx = ipv4_rx,
+ .ntoa = ipv4_ntoa,
+};
+
+/** IPv4 TCPIP net protocol */
+struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
+ .name = "IPv4",
+ .sa_family = AF_INET,
+ .tx = ipv4_tx,
+};
+
+/** IPv4 ARP protocol */
+struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol = {
+ .net_protocol = &ipv4_protocol,
+ .check = ipv4_arp_check,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** IPv4 address setting */
+struct setting ip_setting __setting = {
+ .name = "ip",
+ .description = "IPv4 address",
+ .tag = DHCP_EB_YIADDR,
+ .type = &setting_type_ipv4,
+};
+
+/** IPv4 subnet mask setting */
+struct setting netmask_setting __setting = {
+ .name = "netmask",
+ .description = "IPv4 subnet mask",
+ .tag = DHCP_SUBNET_MASK,
+ .type = &setting_type_ipv4,
+};
+
+/** Default gateway setting */
+struct setting gateway_setting __setting = {
+ .name = "gateway",
+ .description = "Default gateway",
+ .tag = DHCP_ROUTERS,
+ .type = &setting_type_ipv4,
+};
+
+/**
+ * Create IPv4 routing table based on configured settings
+ *
+ * @ret rc Return status code
+ */
+static int ipv4_create_routes ( void ) {
+ struct ipv4_miniroute *miniroute;
+ struct ipv4_miniroute *tmp;
+ struct net_device *netdev;
+ struct settings *settings;
+ struct in_addr address = { 0 };
+ struct in_addr netmask = { 0 };
+ struct in_addr gateway = { INADDR_NONE };
+
+ /* Delete all existing routes */
+ list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
+ del_ipv4_miniroute ( miniroute );
+
+ /* Create a route for each configured network device */
+ for_each_netdev ( netdev ) {
+ settings = netdev_settings ( netdev );
+ /* Get IPv4 address */
+ address.s_addr = 0;
+ fetch_ipv4_setting ( settings, &ip_setting, &address );
+ if ( ! address.s_addr )
+ continue;
+ /* Calculate default netmask */
+ if ( IN_CLASSA ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSA_NET );
+ } else if ( IN_CLASSB ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSB_NET );
+ } else if ( IN_CLASSC ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSC_NET );
+ } else {
+ netmask.s_addr = 0;
+ }
+ /* Override with subnet mask, if present */
+ fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
+ /* Get default gateway, if present */
+ gateway.s_addr = INADDR_NONE;
+ fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
+ /* Configure route */
+ miniroute = add_ipv4_miniroute ( netdev, address,
+ netmask, gateway );
+ if ( ! miniroute )
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/** IPv4 settings applicator */
+struct settings_applicator ipv4_settings_applicator __settings_applicator = {
+ .apply = ipv4_create_routes,
+};
+
+/* Drag in ICMP */
+REQUIRE_OBJECT ( icmp );
diff --git a/debian/grub-extras/disabled/gpxe/src/net/netdev_settings.c b/debian/grub-extras/disabled/gpxe/src/net/netdev_settings.c
new file mode 100644
index 0000000..b9220f5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/netdev_settings.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/settings.h>
+#include <gpxe/netdevice.h>
+
+/** @file
+ *
+ * Network device configuration settings
+ *
+ */
+
+/** Network device named settings */
+struct setting mac_setting __setting = {
+ .name = "mac",
+ .description = "MAC address",
+ .type = &setting_type_hex,
+};
+
+/**
+ * Store value of network device setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int netdev_store ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ struct net_device *netdev = container_of ( settings, struct net_device,
+ settings.settings );
+
+ if ( setting_cmp ( setting, &mac_setting ) == 0 ) {
+ if ( len != netdev->ll_protocol->ll_addr_len )
+ return -EINVAL;
+ memcpy ( netdev->ll_addr, data, len );
+ return 0;
+ }
+
+ return generic_settings_store ( settings, setting, data, len );
+}
+
+/**
+ * Fetch value of network device setting
+ *
+ * @v settings Settings block
+ * @v setting Setting to fetch
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+static int netdev_fetch ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct net_device *netdev = container_of ( settings, struct net_device,
+ settings.settings );
+
+ if ( setting_cmp ( setting, &mac_setting ) == 0 ) {
+ if ( len > netdev->ll_protocol->ll_addr_len )
+ len = netdev->ll_protocol->ll_addr_len;
+ memcpy ( data, netdev->ll_addr, len );
+ return netdev->ll_protocol->ll_addr_len;
+ }
+
+ return generic_settings_fetch ( settings, setting, data, len );
+}
+
+/**
+ * Clear network device settings
+ *
+ * @v settings Settings block
+ */
+static void netdev_clear ( struct settings *settings ) {
+ generic_settings_clear ( settings );
+}
+
+/** Network device configuration settings operations */
+struct settings_operations netdev_settings_operations = {
+ .store = netdev_store,
+ .fetch = netdev_fetch,
+ .clear = netdev_clear,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/netdevice.c b/debian/grub-extras/disabled/gpxe/src/net/netdevice.c
new file mode 100644
index 0000000..ee0d0b7
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/netdevice.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <byteswap.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/tables.h>
+#include <gpxe/process.h>
+#include <gpxe/init.h>
+#include <gpxe/device.h>
+#include <gpxe/errortab.h>
+#include <gpxe/netdevice.h>
+
+/** @file
+ *
+ * Network device management
+ *
+ */
+
+/** List of network devices */
+struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
+
+/** List of open network devices, in reverse order of opening */
+static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
+
+/** Default link status code */
+#define EUNKNOWN_LINK_STATUS EINPROGRESS
+
+/** Human-readable message for the default link status */
+struct errortab netdev_errors[] __errortab = {
+ { EUNKNOWN_LINK_STATUS, "Unknown" },
+};
+
+/**
+ * Mark network device as having link down
+ *
+ * @v netdev Network device
+ */
+void netdev_link_down ( struct net_device *netdev ) {
+
+ switch ( netdev->link_rc ) {
+ case 0:
+ case -EUNKNOWN_LINK_STATUS:
+ netdev->link_rc = -ENOTCONN;
+ break;
+ default:
+ /* Avoid clobbering a more detailed link status code,
+ * if one is already set.
+ */
+ break;
+ }
+}
+
+/**
+ * Record network device statistic
+ *
+ * @v stats Network device statistics
+ * @v rc Status code
+ */
+static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
+ struct net_device_error *error;
+ struct net_device_error *least_common_error;
+ unsigned int i;
+
+ /* If this is not an error, just update the good counter */
+ if ( rc == 0 ) {
+ stats->good++;
+ return;
+ }
+
+ /* Update the bad counter */
+ stats->bad++;
+
+ /* Locate the appropriate error record */
+ least_common_error = &stats->errors[0];
+ for ( i = 0 ; i < ( sizeof ( stats->errors ) /
+ sizeof ( stats->errors[0] ) ) ; i++ ) {
+ error = &stats->errors[i];
+ /* Update matching record, if found */
+ if ( error->rc == rc ) {
+ error->count++;
+ return;
+ }
+ if ( error->count < least_common_error->count )
+ least_common_error = error;
+ }
+
+ /* Overwrite the least common error record */
+ least_common_error->rc = rc;
+ least_common_error->count = 1;
+}
+
+/**
+ * Transmit raw packet via network device
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * Transmits the packet via the specified network device. This
+ * function takes ownership of the I/O buffer.
+ */
+int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
+ int rc;
+
+ DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
+ netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
+
+ list_add_tail ( &iobuf->list, &netdev->tx_queue );
+
+ if ( ! ( netdev->state & NETDEV_OPEN ) ) {
+ rc = -ENETUNREACH;
+ goto err;
+ }
+
+ if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ netdev_tx_complete_err ( netdev, iobuf, rc );
+ return rc;
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v rc Packet status code
+ *
+ * The packet must currently be in the network device's TX queue.
+ */
+void netdev_tx_complete_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
+
+ /* Update statistics counter */
+ netdev_record_stat ( &netdev->tx_stats, rc );
+ if ( rc == 0 ) {
+ DBGC ( netdev, "NETDEV %p transmission %p complete\n",
+ netdev, iobuf );
+ } else {
+ DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
+ netdev, iobuf, strerror ( rc ) );
+ }
+
+ /* Catch data corruption as early as possible */
+ assert ( iobuf->list.next != NULL );
+ assert ( iobuf->list.prev != NULL );
+
+ /* Dequeue and free I/O buffer */
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v rc Packet status code
+ *
+ * Completes the oldest outstanding packet in the TX queue.
+ */
+void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
+ struct io_buffer *iobuf;
+
+ list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
+ netdev_tx_complete_err ( netdev, iobuf, rc );
+ return;
+ }
+}
+
+/**
+ * Flush device's transmit queue
+ *
+ * @v netdev Network device
+ */
+static void netdev_tx_flush ( struct net_device *netdev ) {
+
+ /* Discard any packets in the TX queue */
+ while ( ! list_empty ( &netdev->tx_queue ) ) {
+ netdev_tx_complete_next_err ( netdev, -ECANCELED );
+ }
+}
+
+/**
+ * Add packet to receive queue
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer, or NULL
+ *
+ * The packet is added to the network device's RX queue. This
+ * function takes ownership of the I/O buffer.
+ */
+void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
+
+ DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
+ netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
+
+ /* Enqueue packet */
+ list_add_tail ( &iobuf->list, &netdev->rx_queue );
+
+ /* Update statistics counter */
+ netdev_record_stat ( &netdev->rx_stats, 0 );
+}
+
+/**
+ * Discard received packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer, or NULL
+ * @v rc Packet status code
+ *
+ * The packet is discarded and an RX error is recorded. This function
+ * takes ownership of the I/O buffer. @c iobuf may be NULL if, for
+ * example, the net device wishes to report an error due to being
+ * unable to allocate an I/O buffer.
+ */
+void netdev_rx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
+
+ DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
+ netdev, iobuf, strerror ( rc ) );
+
+ /* Discard packet */
+ free_iob ( iobuf );
+
+ /* Update statistics counter */
+ netdev_record_stat ( &netdev->rx_stats, rc );
+}
+
+/**
+ * Poll for completed and received packets on network device
+ *
+ * @v netdev Network device
+ *
+ * Polls the network device for completed transmissions and received
+ * packets. Any received packets will be added to the RX packet queue
+ * via netdev_rx().
+ */
+void netdev_poll ( struct net_device *netdev ) {
+
+ if ( netdev->state & NETDEV_OPEN )
+ netdev->op->poll ( netdev );
+}
+
+/**
+ * Remove packet from device's receive queue
+ *
+ * @v netdev Network device
+ * @ret iobuf I/O buffer, or NULL
+ *
+ * Removes the first packet from the device's RX queue and returns it.
+ * Ownership of the packet is transferred to the caller.
+ */
+struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
+ struct io_buffer *iobuf;
+
+ list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
+ list_del ( &iobuf->list );
+ return iobuf;
+ }
+ return NULL;
+}
+
+/**
+ * Flush device's receive queue
+ *
+ * @v netdev Network device
+ */
+static void netdev_rx_flush ( struct net_device *netdev ) {
+ struct io_buffer *iobuf;
+
+ /* Discard any packets in the RX queue */
+ while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
+ netdev_rx_err ( netdev, iobuf, -ECANCELED );
+ }
+}
+
+/**
+ * Free network device
+ *
+ * @v refcnt Network device reference counter
+ */
+static void free_netdev ( struct refcnt *refcnt ) {
+ struct net_device *netdev =
+ container_of ( refcnt, struct net_device, refcnt );
+
+ netdev_tx_flush ( netdev );
+ netdev_rx_flush ( netdev );
+ clear_settings ( netdev_settings ( netdev ) );
+ free ( netdev );
+}
+
+/**
+ * Allocate network device
+ *
+ * @v priv_size Size of private data area (net_device::priv)
+ * @ret netdev Network device, or NULL
+ *
+ * Allocates space for a network device and its private data area.
+ */
+struct net_device * alloc_netdev ( size_t priv_size ) {
+ struct net_device *netdev;
+ size_t total_len;
+
+ total_len = ( sizeof ( *netdev ) + priv_size );
+ netdev = zalloc ( total_len );
+ if ( netdev ) {
+ netdev->refcnt.free = free_netdev;
+ netdev->link_rc = -EUNKNOWN_LINK_STATUS;
+ INIT_LIST_HEAD ( &netdev->tx_queue );
+ INIT_LIST_HEAD ( &netdev->rx_queue );
+ netdev_settings_init ( netdev );
+ netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
+ }
+ return netdev;
+}
+
+/**
+ * Register network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * Gives the network device a name and adds it to the list of network
+ * devices.
+ */
+int register_netdev ( struct net_device *netdev ) {
+ static unsigned int ifindex = 0;
+ int rc;
+
+ /* Create device name */
+ snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
+ ifindex++ );
+
+ /* Set initial link-layer address */
+ netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
+
+ /* Register per-netdev configuration settings */
+ if ( ( rc = register_settings ( netdev_settings ( netdev ),
+ NULL ) ) != 0 ) {
+ DBGC ( netdev, "NETDEV %p could not register settings: %s\n",
+ netdev, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Add to device list */
+ netdev_get ( netdev );
+ list_add_tail ( &netdev->list, &net_devices );
+ DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
+ netdev, netdev->name, netdev->dev->name,
+ netdev_addr ( netdev ) );
+
+ return 0;
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+int netdev_open ( struct net_device *netdev ) {
+ int rc;
+
+ /* Do nothing if device is already open */
+ if ( netdev->state & NETDEV_OPEN )
+ return 0;
+
+ DBGC ( netdev, "NETDEV %p opening\n", netdev );
+
+ /* Open the device */
+ if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
+ return rc;
+
+ /* Mark as opened */
+ netdev->state |= NETDEV_OPEN;
+
+ /* Add to head of open devices list */
+ list_add ( &netdev->open_list, &open_net_devices );
+
+ return 0;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+void netdev_close ( struct net_device *netdev ) {
+
+ /* Do nothing if device is already closed */
+ if ( ! ( netdev->state & NETDEV_OPEN ) )
+ return;
+
+ DBGC ( netdev, "NETDEV %p closing\n", netdev );
+
+ /* Close the device */
+ netdev->op->close ( netdev );
+
+ /* Flush TX and RX queues */
+ netdev_tx_flush ( netdev );
+ netdev_rx_flush ( netdev );
+
+ /* Mark as closed */
+ netdev->state &= ~NETDEV_OPEN;
+
+ /* Remove from open devices list */
+ list_del ( &netdev->open_list );
+}
+
+/**
+ * Unregister network device
+ *
+ * @v netdev Network device
+ *
+ * Removes the network device from the list of network devices.
+ */
+void unregister_netdev ( struct net_device *netdev ) {
+
+ /* Ensure device is closed */
+ netdev_close ( netdev );
+
+ /* Unregister per-netdev configuration settings */
+ unregister_settings ( netdev_settings ( netdev ) );
+
+ /* Remove from device list */
+ list_del ( &netdev->list );
+ netdev_put ( netdev );
+ DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
+}
+
+/** Enable or disable interrupts
+ *
+ * @v netdev Network device
+ * @v enable Interrupts should be enabled
+ */
+void netdev_irq ( struct net_device *netdev, int enable ) {
+ netdev->op->irq ( netdev, enable );
+}
+
+/**
+ * Get network device by name
+ *
+ * @v name Network device name
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * find_netdev ( const char *name ) {
+ struct net_device *netdev;
+
+ list_for_each_entry ( netdev, &net_devices, list ) {
+ if ( strcmp ( netdev->name, name ) == 0 )
+ return netdev;
+ }
+
+ return NULL;
+}
+
+/**
+ * Get network device by PCI bus:dev.fn address
+ *
+ * @v bus_type Bus type
+ * @v location Bus location
+ * @ret netdev Network device, or NULL
+ */
+struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location ) {
+ struct net_device *netdev;
+
+ list_for_each_entry ( netdev, &net_devices, list ) {
+ if ( ( netdev->dev->desc.bus_type == bus_type ) &&
+ ( netdev->dev->desc.location == location ) )
+ return netdev;
+ }
+
+ return NULL;
+}
+
+/**
+ * Get most recently opened network device
+ *
+ * @ret netdev Most recently opened network device, or NULL
+ */
+struct net_device * last_opened_netdev ( void ) {
+ struct net_device *netdev;
+
+ list_for_each_entry ( netdev, &open_net_devices, open_list ) {
+ assert ( netdev->state & NETDEV_OPEN );
+ return netdev;
+ }
+
+ return NULL;
+}
+
+/**
+ * Transmit network-layer packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v net_protocol Network-layer protocol
+ * @v ll_dest Destination link-layer address
+ * @ret rc Return status code
+ *
+ * Prepends link-layer headers to the I/O buffer and transmits the
+ * packet via the specified network device. This function takes
+ * ownership of the I/O buffer.
+ */
+int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
+ struct net_protocol *net_protocol, const void *ll_dest ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ int rc;
+
+ /* Force a poll on the netdevice to (potentially) clear any
+ * backed-up TX completions. This is needed on some network
+ * devices to avoid excessive losses due to small TX ring
+ * sizes.
+ */
+ netdev_poll ( netdev );
+
+ /* Add link-layer header */
+ if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, netdev->ll_addr,
+ net_protocol->net_proto ) ) != 0 ) {
+ free_iob ( iobuf );
+ return rc;
+ }
+
+ /* Transmit packet */
+ return netdev_tx ( netdev, iobuf );
+}
+
+/**
+ * Process received network-layer packet
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v net_proto Network-layer protocol, in network-byte order
+ * @v ll_source Source link-layer address
+ * @ret rc Return status code
+ */
+int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
+ uint16_t net_proto, const void *ll_source ) {
+ struct net_protocol *net_protocol;
+
+ /* Hand off to network-layer protocol, if any */
+ for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
+ if ( net_protocol->net_proto == net_proto )
+ return net_protocol->rx ( iobuf, netdev, ll_source );
+ }
+
+ DBGC ( netdev, "NETDEV %p unknown network protocol %04x\n",
+ netdev, ntohs ( net_proto ) );
+ free_iob ( iobuf );
+ return 0;
+}
+
+/**
+ * Single-step the network stack
+ *
+ * @v process Network stack process
+ *
+ * This polls all interfaces for received packets, and processes
+ * packets from the RX queue.
+ */
+static void net_step ( struct process *process __unused ) {
+ struct net_device *netdev;
+ struct io_buffer *iobuf;
+ struct ll_protocol *ll_protocol;
+ const void *ll_dest;
+ const void *ll_source;
+ uint16_t net_proto;
+ int rc;
+
+ /* Poll and process each network device */
+ list_for_each_entry ( netdev, &net_devices, list ) {
+
+ /* Poll for new packets */
+ netdev_poll ( netdev );
+
+ /* Process at most one received packet. Give priority
+ * to getting packets out of the NIC over processing
+ * the received packets, because we advertise a window
+ * that assumes that we can receive packets from the
+ * NIC faster than they arrive.
+ */
+ if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
+
+ DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
+ netdev, iobuf, iobuf->data,
+ iob_len ( iobuf ) );
+
+ /* Remove link-layer header */
+ ll_protocol = netdev->ll_protocol;
+ if ( ( rc = ll_protocol->pull ( netdev, iobuf,
+ &ll_dest, &ll_source,
+ &net_proto ) ) != 0 ) {
+ free_iob ( iobuf );
+ continue;
+ }
+
+ net_rx ( iobuf, netdev, net_proto, ll_source );
+ }
+ }
+}
+
+/** Networking stack process */
+struct process net_process __permanent_process = {
+ .list = LIST_HEAD_INIT ( net_process.list ),
+ .step = net_step,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/nullnet.c b/debian/grub-extras/disabled/gpxe/src/net/nullnet.c
new file mode 100644
index 0000000..381f02a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/nullnet.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <errno.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+
+/** @file
+ *
+ * Null network device
+ *
+ */
+
+static int null_open ( struct net_device *netdev __unused ) {
+ return -ENODEV;
+};
+
+static void null_close ( struct net_device *netdev __unused ) {
+ /* Do nothing */
+};
+
+static int null_transmit ( struct net_device *netdev __unused,
+ struct io_buffer *iobuf __unused ) {
+ return -ENODEV;
+};
+
+static void null_poll ( struct net_device *netdev __unused ) {
+ /* Do nothing */
+}
+
+static void null_irq ( struct net_device *netdev __unused,
+ int enable __unused ) {
+ /* Do nothing */
+}
+
+struct net_device_operations null_netdev_operations = {
+ .open = null_open,
+ .close = null_close,
+ .transmit = null_transmit,
+ .poll = null_poll,
+ .irq = null_irq,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/rarp.c b/debian/grub-extras/disabled/gpxe/src/net/rarp.c
new file mode 100644
index 0000000..1d0dd96
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/rarp.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/rarp.h>
+
+/** @file
+ *
+ * Reverse Address Resolution Protocol
+ *
+ */
+
+/**
+ * Process incoming ARP packets
+ *
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_source Link-layer source address
+ * @ret rc Return status code
+ *
+ * This is a dummy method which simply discards RARP packets.
+ */
+static int rarp_rx ( struct io_buffer *iobuf,
+ struct net_device *netdev __unused,
+ const void *ll_source __unused ) {
+ free_iob ( iobuf );
+ return 0;
+}
+
+
+/**
+ * Transcribe RARP address
+ *
+ * @v net_addr RARP address
+ * @ret string "<RARP>"
+ *
+ * This operation is meaningless for the RARP protocol.
+ */
+static const char * rarp_ntoa ( const void *net_addr __unused ) {
+ return "<RARP>";
+}
+
+/** RARP protocol */
+struct net_protocol rarp_protocol __net_protocol = {
+ .name = "RARP",
+ .net_proto = htons ( ETH_P_RARP ),
+ .rx = rarp_rx,
+ .ntoa = rarp_ntoa,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/retry.c b/debian/grub-extras/disabled/gpxe/src/net/retry.c
new file mode 100644
index 0000000..40f656f
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/retry.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <gpxe/timer.h>
+#include <gpxe/list.h>
+#include <gpxe/process.h>
+#include <gpxe/init.h>
+#include <gpxe/retry.h>
+
+/** @file
+ *
+ * Retry timers
+ *
+ * A retry timer is a binary exponential backoff timer. It can be
+ * used to build automatic retransmission into network protocols.
+ *
+ * This implementation of the timer is designed to satisfy RFC 2988
+ * and therefore be usable as a TCP retransmission timer.
+ *
+ *
+ */
+
+/* The theoretical minimum that the algorithm in stop_timer() can
+ * adjust the timeout back down to is seven ticks, so set the minimum
+ * timeout to at least that value for the sake of consistency.
+ */
+#define MIN_TIMEOUT 7
+
+/** List of running timers */
+static LIST_HEAD ( timers );
+
+/**
+ * Start timer
+ *
+ * @v timer Retry timer
+ *
+ * This starts the timer running with the current timeout value. If
+ * stop_timer() is not called before the timer expires, the timer will
+ * be stopped and the timer's callback function will be called.
+ */
+void start_timer ( struct retry_timer *timer ) {
+ if ( ! timer->running )
+ list_add ( &timer->list, &timers );
+ timer->start = currticks();
+ timer->running = 1;
+
+ /* 0 means "use default timeout" */
+ if ( timer->min_timeout == 0 )
+ timer->min_timeout = DEFAULT_MIN_TIMEOUT;
+ /* We must never be less than MIN_TIMEOUT under any circumstances */
+ if ( timer->min_timeout < MIN_TIMEOUT )
+ timer->min_timeout = MIN_TIMEOUT;
+ /* Honor user-specified minimum timeout */
+ if ( timer->timeout < timer->min_timeout )
+ timer->timeout = timer->min_timeout;
+
+ DBG2 ( "Timer %p started at time %ld (expires at %ld)\n",
+ timer, timer->start, ( timer->start + timer->timeout ) );
+}
+
+/**
+ * Start timer with a specified fixed timeout
+ *
+ * @v timer Retry timer
+ * @v timeout Timeout, in ticks
+ */
+void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
+ start_timer ( timer );
+ timer->timeout = timeout;
+ DBG2 ( "Timer %p expiry time changed to %ld\n",
+ timer, ( timer->start + timer->timeout ) );
+}
+
+/**
+ * Stop timer
+ *
+ * @v timer Retry timer
+ *
+ * This stops the timer and updates the timer's timeout value.
+ */
+void stop_timer ( struct retry_timer *timer ) {
+ unsigned long old_timeout = timer->timeout;
+ unsigned long now = currticks();
+ unsigned long runtime;
+
+ /* If timer was already stopped, do nothing */
+ if ( ! timer->running )
+ return;
+
+ list_del ( &timer->list );
+ runtime = ( now - timer->start );
+ timer->running = 0;
+ DBG2 ( "Timer %p stopped at time %ld (ran for %ld)\n",
+ timer, now, runtime );
+
+ /* Update timer. Variables are:
+ *
+ * r = round-trip time estimate (i.e. runtime)
+ * t = timeout value (i.e. timer->timeout)
+ * s = smoothed round-trip time
+ *
+ * By choice, we set t = 4s, i.e. allow for four times the
+ * normal round-trip time to pass before retransmitting.
+ *
+ * We want to smooth according to s := ( 7 s + r ) / 8
+ *
+ * Since we don't actually store s, this reduces to
+ * t := ( 7 t / 8 ) + ( r / 2 )
+ *
+ */
+ if ( timer->count ) {
+ timer->count--;
+ } else {
+ timer->timeout -= ( timer->timeout >> 3 );
+ timer->timeout += ( runtime >> 1 );
+ if ( timer->timeout != old_timeout ) {
+ DBG ( "Timer %p timeout updated to %ld\n",
+ timer, timer->timeout );
+ }
+ }
+}
+
+/**
+ * Handle expired timer
+ *
+ * @v timer Retry timer
+ */
+static void timer_expired ( struct retry_timer *timer ) {
+ int fail;
+
+ /* Stop timer without performing RTT calculations */
+ DBG2 ( "Timer %p stopped at time %ld on expiry\n",
+ timer, currticks() );
+ assert ( timer->running );
+ list_del ( &timer->list );
+ timer->running = 0;
+ timer->count++;
+
+ /* Back off the timeout value */
+ timer->timeout <<= 1;
+ if ( timer->max_timeout == 0 ) /* 0 means "use default timeout" */
+ timer->max_timeout = DEFAULT_MAX_TIMEOUT;
+ if ( ( fail = ( timer->timeout > timer->max_timeout ) ) )
+ timer->timeout = timer->max_timeout;
+ DBG ( "Timer %p timeout backed off to %ld\n",
+ timer, timer->timeout );
+
+ /* Call expiry callback */
+ timer->expired ( timer, fail );
+}
+
+/**
+ * Single-step the retry timer list
+ *
+ * @v process Retry timer process
+ */
+static void retry_step ( struct process *process __unused ) {
+ struct retry_timer *timer;
+ struct retry_timer *tmp;
+ unsigned long now = currticks();
+ unsigned long used;
+
+ list_for_each_entry_safe ( timer, tmp, &timers, list ) {
+ used = ( now - timer->start );
+ if ( used >= timer->timeout )
+ timer_expired ( timer );
+ }
+}
+
+/** Retry timer process */
+struct process retry_process __permanent_process = {
+ .list = LIST_HEAD_INIT ( retry_process.list ),
+ .step = retry_step,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/tcp.c b/debian/grub-extras/disabled/gpxe/src/net/tcp.c
new file mode 100644
index 0000000..1269579
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/tcp.c
@@ -0,0 +1,1156 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/timer.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/malloc.h>
+#include <gpxe/retry.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/uri.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/tcp.h>
+
+/** @file
+ *
+ * TCP protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** A TCP connection */
+struct tcp_connection {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of TCP connections */
+ struct list_head list;
+
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+ /** Data transfer interface closed flag */
+ int xfer_closed;
+
+ /** Remote socket address */
+ struct sockaddr_tcpip peer;
+ /** Local port, in network byte order */
+ unsigned int local_port;
+
+ /** Current TCP state */
+ unsigned int tcp_state;
+ /** Previous TCP state
+ *
+ * Maintained only for debug messages
+ */
+ unsigned int prev_tcp_state;
+ /** Current sequence number
+ *
+ * Equivalent to SND.UNA in RFC 793 terminology.
+ */
+ uint32_t snd_seq;
+ /** Unacknowledged sequence count
+ *
+ * Equivalent to (SND.NXT-SND.UNA) in RFC 793 terminology.
+ */
+ uint32_t snd_sent;
+ /** Send window
+ *
+ * Equivalent to SND.WND in RFC 793 terminology
+ */
+ uint32_t snd_win;
+ /** Current acknowledgement number
+ *
+ * Equivalent to RCV.NXT in RFC 793 terminology.
+ */
+ uint32_t rcv_ack;
+ /** Receive window
+ *
+ * Equivalent to RCV.WND in RFC 793 terminology.
+ */
+ uint32_t rcv_win;
+ /** Most recent received timestamp
+ *
+ * Equivalent to TS.Recent in RFC 1323 terminology.
+ */
+ uint32_t ts_recent;
+ /** Timestamps enabled */
+ int timestamps;
+
+ /** Transmit queue */
+ struct list_head queue;
+ /** Retransmission timer */
+ struct retry_timer timer;
+};
+
+/**
+ * List of registered TCP connections
+ */
+static LIST_HEAD ( tcp_conns );
+
+/* Forward declarations */
+static struct xfer_interface_operations tcp_xfer_operations;
+static void tcp_expired ( struct retry_timer *timer, int over );
+static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
+ uint32_t win );
+
+/**
+ * Name TCP state
+ *
+ * @v state TCP state
+ * @ret name Name of TCP state
+ */
+static inline __attribute__ (( always_inline )) const char *
+tcp_state ( int state ) {
+ switch ( state ) {
+ case TCP_CLOSED: return "CLOSED";
+ case TCP_LISTEN: return "LISTEN";
+ case TCP_SYN_SENT: return "SYN_SENT";
+ case TCP_SYN_RCVD: return "SYN_RCVD";
+ case TCP_ESTABLISHED: return "ESTABLISHED";
+ case TCP_FIN_WAIT_1: return "FIN_WAIT_1";
+ case TCP_FIN_WAIT_2: return "FIN_WAIT_2";
+ case TCP_CLOSING_OR_LAST_ACK: return "CLOSING/LAST_ACK";
+ case TCP_TIME_WAIT: return "TIME_WAIT";
+ case TCP_CLOSE_WAIT: return "CLOSE_WAIT";
+ default: return "INVALID";
+ }
+}
+
+/**
+ * Dump TCP state transition
+ *
+ * @v tcp TCP connection
+ */
+static inline __attribute__ (( always_inline )) void
+tcp_dump_state ( struct tcp_connection *tcp ) {
+
+ if ( tcp->tcp_state != tcp->prev_tcp_state ) {
+ DBGC ( tcp, "TCP %p transitioned from %s to %s\n", tcp,
+ tcp_state ( tcp->prev_tcp_state ),
+ tcp_state ( tcp->tcp_state ) );
+ }
+ tcp->prev_tcp_state = tcp->tcp_state;
+}
+
+/**
+ * Dump TCP flags
+ *
+ * @v flags TCP flags
+ */
+static inline __attribute__ (( always_inline )) void
+tcp_dump_flags ( struct tcp_connection *tcp, unsigned int flags ) {
+ if ( flags & TCP_RST )
+ DBGC2 ( tcp, " RST" );
+ if ( flags & TCP_SYN )
+ DBGC2 ( tcp, " SYN" );
+ if ( flags & TCP_PSH )
+ DBGC2 ( tcp, " PSH" );
+ if ( flags & TCP_FIN )
+ DBGC2 ( tcp, " FIN" );
+ if ( flags & TCP_ACK )
+ DBGC2 ( tcp, " ACK" );
+}
+
+/***************************************************************************
+ *
+ * Open and close
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Bind TCP connection to local port
+ *
+ * @v tcp TCP connection
+ * @v port Local port number, in network-endian order
+ * @ret rc Return status code
+ *
+ * If the port is 0, the connection is assigned an available port
+ * between 1024 and 65535.
+ */
+static int tcp_bind ( struct tcp_connection *tcp, unsigned int port ) {
+ struct tcp_connection *existing;
+ static uint16_t try_port = 1023;
+
+ /* If no port specified, find the first available port */
+ if ( ! port ) {
+ while ( try_port ) {
+ try_port++;
+ if ( try_port < 1024 )
+ continue;
+ if ( tcp_bind ( tcp, htons ( try_port ) ) == 0 )
+ return 0;
+ }
+ DBGC ( tcp, "TCP %p could not bind: no free ports\n", tcp );
+ return -EADDRINUSE;
+ }
+
+ /* Attempt bind to local port */
+ list_for_each_entry ( existing, &tcp_conns, list ) {
+ if ( existing->local_port == port ) {
+ DBGC ( tcp, "TCP %p could not bind: port %d in use\n",
+ tcp, ntohs ( port ) );
+ return -EADDRINUSE;
+ }
+ }
+ tcp->local_port = port;
+
+ DBGC ( tcp, "TCP %p bound to port %d\n", tcp, ntohs ( port ) );
+ return 0;
+}
+
+/**
+ * Open a TCP connection
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+static int tcp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local ) {
+ struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
+ struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
+ struct tcp_connection *tcp;
+ unsigned int bind_port;
+ int rc;
+
+ /* Allocate and initialise structure */
+ tcp = zalloc ( sizeof ( *tcp ) );
+ if ( ! tcp )
+ return -ENOMEM;
+ DBGC ( tcp, "TCP %p allocated\n", tcp );
+ xfer_init ( &tcp->xfer, &tcp_xfer_operations, &tcp->refcnt );
+ tcp->prev_tcp_state = TCP_CLOSED;
+ tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN );
+ tcp_dump_state ( tcp );
+ tcp->snd_seq = random();
+ INIT_LIST_HEAD ( &tcp->queue );
+ tcp->timer.expired = tcp_expired;
+ memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
+
+ /* Bind to local port */
+ bind_port = ( st_local ? st_local->st_port : 0 );
+ if ( ( rc = tcp_bind ( tcp, bind_port ) ) != 0 )
+ goto err;
+
+ /* Start timer to initiate SYN */
+ start_timer_nodelay ( &tcp->timer );
+
+ /* Attach parent interface, transfer reference to connection
+ * list and return
+ */
+ xfer_plug_plug ( &tcp->xfer, xfer );
+ list_add ( &tcp->list, &tcp_conns );
+ return 0;
+
+ err:
+ ref_put ( &tcp->refcnt );
+ return rc;
+}
+
+/**
+ * Close TCP connection
+ *
+ * @v tcp TCP connection
+ * @v rc Reason for close
+ *
+ * Closes the data transfer interface. If the TCP state machine is in
+ * a suitable state, the connection will be deleted.
+ */
+static void tcp_close ( struct tcp_connection *tcp, int rc ) {
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+
+ /* Close data transfer interface */
+ xfer_nullify ( &tcp->xfer );
+ xfer_close ( &tcp->xfer, rc );
+ tcp->xfer_closed = 1;
+
+ /* If we are in CLOSED, or have otherwise not yet received a
+ * SYN (i.e. we are in LISTEN or SYN_SENT), just delete the
+ * connection.
+ */
+ if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
+
+ /* Transition to CLOSED for the sake of debugging messages */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+
+ /* Free any unsent I/O buffers */
+ list_for_each_entry_safe ( iobuf, tmp, &tcp->queue, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+
+ /* Remove from list and drop reference */
+ stop_timer ( &tcp->timer );
+ list_del ( &tcp->list );
+ ref_put ( &tcp->refcnt );
+ DBGC ( tcp, "TCP %p connection deleted\n", tcp );
+ return;
+ }
+
+ /* If we have not had our SYN acknowledged (i.e. we are in
+ * SYN_RCVD), pretend that it has been acknowledged so that we
+ * can send a FIN without breaking things.
+ */
+ if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ tcp_rx_ack ( tcp, ( tcp->snd_seq + 1 ), 0 );
+
+ /* If we have no data remaining to send, start sending FIN */
+ if ( list_empty ( &tcp->queue ) ) {
+ tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
+ tcp_dump_state ( tcp );
+ }
+}
+
+/***************************************************************************
+ *
+ * Transmit data path
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Calculate transmission window
+ *
+ * @v tcp TCP connection
+ * @ret len Maximum length that can be sent in a single packet
+ */
+static size_t tcp_xmit_win ( struct tcp_connection *tcp ) {
+ size_t len;
+
+ /* Not ready if we're not in a suitable connection state */
+ if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
+ return 0;
+
+ /* Length is the minimum of the receiver's window and the path MTU */
+ len = tcp->snd_win;
+ if ( len > TCP_PATH_MTU )
+ len = TCP_PATH_MTU;
+
+ return len;
+}
+
+/**
+ * Process TCP transmit queue
+ *
+ * @v tcp TCP connection
+ * @v max_len Maximum length to process
+ * @v dest I/O buffer to fill with data, or NULL
+ * @v remove Remove data from queue
+ * @ret len Length of data processed
+ *
+ * This processes at most @c max_len bytes from the TCP connection's
+ * transmit queue. Data will be copied into the @c dest I/O buffer
+ * (if provided) and, if @c remove is true, removed from the transmit
+ * queue.
+ */
+static size_t tcp_process_queue ( struct tcp_connection *tcp, size_t max_len,
+ struct io_buffer *dest, int remove ) {
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+ size_t frag_len;
+ size_t len = 0;
+
+ list_for_each_entry_safe ( iobuf, tmp, &tcp->queue, list ) {
+ frag_len = iob_len ( iobuf );
+ if ( frag_len > max_len )
+ frag_len = max_len;
+ if ( dest ) {
+ memcpy ( iob_put ( dest, frag_len ), iobuf->data,
+ frag_len );
+ }
+ if ( remove ) {
+ iob_pull ( iobuf, frag_len );
+ if ( ! iob_len ( iobuf ) ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+ }
+ len += frag_len;
+ max_len -= frag_len;
+ }
+ return len;
+}
+
+/**
+ * Transmit any outstanding data
+ *
+ * @v tcp TCP connection
+ * @v force_send Force sending of packet
+ *
+ * Transmits any outstanding data on the connection.
+ *
+ * Note that even if an error is returned, the retransmission timer
+ * will have been started if necessary, and so the stack will
+ * eventually attempt to retransmit the failed packet.
+ */
+static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
+ struct io_buffer *iobuf;
+ struct tcp_header *tcphdr;
+ struct tcp_mss_option *mssopt;
+ struct tcp_timestamp_padded_option *tsopt;
+ void *payload;
+ unsigned int flags;
+ size_t len = 0;
+ uint32_t seq_len;
+ uint32_t app_win;
+ uint32_t max_rcv_win;
+ int rc;
+
+ /* If retransmission timer is already running, do nothing */
+ if ( timer_running ( &tcp->timer ) )
+ return 0;
+
+ /* Calculate both the actual (payload) and sequence space
+ * lengths that we wish to transmit.
+ */
+ if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
+ len = tcp_process_queue ( tcp, tcp_xmit_win ( tcp ),
+ NULL, 0 );
+ }
+ seq_len = len;
+ flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
+ if ( flags & ( TCP_SYN | TCP_FIN ) ) {
+ /* SYN or FIN consume one byte, and we can never send both */
+ assert ( ! ( ( flags & TCP_SYN ) && ( flags & TCP_FIN ) ) );
+ seq_len++;
+ }
+ tcp->snd_sent = seq_len;
+
+ /* If we have nothing to transmit, stop now */
+ if ( ( seq_len == 0 ) && ! force_send )
+ return 0;
+
+ /* If we are transmitting anything that requires
+ * acknowledgement (i.e. consumes sequence space), start the
+ * retransmission timer. Do this before attempting to
+ * allocate the I/O buffer, in case allocation itself fails.
+ */
+ if ( seq_len )
+ start_timer ( &tcp->timer );
+
+ /* Allocate I/O buffer */
+ iobuf = alloc_iob ( len + MAX_HDR_LEN );
+ if ( ! iobuf ) {
+ DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
+ "%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
+ tcp->rcv_ack );
+ return -ENOMEM;
+ }
+ iob_reserve ( iobuf, MAX_HDR_LEN );
+
+ /* Fill data payload from transmit queue */
+ tcp_process_queue ( tcp, len, iobuf, 0 );
+
+ /* Expand receive window if possible */
+ // max_rcv_win = ( ( freemem * 3 ) / 4 );
+ //if ( max_rcv_win > TCP_MAX_WINDOW_SIZE )
+ max_rcv_win = TCP_MAX_WINDOW_SIZE;
+ app_win = xfer_window ( &tcp->xfer );
+ if ( max_rcv_win > app_win )
+ max_rcv_win = app_win;
+ max_rcv_win &= ~0x03; /* Keep everything dword-aligned */
+ if ( tcp->rcv_win < max_rcv_win )
+ tcp->rcv_win = max_rcv_win;
+
+ /* Fill up the TCP header */
+ payload = iobuf->data;
+ if ( flags & TCP_SYN ) {
+ mssopt = iob_push ( iobuf, sizeof ( *mssopt ) );
+ mssopt->kind = TCP_OPTION_MSS;
+ mssopt->length = sizeof ( *mssopt );
+ mssopt->mss = htons ( TCP_MSS );
+ }
+ if ( ( flags & TCP_SYN ) || tcp->timestamps ) {
+ tsopt = iob_push ( iobuf, sizeof ( *tsopt ) );
+ memset ( tsopt->nop, TCP_OPTION_NOP, sizeof ( tsopt->nop ) );
+ tsopt->tsopt.kind = TCP_OPTION_TS;
+ tsopt->tsopt.length = sizeof ( tsopt->tsopt );
+ tsopt->tsopt.tsval = ntohl ( currticks() );
+ tsopt->tsopt.tsecr = ntohl ( tcp->ts_recent );
+ }
+ if ( ! ( flags & TCP_SYN ) )
+ flags |= TCP_PSH;
+ tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
+ memset ( tcphdr, 0, sizeof ( *tcphdr ) );
+ tcphdr->src = tcp->local_port;
+ tcphdr->dest = tcp->peer.st_port;
+ tcphdr->seq = htonl ( tcp->snd_seq );
+ tcphdr->ack = htonl ( tcp->rcv_ack );
+ tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
+ tcphdr->flags = flags;
+ tcphdr->win = htons ( tcp->rcv_win );
+ tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
+
+ /* Dump header */
+ DBGC2 ( tcp, "TCP %p TX %d->%d %08x..%08x %08x %4zd",
+ tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
+ ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) + seq_len ),
+ ntohl ( tcphdr->ack ), len );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC2 ( tcp, "\n" );
+
+ /* Transmit packet */
+ if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
+ &tcphdr->csum ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not transmit %08x..%08x %08x: %s\n",
+ tcp, tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ),
+ tcp->rcv_ack, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Retransmission timer expired
+ *
+ * @v timer Retry timer
+ * @v over Failure indicator
+ */
+static void tcp_expired ( struct retry_timer *timer, int over ) {
+ struct tcp_connection *tcp =
+ container_of ( timer, struct tcp_connection, timer );
+ int graceful_close = TCP_CLOSED_GRACEFULLY ( tcp->tcp_state );
+
+ DBGC ( tcp, "TCP %p timer %s in %s for %08x..%08x %08x\n", tcp,
+ ( over ? "expired" : "fired" ), tcp_state ( tcp->tcp_state ),
+ tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
+
+ assert ( ( tcp->tcp_state == TCP_SYN_SENT ) ||
+ ( tcp->tcp_state == TCP_SYN_RCVD ) ||
+ ( tcp->tcp_state == TCP_ESTABLISHED ) ||
+ ( tcp->tcp_state == TCP_FIN_WAIT_1 ) ||
+ ( tcp->tcp_state == TCP_TIME_WAIT ) ||
+ ( tcp->tcp_state == TCP_CLOSE_WAIT ) ||
+ ( tcp->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
+
+ if ( over || graceful_close ) {
+ /* If we have finally timed out and given up, or if
+ * this is the result of a graceful close, terminate
+ * the connection
+ */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ tcp_close ( tcp, -ETIMEDOUT );
+ } else {
+ /* Otherwise, retransmit the packet */
+ tcp_xmit ( tcp, 0 );
+ }
+}
+
+/**
+ * Send RST response to incoming packet
+ *
+ * @v in_tcphdr TCP header of incoming packet
+ * @ret rc Return status code
+ */
+static int tcp_xmit_reset ( struct tcp_connection *tcp,
+ struct sockaddr_tcpip *st_dest,
+ struct tcp_header *in_tcphdr ) {
+ struct io_buffer *iobuf;
+ struct tcp_header *tcphdr;
+ int rc;
+
+ /* Allocate space for dataless TX buffer */
+ iobuf = alloc_iob ( MAX_HDR_LEN );
+ if ( ! iobuf ) {
+ DBGC ( tcp, "TCP %p could not allocate iobuf for RST "
+ "%08x..%08x %08x\n", tcp, ntohl ( in_tcphdr->ack ),
+ ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ) );
+ return -ENOMEM;
+ }
+ iob_reserve ( iobuf, MAX_HDR_LEN );
+
+ /* Construct RST response */
+ tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) );
+ memset ( tcphdr, 0, sizeof ( *tcphdr ) );
+ tcphdr->src = in_tcphdr->dest;
+ tcphdr->dest = in_tcphdr->src;
+ tcphdr->seq = in_tcphdr->ack;
+ tcphdr->ack = in_tcphdr->seq;
+ tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 );
+ tcphdr->flags = ( TCP_RST | TCP_ACK );
+ tcphdr->win = htons ( TCP_MAX_WINDOW_SIZE );
+ tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
+
+ /* Dump header */
+ DBGC2 ( tcp, "TCP %p TX %d->%d %08x..%08x %08x %4d",
+ tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
+ ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) ),
+ ntohl ( tcphdr->ack ), 0 );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC2 ( tcp, "\n" );
+
+ /* Transmit packet */
+ if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
+ NULL, &tcphdr->csum ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not transmit RST %08x..%08x %08x: "
+ "%s\n", tcp, ntohl ( in_tcphdr->ack ),
+ ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ),
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * Receive data path
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Identify TCP connection by local port number
+ *
+ * @v local_port Local port (in network-endian order)
+ * @ret tcp TCP connection, or NULL
+ */
+static struct tcp_connection * tcp_demux ( unsigned int local_port ) {
+ struct tcp_connection *tcp;
+
+ list_for_each_entry ( tcp, &tcp_conns, list ) {
+ if ( tcp->local_port == local_port )
+ return tcp;
+ }
+ return NULL;
+}
+
+/**
+ * Parse TCP received options
+ *
+ * @v tcp TCP connection
+ * @v data Raw options data
+ * @v len Raw options length
+ * @v options Options structure to fill in
+ */
+static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data,
+ size_t len, struct tcp_options *options ) {
+ const void *end = ( data + len );
+ const struct tcp_option *option;
+ unsigned int kind;
+
+ memset ( options, 0, sizeof ( *options ) );
+ while ( data < end ) {
+ option = data;
+ kind = option->kind;
+ if ( kind == TCP_OPTION_END )
+ return;
+ if ( kind == TCP_OPTION_NOP ) {
+ data++;
+ continue;
+ }
+ switch ( kind ) {
+ case TCP_OPTION_MSS:
+ options->mssopt = data;
+ break;
+ case TCP_OPTION_TS:
+ options->tsopt = data;
+ break;
+ default:
+ DBGC ( tcp, "TCP %p received unknown option %d\n",
+ tcp, kind );
+ break;
+ }
+ data += option->length;
+ }
+}
+
+/**
+ * Consume received sequence space
+ *
+ * @v tcp TCP connection
+ * @v seq_len Sequence space length to consume
+ */
+static void tcp_rx_seq ( struct tcp_connection *tcp, uint32_t seq_len ) {
+ tcp->rcv_ack += seq_len;
+ if ( tcp->rcv_win > seq_len ) {
+ tcp->rcv_win -= seq_len;
+ } else {
+ tcp->rcv_win = 0;
+ }
+}
+
+/**
+ * Handle TCP received SYN
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @v options TCP options
+ * @ret rc Return status code
+ */
+static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq,
+ struct tcp_options *options ) {
+
+ /* Synchronise sequence numbers on first SYN */
+ if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
+ tcp->rcv_ack = seq;
+ if ( options->tsopt )
+ tcp->timestamps = 1;
+ }
+
+ /* Ignore duplicate SYN */
+ if ( ( tcp->rcv_ack - seq ) > 0 )
+ return 0;
+
+ /* Mark SYN as received and start sending ACKs with each packet */
+ tcp->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
+ TCP_STATE_RCVD ( TCP_SYN ) );
+
+ /* Acknowledge SYN */
+ tcp_rx_seq ( tcp, 1 );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received ACK
+ *
+ * @v tcp TCP connection
+ * @v ack ACK value (in host-endian order)
+ * @v win WIN value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
+ uint32_t win ) {
+ uint32_t ack_len = ( ack - tcp->snd_seq );
+ size_t len;
+ unsigned int acked_flags;
+
+ /* Check for out-of-range or old duplicate ACKs */
+ if ( ack_len > tcp->snd_sent ) {
+ DBGC ( tcp, "TCP %p received ACK for %08x..%08x, "
+ "sent only %08x..%08x\n", tcp, tcp->snd_seq,
+ ( tcp->snd_seq + ack_len ), tcp->snd_seq,
+ ( tcp->snd_seq + tcp->snd_sent ) );
+
+ if ( TCP_HAS_BEEN_ESTABLISHED ( tcp->tcp_state ) ) {
+ /* Just ignore what might be old duplicate ACKs */
+ return 0;
+ } else {
+ /* Send RST if an out-of-range ACK is received
+ * on a not-yet-established connection, as per
+ * RFC 793.
+ */
+ return -EINVAL;
+ }
+ }
+
+ /* Ignore ACKs that don't actually acknowledge any new data.
+ * (In particular, do not stop the retransmission timer; this
+ * avoids creating a sorceror's apprentice syndrome when a
+ * duplicate ACK is received and we still have data in our
+ * transmit queue.)
+ */
+ if ( ack_len == 0 )
+ return 0;
+
+ /* Stop the retransmission timer */
+ stop_timer ( &tcp->timer );
+
+ /* Determine acknowledged flags and data length */
+ len = ack_len;
+ acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) &
+ ( TCP_SYN | TCP_FIN ) );
+ if ( acked_flags )
+ len--;
+
+ /* Update SEQ and sent counters, and window size */
+ tcp->snd_seq = ack;
+ tcp->snd_sent = 0;
+ tcp->snd_win = win;
+
+ /* Remove any acknowledged data from transmit queue */
+ tcp_process_queue ( tcp, len, NULL, 1 );
+
+ /* Mark SYN/FIN as acknowledged if applicable. */
+ if ( acked_flags )
+ tcp->tcp_state |= TCP_STATE_ACKED ( acked_flags );
+
+ /* Start sending FIN if we've had all possible data ACKed */
+ if ( list_empty ( &tcp->queue ) && tcp->xfer_closed )
+ tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received data
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This function takes ownership of the I/O buffer.
+ */
+static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
+ struct io_buffer *iobuf ) {
+ uint32_t already_rcvd;
+ uint32_t len;
+ int rc;
+
+ /* Ignore duplicate or out-of-order data */
+ already_rcvd = ( tcp->rcv_ack - seq );
+ len = iob_len ( iobuf );
+ if ( already_rcvd >= len ) {
+ free_iob ( iobuf );
+ return 0;
+ }
+ iob_pull ( iobuf, already_rcvd );
+ len -= already_rcvd;
+
+ /* Deliver data to application */
+ if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not deliver %08x..%08x: %s\n",
+ tcp, seq, ( seq + len ), strerror ( rc ) );
+ return rc;
+ }
+
+ /* Acknowledge new data */
+ tcp_rx_seq ( tcp, len );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received FIN
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_fin ( struct tcp_connection *tcp, uint32_t seq ) {
+
+ /* Ignore duplicate or out-of-order FIN */
+ if ( ( tcp->rcv_ack - seq ) > 0 )
+ return 0;
+
+ /* Mark FIN as received and acknowledge it */
+ tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
+ tcp_rx_seq ( tcp, 1 );
+
+ /* Close connection */
+ tcp_close ( tcp, 0 );
+
+ return 0;
+}
+
+/**
+ * Handle TCP received RST
+ *
+ * @v tcp TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_rst ( struct tcp_connection *tcp, uint32_t seq ) {
+
+ /* Accept RST only if it falls within the window. If we have
+ * not yet received a SYN, then we have no window to test
+ * against, so fall back to checking that our SYN has been
+ * ACKed.
+ */
+ if ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
+ if ( ( seq - tcp->rcv_ack ) >= tcp->rcv_win )
+ return 0;
+ } else {
+ if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ return 0;
+ }
+
+ /* Abort connection */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ tcp_close ( tcp, -ECONNRESET );
+
+ DBGC ( tcp, "TCP %p connection reset by peer\n", tcp );
+ return -ECONNRESET;
+}
+
+/**
+ * Process received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
+static int tcp_rx ( struct io_buffer *iobuf,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest __unused,
+ uint16_t pshdr_csum ) {
+ struct tcp_header *tcphdr = iobuf->data;
+ struct tcp_connection *tcp;
+ struct tcp_options options;
+ size_t hlen;
+ uint16_t csum;
+ uint32_t start_seq;
+ uint32_t seq;
+ uint32_t ack;
+ uint32_t win;
+ unsigned int flags;
+ size_t len;
+ int rc;
+
+ /* Sanity check packet */
+ if ( iob_len ( iobuf ) < sizeof ( *tcphdr ) ) {
+ DBG ( "TCP packet too short at %zd bytes (min %zd bytes)\n",
+ iob_len ( iobuf ), sizeof ( *tcphdr ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+ hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
+ if ( hlen < sizeof ( *tcphdr ) ) {
+ DBG ( "TCP header too short at %zd bytes (min %zd bytes)\n",
+ hlen, sizeof ( *tcphdr ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+ if ( hlen > iob_len ( iobuf ) ) {
+ DBG ( "TCP header too long at %zd bytes (max %zd bytes)\n",
+ hlen, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+ csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data,
+ iob_len ( iobuf ) );
+ if ( csum != 0 ) {
+ DBG ( "TCP checksum incorrect (is %04x including checksum "
+ "field, should be 0000)\n", csum );
+ rc = -EINVAL;
+ goto discard;
+ }
+
+ /* Parse parameters from header and strip header */
+ tcp = tcp_demux ( tcphdr->dest );
+ start_seq = seq = ntohl ( tcphdr->seq );
+ ack = ntohl ( tcphdr->ack );
+ win = ntohs ( tcphdr->win );
+ flags = tcphdr->flags;
+ tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
+ ( hlen - sizeof ( *tcphdr ) ), &options );
+ iob_pull ( iobuf, hlen );
+ len = iob_len ( iobuf );
+
+ /* Dump header */
+ DBGC2 ( tcp, "TCP %p RX %d<-%d %08x %08x..%08zx %4zd",
+ tcp, ntohs ( tcphdr->dest ), ntohs ( tcphdr->src ),
+ ntohl ( tcphdr->ack ), ntohl ( tcphdr->seq ),
+ ( ntohl ( tcphdr->seq ) + len +
+ ( ( tcphdr->flags & ( TCP_SYN | TCP_FIN ) ) ? 1 : 0 )), len);
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC2 ( tcp, "\n" );
+
+ /* If no connection was found, send RST */
+ if ( ! tcp ) {
+ tcp_xmit_reset ( tcp, st_src, tcphdr );
+ rc = -ENOTCONN;
+ goto discard;
+ }
+
+ /* Handle ACK, if present */
+ if ( flags & TCP_ACK ) {
+ if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) {
+ tcp_xmit_reset ( tcp, st_src, tcphdr );
+ goto discard;
+ }
+ }
+
+ /* Handle SYN, if present */
+ if ( flags & TCP_SYN ) {
+ tcp_rx_syn ( tcp, seq, &options );
+ seq++;
+ }
+
+ /* Handle RST, if present */
+ if ( flags & TCP_RST ) {
+ if ( ( rc = tcp_rx_rst ( tcp, seq ) ) != 0 )
+ goto discard;
+ }
+
+ /* Handle new data, if any */
+ tcp_rx_data ( tcp, seq, iobuf );
+ seq += len;
+
+ /* Handle FIN, if present */
+ if ( flags & TCP_FIN ) {
+ tcp_rx_fin ( tcp, seq );
+ seq++;
+ }
+
+ /* Update timestamp, if present and applicable */
+ if ( ( seq == tcp->rcv_ack ) && options.tsopt )
+ tcp->ts_recent = ntohl ( options.tsopt->tsval );
+
+ /* Dump out any state change as a result of the received packet */
+ tcp_dump_state ( tcp );
+
+ /* Send out any pending data. We force sending a reply if either
+ *
+ * a) the peer is expecting an ACK (i.e. consumed sequence space), or
+ * b) either end of the packet was outside the receive window
+ *
+ * Case (b) enables us to support TCP keepalives using
+ * zero-length packets, which we would otherwise ignore. Note
+ * that for case (b), we need *only* consider zero-length
+ * packets, since non-zero-length packets will already be
+ * caught by case (a).
+ */
+ tcp_xmit ( tcp, ( ( start_seq != seq ) ||
+ ( ( seq - tcp->rcv_ack ) > tcp->rcv_win ) ) );
+
+ /* If this packet was the last we expect to receive, set up
+ * timer to expire and cause the connection to be freed.
+ */
+ if ( TCP_CLOSED_GRACEFULLY ( tcp->tcp_state ) ) {
+ tcp->timer.timeout = ( 2 * TCP_MSL );
+ start_timer ( &tcp->timer );
+ }
+
+ return 0;
+
+ discard:
+ /* Free received packet */
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** TCP protocol */
+struct tcpip_protocol tcp_protocol __tcpip_protocol = {
+ .name = "TCP",
+ .rx = tcp_rx,
+ .tcpip_proto = IP_TCP,
+};
+
+/***************************************************************************
+ *
+ * Data transfer interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Close interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void tcp_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct tcp_connection *tcp =
+ container_of ( xfer, struct tcp_connection, xfer );
+
+ /* Close data transfer interface */
+ tcp_close ( tcp, rc );
+
+ /* Transmit FIN, if possible */
+ tcp_xmit ( tcp, 0 );
+}
+
+/**
+ * Check flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ */
+static size_t tcp_xfer_window ( struct xfer_interface *xfer ) {
+ struct tcp_connection *tcp =
+ container_of ( xfer, struct tcp_connection, xfer );
+
+ /* Not ready if data queue is non-empty. This imposes a limit
+ * of only one unACKed packet in the TX queue at any time; we
+ * do this to conserve memory usage.
+ */
+ if ( ! list_empty ( &tcp->queue ) )
+ return 0;
+
+ /* Return TCP window length */
+ return tcp_xmit_win ( tcp );
+}
+
+/**
+ * Deliver datagram as I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int tcp_xfer_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct tcp_connection *tcp =
+ container_of ( xfer, struct tcp_connection, xfer );
+
+ /* Enqueue packet */
+ list_add_tail ( &iobuf->list, &tcp->queue );
+
+ /* Transmit data, if possible */
+ tcp_xmit ( tcp, 0 );
+
+ return 0;
+}
+
+/** TCP data transfer interface operations */
+static struct xfer_interface_operations tcp_xfer_operations = {
+ .close = tcp_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = tcp_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = tcp_xfer_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/***************************************************************************
+ *
+ * Openers
+ *
+ ***************************************************************************
+ */
+
+/** TCP socket opener */
+struct socket_opener tcp_socket_opener __socket_opener = {
+ .semantics = TCP_SOCK_STREAM,
+ .family = AF_INET,
+ .open = tcp_open,
+};
+
+/** Linkage hack */
+int tcp_sock_stream = TCP_SOCK_STREAM;
+
+/**
+ * Open TCP URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int tcp_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
+ struct sockaddr_tcpip peer;
+
+ /* Sanity check */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ memset ( &peer, 0, sizeof ( peer ) );
+ peer.st_port = htons ( uri_port ( uri, 0 ) );
+ return xfer_open_named_socket ( xfer, SOCK_STREAM,
+ ( struct sockaddr * ) &peer,
+ uri->host, NULL );
+}
+
+/** TCP URI opener */
+struct uri_opener tcp_uri_opener __uri_opener = {
+ .scheme = "tcp",
+ .open = tcp_open_uri,
+};
+
diff --git a/debian/grub-extras/disabled/gpxe/src/net/tcp/http.c b/debian/grub-extras/disabled/gpxe/src/net/tcp/http.c
new file mode 100644
index 0000000..a02408a
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/tcp/http.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Hyper Text Transfer Protocol (HTTP)
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/uri.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/socket.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/process.h>
+#include <gpxe/linebuf.h>
+#include <gpxe/features.h>
+#include <gpxe/base64.h>
+#include <gpxe/http.h>
+
+FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
+
+/** HTTP receive state */
+enum http_rx_state {
+ HTTP_RX_RESPONSE = 0,
+ HTTP_RX_HEADER,
+ HTTP_RX_DATA,
+ HTTP_RX_DEAD,
+};
+
+/**
+ * An HTTP request
+ *
+ */
+struct http_request {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+
+ /** URI being fetched */
+ struct uri *uri;
+ /** Transport layer interface */
+ struct xfer_interface socket;
+
+ /** TX process */
+ struct process process;
+
+ /** HTTP response code */
+ unsigned int response;
+ /** HTTP Content-Length */
+ size_t content_length;
+ /** Received length */
+ size_t rx_len;
+ /** RX state */
+ enum http_rx_state rx_state;
+ /** Line buffer for received header lines */
+ struct line_buffer linebuf;
+};
+
+/**
+ * Free HTTP request
+ *
+ * @v refcnt Reference counter
+ */
+static void http_free ( struct refcnt *refcnt ) {
+ struct http_request *http =
+ container_of ( refcnt, struct http_request, refcnt );
+
+ uri_put ( http->uri );
+ empty_line_buffer ( &http->linebuf );
+ free ( http );
+};
+
+/**
+ * Mark HTTP request as complete
+ *
+ * @v http HTTP request
+ * @v rc Return status code
+ */
+static void http_done ( struct http_request *http, int rc ) {
+
+ /* Prevent further processing of any current packet */
+ http->rx_state = HTTP_RX_DEAD;
+
+ /* If we had a Content-Length, and the received content length
+ * isn't correct, flag an error
+ */
+ if ( http->content_length &&
+ ( http->content_length != http->rx_len ) ) {
+ DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
+ http, http->rx_len, http->content_length );
+ rc = -EIO;
+ }
+
+ /* Remove process */
+ process_del ( &http->process );
+
+ /* Close all data transfer interfaces */
+ xfer_nullify ( &http->socket );
+ xfer_close ( &http->socket, rc );
+ xfer_nullify ( &http->xfer );
+ xfer_close ( &http->xfer, rc );
+}
+
+/**
+ * Convert HTTP response code to return status code
+ *
+ * @v response HTTP response code
+ * @ret rc Return status code
+ */
+static int http_response_to_rc ( unsigned int response ) {
+ switch ( response ) {
+ case 200:
+ case 301:
+ case 302:
+ return 0;
+ case 404:
+ return -ENOENT;
+ case 403:
+ return -EPERM;
+ case 401:
+ return -EACCES;
+ default:
+ return -EIO;
+ }
+}
+
+/**
+ * Handle HTTP response
+ *
+ * @v http HTTP request
+ * @v response HTTP response
+ * @ret rc Return status code
+ */
+static int http_rx_response ( struct http_request *http, char *response ) {
+ char *spc;
+ int rc;
+
+ DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
+
+ /* Check response starts with "HTTP/" */
+ if ( strncmp ( response, "HTTP/", 5 ) != 0 )
+ return -EIO;
+
+ /* Locate and check response code */
+ spc = strchr ( response, ' ' );
+ if ( ! spc )
+ return -EIO;
+ http->response = strtoul ( spc, NULL, 10 );
+ if ( ( rc = http_response_to_rc ( http->response ) ) != 0 )
+ return rc;
+
+ /* Move to received headers */
+ http->rx_state = HTTP_RX_HEADER;
+ return 0;
+}
+
+/**
+ * Handle HTTP Location header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ */
+static int http_rx_location ( struct http_request *http, const char *value ) {
+ int rc;
+
+ /* Redirect to new location */
+ DBGC ( http, "HTTP %p redirecting to %s\n", http, value );
+ if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING,
+ value ) ) != 0 ) {
+ DBGC ( http, "HTTP %p could not redirect: %s\n",
+ http, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle HTTP Content-Length header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ */
+static int http_rx_content_length ( struct http_request *http,
+ const char *value ) {
+ char *endp;
+
+ http->content_length = strtoul ( value, &endp, 10 );
+ if ( *endp != '\0' ) {
+ DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
+ http, value );
+ return -EIO;
+ }
+
+ /* Use seek() to notify recipient of filesize */
+ xfer_seek ( &http->xfer, http->content_length, SEEK_SET );
+ xfer_seek ( &http->xfer, 0, SEEK_SET );
+
+ return 0;
+}
+
+/** An HTTP header handler */
+struct http_header_handler {
+ /** Name (e.g. "Content-Length") */
+ const char *header;
+ /** Handle received header
+ *
+ * @v http HTTP request
+ * @v value HTTP header value
+ * @ret rc Return status code
+ *
+ * If an error is returned, the download will be aborted.
+ */
+ int ( * rx ) ( struct http_request *http, const char *value );
+};
+
+/** List of HTTP header handlers */
+static struct http_header_handler http_header_handlers[] = {
+ {
+ .header = "Location",
+ .rx = http_rx_location,
+ },
+ {
+ .header = "Content-Length",
+ .rx = http_rx_content_length,
+ },
+ { NULL, NULL }
+};
+
+/**
+ * Handle HTTP header
+ *
+ * @v http HTTP request
+ * @v header HTTP header
+ * @ret rc Return status code
+ */
+static int http_rx_header ( struct http_request *http, char *header ) {
+ struct http_header_handler *handler;
+ char *separator;
+ char *value;
+ int rc;
+
+ /* An empty header line marks the transition to the data phase */
+ if ( ! header[0] ) {
+ DBGC ( http, "HTTP %p start of data\n", http );
+ empty_line_buffer ( &http->linebuf );
+ http->rx_state = HTTP_RX_DATA;
+ return 0;
+ }
+
+ DBGC ( http, "HTTP %p header \"%s\"\n", http, header );
+
+ /* Split header at the ": " */
+ separator = strstr ( header, ": " );
+ if ( ! separator ) {
+ DBGC ( http, "HTTP %p malformed header\n", http );
+ return -EIO;
+ }
+ *separator = '\0';
+ value = ( separator + 2 );
+
+ /* Hand off to header handler, if one exists */
+ for ( handler = http_header_handlers ; handler->header ; handler++ ) {
+ if ( strcasecmp ( header, handler->header ) == 0 ) {
+ if ( ( rc = handler->rx ( http, value ) ) != 0 )
+ return rc;
+ break;
+ }
+ }
+ return 0;
+}
+
+/** An HTTP line-based data handler */
+struct http_line_handler {
+ /** Handle line
+ *
+ * @v http HTTP request
+ * @v line Line to handle
+ * @ret rc Return status code
+ */
+ int ( * rx ) ( struct http_request *http, char *line );
+};
+
+/** List of HTTP line-based data handlers */
+static struct http_line_handler http_line_handlers[] = {
+ [HTTP_RX_RESPONSE] = { .rx = http_rx_response },
+ [HTTP_RX_HEADER] = { .rx = http_rx_header },
+};
+
+/**
+ * Handle new data arriving via HTTP connection in the data phase
+ *
+ * @v http HTTP request
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int http_rx_data ( struct http_request *http,
+ struct io_buffer *iobuf ) {
+ int rc;
+
+ /* Update received length */
+ http->rx_len += iob_len ( iobuf );
+
+ /* Hand off data buffer */
+ if ( ( rc = xfer_deliver_iob ( &http->xfer, iobuf ) ) != 0 )
+ return rc;
+
+ /* If we have reached the content-length, stop now */
+ if ( http->content_length &&
+ ( http->rx_len >= http->content_length ) ) {
+ http_done ( http, 0 );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle new data arriving via HTTP connection
+ *
+ * @v socket Transport layer interface
+ * @v iobuf I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int http_socket_deliver_iob ( struct xfer_interface *socket,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta __unused ) {
+ struct http_request *http =
+ container_of ( socket, struct http_request, socket );
+ struct http_line_handler *lh;
+ char *line;
+ ssize_t len;
+ int rc = 0;
+
+ while ( iob_len ( iobuf ) ) {
+ switch ( http->rx_state ) {
+ case HTTP_RX_DEAD:
+ /* Do no further processing */
+ goto done;
+ case HTTP_RX_DATA:
+ /* Once we're into the data phase, just fill
+ * the data buffer
+ */
+ rc = http_rx_data ( http, iob_disown ( iobuf ) );
+ goto done;
+ case HTTP_RX_RESPONSE:
+ case HTTP_RX_HEADER:
+ /* In the other phases, buffer and process a
+ * line at a time
+ */
+ len = line_buffer ( &http->linebuf, iobuf->data,
+ iob_len ( iobuf ) );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( http, "HTTP %p could not buffer line: "
+ "%s\n", http, strerror ( rc ) );
+ goto done;
+ }
+ iob_pull ( iobuf, len );
+ line = buffered_line ( &http->linebuf );
+ if ( line ) {
+ lh = &http_line_handlers[http->rx_state];
+ if ( ( rc = lh->rx ( http, line ) ) != 0 )
+ goto done;
+ }
+ break;
+ default:
+ assert ( 0 );
+ break;
+ }
+ }
+
+ done:
+ if ( rc )
+ http_done ( http, rc );
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * HTTP process
+ *
+ * @v process Process
+ */
+static void http_step ( struct process *process ) {
+ struct http_request *http =
+ container_of ( process, struct http_request, process );
+ const char *path = http->uri->path;
+ const char *host = http->uri->host;
+ const char *query = http->uri->query;
+ const char *user = http->uri->user;
+ const char *password =
+ ( http->uri->password ? http->uri->password : "" );
+ size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
+ strlen ( password ) ) : 0 );
+ size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
+ char user_pw[ user_pw_len + 1 /* NUL */ ];
+ char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
+ int rc;
+
+ if ( xfer_window ( &http->socket ) ) {
+
+ /* We want to execute only once */
+ process_del ( &http->process );
+
+ /* Construct authorisation, if applicable */
+ if ( user ) {
+ char *buf = user_pw;
+ ssize_t remaining = sizeof ( user_pw );
+ size_t len;
+
+ /* URI-decode the username and password */
+ len = uri_decode ( user, buf, remaining );
+ buf += len;
+ remaining -= len;
+ *(remaining--, buf++) = ':';
+ len = uri_decode ( password, buf, remaining );
+ buf += len;
+ remaining -= len;
+ assert ( remaining >= 0 );
+
+ /* Base64-encode the "user:password" string */
+ base64_encode ( user_pw, user_pw_base64 );
+ }
+
+ /* Send GET request */
+ if ( ( rc = xfer_printf ( &http->socket,
+ "GET %s%s%s HTTP/1.0\r\n"
+ "User-Agent: gPXE/" VERSION "\r\n"
+ "%s%s%s"
+ "Host: %s\r\n"
+ "\r\n",
+ ( path ? path : "/" ),
+ ( query ? "?" : "" ),
+ ( query ? query : "" ),
+ ( user ?
+ "Authorization: Basic " : "" ),
+ ( user ? user_pw_base64 : "" ),
+ ( user ? "\r\n" : "" ),
+ host ) ) != 0 ) {
+ http_done ( http, rc );
+ }
+ }
+}
+
+/**
+ * HTTP connection closed by network stack
+ *
+ * @v socket Transport layer interface
+ * @v rc Reason for close
+ */
+static void http_socket_close ( struct xfer_interface *socket, int rc ) {
+ struct http_request *http =
+ container_of ( socket, struct http_request, socket );
+
+ DBGC ( http, "HTTP %p socket closed: %s\n",
+ http, strerror ( rc ) );
+
+ http_done ( http, rc );
+}
+
+/** HTTP socket operations */
+static struct xfer_interface_operations http_socket_operations = {
+ .close = http_socket_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = http_socket_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/**
+ * Close HTTP data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void http_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct http_request *http =
+ container_of ( xfer, struct http_request, xfer );
+
+ DBGC ( http, "HTTP %p interface closed: %s\n",
+ http, strerror ( rc ) );
+
+ http_done ( http, rc );
+}
+
+/** HTTP data transfer interface operations */
+static struct xfer_interface_operations http_xfer_operations = {
+ .close = http_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = ignore_xfer_deliver_raw,
+};
+
+/**
+ * Initiate an HTTP connection, with optional filter
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @v default_port Default port number
+ * @v filter Filter to apply to socket, or NULL
+ * @ret rc Return status code
+ */
+int http_open_filter ( struct xfer_interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ int ( * filter ) ( struct xfer_interface *xfer,
+ struct xfer_interface **next ) ) {
+ struct http_request *http;
+ struct sockaddr_tcpip server;
+ struct xfer_interface *socket;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ /* Allocate and populate HTTP structure */
+ http = zalloc ( sizeof ( *http ) );
+ if ( ! http )
+ return -ENOMEM;
+ http->refcnt.free = http_free;
+ xfer_init ( &http->xfer, &http_xfer_operations, &http->refcnt );
+ http->uri = uri_get ( uri );
+ xfer_init ( &http->socket, &http_socket_operations, &http->refcnt );
+ process_init ( &http->process, http_step, &http->refcnt );
+
+ /* Open socket */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( uri_port ( http->uri, default_port ) );
+ socket = &http->socket;
+ if ( filter ) {
+ if ( ( rc = filter ( socket, &socket ) ) != 0 )
+ goto err;
+ }
+ if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
+ ( struct sockaddr * ) &server,
+ uri->host, NULL ) ) != 0 )
+ goto err;
+
+ /* Attach to parent interface, mortalise self, and return */
+ xfer_plug_plug ( &http->xfer, xfer );
+ ref_put ( &http->refcnt );
+ return 0;
+
+ err:
+ DBGC ( http, "HTTP %p could not create request: %s\n",
+ http, strerror ( rc ) );
+ http_done ( http, rc );
+ ref_put ( &http->refcnt );
+ return rc;
+}
+
+/**
+ * Initiate an HTTP connection
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int http_open ( struct xfer_interface *xfer, struct uri *uri ) {
+ return http_open_filter ( xfer, uri, HTTP_PORT, NULL );
+}
+
+/** HTTP URI opener */
+struct uri_opener http_uri_opener __uri_opener = {
+ .scheme = "http",
+ .open = http_open,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/tcp/https.c b/debian/grub-extras/disabled/gpxe/src/net/tcp/https.c
new file mode 100644
index 0000000..7a2961f
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/tcp/https.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Secure Hyper Text Transfer Protocol (HTTPS)
+ *
+ */
+
+#include <stddef.h>
+#include <gpxe/open.h>
+#include <gpxe/tls.h>
+#include <gpxe/http.h>
+#include <gpxe/features.h>
+
+FEATURE ( FEATURE_PROTOCOL, "HTTPS", DHCP_EB_FEATURE_HTTPS, 1 );
+
+/**
+ * Initiate an HTTPS connection
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int https_open ( struct xfer_interface *xfer, struct uri *uri ) {
+ return http_open_filter ( xfer, uri, HTTPS_PORT, add_tls );
+}
+
+/** HTTPS URI opener */
+struct uri_opener https_uri_opener __uri_opener = {
+ .scheme = "https",
+ .open = https_open,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/tcp/iscsi.c b/debian/grub-extras/disabled/gpxe/src/net/tcp/iscsi.c
new file mode 100644
index 0000000..771384b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/tcp/iscsi.c
@@ -0,0 +1,1934 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <gpxe/vsprintf.h>
+#include <gpxe/socket.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/scsi.h>
+#include <gpxe/process.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/settings.h>
+#include <gpxe/features.h>
+#include <gpxe/iscsi.h>
+
+/** @file
+ *
+ * iSCSI protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 );
+
+/** iSCSI initiator name (explicitly specified) */
+static char *iscsi_explicit_initiator_iqn;
+
+/** Default iSCSI initiator name (constructed from hostname) */
+static char *iscsi_default_initiator_iqn;
+
+/** iSCSI initiator username */
+static char *iscsi_initiator_username;
+
+/** iSCSI initiator password */
+static char *iscsi_initiator_password;
+
+/** iSCSI target username */
+static char *iscsi_target_username;
+
+/** iSCSI target password */
+static char *iscsi_target_password;
+
+static void iscsi_start_tx ( struct iscsi_session *iscsi );
+static void iscsi_start_login ( struct iscsi_session *iscsi );
+static void iscsi_start_data_out ( struct iscsi_session *iscsi,
+ unsigned int datasn );
+
+/**
+ * Finish receiving PDU data into buffer
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
+ free ( iscsi->rx_buffer );
+ iscsi->rx_buffer = NULL;
+}
+
+/**
+ * Free iSCSI session
+ *
+ * @v refcnt Reference counter
+ */
+static void iscsi_free ( struct refcnt *refcnt ) {
+ struct iscsi_session *iscsi =
+ container_of ( refcnt, struct iscsi_session, refcnt );
+
+ free ( iscsi->target_address );
+ free ( iscsi->target_iqn );
+ free ( iscsi->initiator_username );
+ free ( iscsi->initiator_password );
+ free ( iscsi->target_username );
+ free ( iscsi->target_password );
+ chap_finish ( &iscsi->chap );
+ iscsi_rx_buffered_data_done ( iscsi );
+ free ( iscsi );
+}
+
+/**
+ * Open iSCSI transport-layer connection
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_open_connection ( struct iscsi_session *iscsi ) {
+ struct sockaddr_tcpip target;
+ int rc;
+
+ assert ( iscsi->tx_state == ISCSI_TX_IDLE );
+ assert ( iscsi->rx_state == ISCSI_RX_BHS );
+ assert ( iscsi->rx_offset == 0 );
+
+ /* Open socket */
+ memset ( &target, 0, sizeof ( target ) );
+ target.st_port = htons ( iscsi->target_port );
+ if ( ( rc = xfer_open_named_socket ( &iscsi->socket, SOCK_STREAM,
+ ( struct sockaddr * ) &target,
+ iscsi->target_address,
+ NULL ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not open socket: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Enter security negotiation phase */
+ iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
+ ISCSI_STATUS_STRINGS_SECURITY );
+ if ( iscsi->target_username )
+ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_REQUIRED;
+
+ /* Assign fresh initiator task tag */
+ iscsi->itt++;
+
+ /* Initiate login */
+ iscsi_start_login ( iscsi );
+
+ return 0;
+}
+
+/**
+ * Close iSCSI transport-layer connection
+ *
+ * @v iscsi iSCSI session
+ * @v rc Reason for close
+ *
+ * Closes the transport-layer connection and resets the session state
+ * ready to attempt a fresh login.
+ */
+static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) {
+
+ /* Close all data transfer interfaces */
+ xfer_close ( &iscsi->socket, rc );
+
+ /* Clear connection status */
+ iscsi->status = 0;
+
+ /* Reset TX and RX state machines */
+ iscsi->tx_state = ISCSI_TX_IDLE;
+ iscsi->rx_state = ISCSI_RX_BHS;
+ iscsi->rx_offset = 0;
+
+ /* Free any temporary dynamically allocated memory */
+ chap_finish ( &iscsi->chap );
+ iscsi_rx_buffered_data_done ( iscsi );
+}
+
+/**
+ * Mark iSCSI SCSI operation as complete
+ *
+ * @v iscsi iSCSI session
+ * @v rc Return status code
+ *
+ * Note that iscsi_scsi_done() will not close the connection, and must
+ * therefore be called only when the internal state machines are in an
+ * appropriate state, otherwise bad things may happen on the next call
+ * to iscsi_issue(). The general rule is to call iscsi_scsi_done()
+ * only at the end of receiving a PDU; at this point the TX and RX
+ * engines should both be idle.
+ */
+static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
+
+ assert ( iscsi->tx_state == ISCSI_TX_IDLE );
+ assert ( iscsi->command != NULL );
+
+ iscsi->command->rc = rc;
+ iscsi->command = NULL;
+}
+
+/****************************************************************************
+ *
+ * iSCSI SCSI command issuing
+ *
+ */
+
+/**
+ * Build iSCSI SCSI command BHS
+ *
+ * @v iscsi iSCSI session
+ *
+ * We don't currently support bidirectional commands (i.e. with both
+ * Data-In and Data-Out segments); these would require providing code
+ * to generate an AHS, and there doesn't seem to be any need for it at
+ * the moment.
+ */
+static void iscsi_start_command ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_scsi_command *command = &iscsi->tx_bhs.scsi_command;
+
+ assert ( ! ( iscsi->command->data_in && iscsi->command->data_out ) );
+
+ /* Construct BHS and initiate transmission */
+ iscsi_start_tx ( iscsi );
+ command->opcode = ISCSI_OPCODE_SCSI_COMMAND;
+ command->flags = ( ISCSI_FLAG_FINAL |
+ ISCSI_COMMAND_ATTR_SIMPLE );
+ if ( iscsi->command->data_in )
+ command->flags |= ISCSI_COMMAND_FLAG_READ;
+ if ( iscsi->command->data_out )
+ command->flags |= ISCSI_COMMAND_FLAG_WRITE;
+ /* lengths left as zero */
+ command->lun = iscsi->lun;
+ command->itt = htonl ( ++iscsi->itt );
+ command->exp_len = htonl ( iscsi->command->data_in_len |
+ iscsi->command->data_out_len );
+ command->cmdsn = htonl ( iscsi->cmdsn );
+ command->expstatsn = htonl ( iscsi->statsn + 1 );
+ memcpy ( &command->cdb, &iscsi->command->cdb, sizeof ( command->cdb ));
+ DBGC2 ( iscsi, "iSCSI %p start " SCSI_CDB_FORMAT " %s %#zx\n",
+ iscsi, SCSI_CDB_DATA ( command->cdb ),
+ ( iscsi->command->data_in ? "in" : "out" ),
+ ( iscsi->command->data_in ?
+ iscsi->command->data_in_len :
+ iscsi->command->data_out_len ) );
+}
+
+/**
+ * Receive data segment of an iSCSI SCSI response PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_scsi_response ( struct iscsi_session *iscsi,
+ const void *data, size_t len,
+ size_t remaining ) {
+ struct iscsi_bhs_scsi_response *response
+ = &iscsi->rx_bhs.scsi_response;
+ int sense_offset;
+
+ /* Capture the sense response code as it floats past, if present */
+ sense_offset = ISCSI_SENSE_RESPONSE_CODE_OFFSET - iscsi->rx_offset;
+ if ( ( sense_offset >= 0 ) && len ) {
+ iscsi->command->sense_response =
+ * ( ( char * ) data + sense_offset );
+ }
+
+ /* Wait for whole SCSI response to arrive */
+ if ( remaining )
+ return 0;
+
+ /* Record SCSI status code */
+ iscsi->command->status = response->status;
+
+ /* Check for errors */
+ if ( response->response != ISCSI_RESPONSE_COMMAND_COMPLETE )
+ return -EIO;
+
+ /* Mark as completed */
+ iscsi_scsi_done ( iscsi, 0 );
+ return 0;
+}
+
+/**
+ * Receive data segment of an iSCSI data-in PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_data_in ( struct iscsi_session *iscsi,
+ const void *data, size_t len,
+ size_t remaining ) {
+ struct iscsi_bhs_data_in *data_in = &iscsi->rx_bhs.data_in;
+ unsigned long offset;
+
+ /* Copy data to data-in buffer */
+ offset = ntohl ( data_in->offset ) + iscsi->rx_offset;
+ assert ( iscsi->command != NULL );
+ assert ( iscsi->command->data_in );
+ assert ( ( offset + len ) <= iscsi->command->data_in_len );
+ copy_to_user ( iscsi->command->data_in, offset, data, len );
+
+ /* Wait for whole SCSI response to arrive */
+ if ( remaining )
+ return 0;
+
+ /* Mark as completed if status is present */
+ if ( data_in->flags & ISCSI_DATA_FLAG_STATUS ) {
+ assert ( ( offset + len ) == iscsi->command->data_in_len );
+ assert ( data_in->flags & ISCSI_FLAG_FINAL );
+ iscsi->command->status = data_in->status;
+ /* iSCSI cannot return an error status via a data-in */
+ iscsi_scsi_done ( iscsi, 0 );
+ }
+
+ return 0;
+}
+
+/**
+ * Receive data segment of an iSCSI R2T PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_r2t ( struct iscsi_session *iscsi,
+ const void *data __unused, size_t len __unused,
+ size_t remaining __unused ) {
+ struct iscsi_bhs_r2t *r2t = &iscsi->rx_bhs.r2t;
+
+ /* Record transfer parameters and trigger first data-out */
+ iscsi->ttt = ntohl ( r2t->ttt );
+ iscsi->transfer_offset = ntohl ( r2t->offset );
+ iscsi->transfer_len = ntohl ( r2t->len );
+ iscsi_start_data_out ( iscsi, 0 );
+
+ return 0;
+}
+
+/**
+ * Build iSCSI data-out BHS
+ *
+ * @v iscsi iSCSI session
+ * @v datasn Data sequence number within the transfer
+ *
+ */
+static void iscsi_start_data_out ( struct iscsi_session *iscsi,
+ unsigned int datasn ) {
+ struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
+ unsigned long offset;
+ unsigned long remaining;
+ unsigned long len;
+
+ /* We always send 512-byte Data-Out PDUs; this removes the
+ * need to worry about the target's MaxRecvDataSegmentLength.
+ */
+ offset = datasn * 512;
+ remaining = iscsi->transfer_len - offset;
+ len = remaining;
+ if ( len > 512 )
+ len = 512;
+
+ /* Construct BHS and initiate transmission */
+ iscsi_start_tx ( iscsi );
+ data_out->opcode = ISCSI_OPCODE_DATA_OUT;
+ if ( len == remaining )
+ data_out->flags = ( ISCSI_FLAG_FINAL );
+ ISCSI_SET_LENGTHS ( data_out->lengths, 0, len );
+ data_out->lun = iscsi->lun;
+ data_out->itt = htonl ( iscsi->itt );
+ data_out->ttt = htonl ( iscsi->ttt );
+ data_out->expstatsn = htonl ( iscsi->statsn + 1 );
+ data_out->datasn = htonl ( datasn );
+ data_out->offset = htonl ( iscsi->transfer_offset + offset );
+ DBGC ( iscsi, "iSCSI %p start data out DataSN %#x len %#lx\n",
+ iscsi, datasn, len );
+}
+
+/**
+ * Complete iSCSI data-out PDU transmission
+ *
+ * @v iscsi iSCSI session
+ *
+ */
+static void iscsi_data_out_done ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
+
+ /* If we haven't reached the end of the sequence, start
+ * sending the next data-out PDU.
+ */
+ if ( ! ( data_out->flags & ISCSI_FLAG_FINAL ) )
+ iscsi_start_data_out ( iscsi, ntohl ( data_out->datasn ) + 1 );
+}
+
+/**
+ * Send iSCSI data-out data segment
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
+ struct io_buffer *iobuf;
+ unsigned long offset;
+ size_t len;
+
+ offset = ntohl ( data_out->offset );
+ len = ISCSI_DATA_LEN ( data_out->lengths );
+
+ assert ( iscsi->command != NULL );
+ assert ( iscsi->command->data_out );
+ assert ( ( offset + len ) <= iscsi->command->data_out_len );
+
+ iobuf = xfer_alloc_iob ( &iscsi->socket, len );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ copy_from_user ( iob_put ( iobuf, len ),
+ iscsi->command->data_out, offset, len );
+
+ return xfer_deliver_iob ( &iscsi->socket, iobuf );
+}
+
+/****************************************************************************
+ *
+ * iSCSI login
+ *
+ */
+
+/**
+ * Build iSCSI login request strings
+ *
+ * @v iscsi iSCSI session
+ *
+ * These are the initial set of strings sent in the first login
+ * request PDU. We want the following settings:
+ *
+ * HeaderDigest=None
+ * DataDigest=None
+ * MaxConnections is irrelevant; we make only one connection anyway
+ * InitialR2T=Yes [1]
+ * ImmediateData is irrelevant; we never send immediate data
+ * MaxRecvDataSegmentLength=8192 (default; we don't care) [3]
+ * MaxBurstLength=262144 (default; we don't care) [3]
+ * FirstBurstLength=262144 (default; we don't care)
+ * DefaultTime2Wait=0 [2]
+ * DefaultTime2Retain=0 [2]
+ * MaxOutstandingR2T=1
+ * DataPDUInOrder=Yes
+ * DataSequenceInOrder=Yes
+ * ErrorRecoveryLevel=0
+ *
+ * [1] InitialR2T has an OR resolution function, so the target may
+ * force us to use it. We therefore simplify our logic by always
+ * using it.
+ *
+ * [2] These ensure that we can safely start a new task once we have
+ * reconnected after a failure, without having to manually tidy up
+ * after the old one.
+ *
+ * [3] We are quite happy to use the RFC-defined default values for
+ * these parameters, but some targets (notably OpenSolaris)
+ * incorrectly assume a default value of zero, so we explicitly
+ * specify the default values.
+ */
+static int iscsi_build_login_request_strings ( struct iscsi_session *iscsi,
+ void *data, size_t len ) {
+ unsigned int used = 0;
+ unsigned int i;
+ const char *auth_method;
+
+ if ( iscsi->status & ISCSI_STATUS_STRINGS_SECURITY ) {
+ /* Default to allowing no authentication */
+ auth_method = "None";
+ /* If we have a credential to supply, permit CHAP */
+ if ( iscsi->initiator_username )
+ auth_method = "CHAP,None";
+ /* If we have a credential to check, force CHAP */
+ if ( iscsi->target_username )
+ auth_method = "CHAP";
+ used += ssnprintf ( data + used, len - used,
+ "InitiatorName=%s%c"
+ "TargetName=%s%c"
+ "SessionType=Normal%c"
+ "AuthMethod=%s%c",
+ iscsi_initiator_iqn(), 0,
+ iscsi->target_iqn, 0, 0,
+ auth_method, 0 );
+ }
+
+ if ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_ALGORITHM ) {
+ used += ssnprintf ( data + used, len - used, "CHAP_A=5%c", 0 );
+ }
+
+ if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_RESPONSE ) ) {
+ assert ( iscsi->initiator_username != NULL );
+ used += ssnprintf ( data + used, len - used,
+ "CHAP_N=%s%cCHAP_R=0x",
+ iscsi->initiator_username, 0 );
+ for ( i = 0 ; i < iscsi->chap.response_len ; i++ ) {
+ used += ssnprintf ( data + used, len - used, "%02x",
+ iscsi->chap.response[i] );
+ }
+ used += ssnprintf ( data + used, len - used, "%c", 0 );
+ }
+
+ if ( ( iscsi->status & ISCSI_STATUS_STRINGS_CHAP_CHALLENGE ) ) {
+ used += ssnprintf ( data + used, len - used,
+ "CHAP_I=%d%cCHAP_C=0x",
+ iscsi->chap_challenge[0], 0 );
+ for ( i = 1 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
+ used += ssnprintf ( data + used, len - used, "%02x",
+ iscsi->chap_challenge[i] );
+ }
+ used += ssnprintf ( data + used, len - used, "%c", 0 );
+ }
+
+ if ( iscsi->status & ISCSI_STATUS_STRINGS_OPERATIONAL ) {
+ used += ssnprintf ( data + used, len - used,
+ "HeaderDigest=None%c"
+ "DataDigest=None%c"
+ "InitialR2T=Yes%c"
+ "MaxRecvDataSegmentLength=8192%c"
+ "MaxBurstLength=262144%c"
+ "DefaultTime2Wait=0%c"
+ "DefaultTime2Retain=0%c"
+ "MaxOutstandingR2T=1%c"
+ "DataPDUInOrder=Yes%c"
+ "DataSequenceInOrder=Yes%c"
+ "ErrorRecoveryLevel=0%c",
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
+ }
+
+ return used;
+}
+
+/**
+ * Build iSCSI login request BHS
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_start_login ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
+ int len;
+
+ /* Construct BHS and initiate transmission */
+ iscsi_start_tx ( iscsi );
+ request->opcode = ( ISCSI_OPCODE_LOGIN_REQUEST |
+ ISCSI_FLAG_IMMEDIATE );
+ request->flags = ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) |
+ ISCSI_LOGIN_FLAG_TRANSITION );
+ /* version_max and version_min left as zero */
+ len = iscsi_build_login_request_strings ( iscsi, NULL, 0 );
+ ISCSI_SET_LENGTHS ( request->lengths, 0, len );
+ request->isid_iana_en = htonl ( ISCSI_ISID_IANA |
+ IANA_EN_FEN_SYSTEMS );
+ /* isid_iana_qual left as zero */
+ request->tsih = htons ( iscsi->tsih );
+ request->itt = htonl ( iscsi->itt );
+ /* cid left as zero */
+ request->cmdsn = htonl ( iscsi->cmdsn );
+ request->expstatsn = htonl ( iscsi->statsn + 1 );
+}
+
+/**
+ * Complete iSCSI login request PDU transmission
+ *
+ * @v iscsi iSCSI session
+ *
+ */
+static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
+
+ /* Clear any "strings to send" flags */
+ iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
+
+ /* Free any dynamically allocated storage used for login */
+ chap_finish ( &iscsi->chap );
+}
+
+/**
+ * Transmit data segment of an iSCSI login request PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ *
+ * For login requests, the data segment consists of the login strings.
+ */
+static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
+ struct io_buffer *iobuf;
+ size_t len;
+
+ len = ISCSI_DATA_LEN ( request->lengths );
+ iobuf = xfer_alloc_iob ( &iscsi->socket, len );
+ if ( ! iobuf )
+ return -ENOMEM;
+ iob_put ( iobuf, len );
+ iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
+ return xfer_deliver_iob ( &iscsi->socket, iobuf );
+}
+
+/**
+ * Handle iSCSI TargetAddress text value
+ *
+ * @v iscsi iSCSI session
+ * @v value TargetAddress value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_targetaddress_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ char *separator;
+
+ DBGC ( iscsi, "iSCSI %p will redirect to %s\n", iscsi, value );
+
+ /* Replace target address */
+ free ( iscsi->target_address );
+ iscsi->target_address = strdup ( value );
+ if ( ! iscsi->target_address )
+ return -ENOMEM;
+
+ /* Replace target port */
+ iscsi->target_port = htons ( ISCSI_PORT );
+ separator = strchr ( iscsi->target_address, ':' );
+ if ( separator ) {
+ *separator = '\0';
+ iscsi->target_port = strtoul ( ( separator + 1 ), NULL, 0 );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI AuthMethod text value
+ *
+ * @v iscsi iSCSI session
+ * @v value AuthMethod value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_authmethod_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+
+ /* If server requests CHAP, send the CHAP_A string */
+ if ( strcmp ( value, "CHAP" ) == 0 ) {
+ DBGC ( iscsi, "iSCSI %p initiating CHAP authentication\n",
+ iscsi );
+ iscsi->status |= ( ISCSI_STATUS_STRINGS_CHAP_ALGORITHM |
+ ISCSI_STATUS_AUTH_FORWARD_REQUIRED );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_A text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_A value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_a_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+
+ /* We only ever offer "5" (i.e. MD5) as an algorithm, so if
+ * the server responds with anything else it is a protocol
+ * violation.
+ */
+ if ( strcmp ( value, "5" ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p got invalid CHAP algorithm \"%s\"\n",
+ iscsi, value );
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_I text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_I value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ unsigned int identifier;
+ char *endp;
+ int rc;
+
+ /* The CHAP identifier is an integer value */
+ identifier = strtoul ( value, &endp, 0 );
+ if ( *endp != '\0' ) {
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP identifier \"%s\"\n",
+ iscsi, value );
+ return -EPROTO;
+ }
+
+ /* Prepare for CHAP with MD5 */
+ chap_finish ( &iscsi->chap );
+ if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Identifier and secret are the first two components of the
+ * challenge.
+ */
+ chap_set_identifier ( &iscsi->chap, identifier );
+ if ( iscsi->initiator_password ) {
+ chap_update ( &iscsi->chap, iscsi->initiator_password,
+ strlen ( iscsi->initiator_password ) );
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_C text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_C value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ char buf[3];
+ char *endp;
+ uint8_t byte;
+ unsigned int i;
+
+ /* Check and strip leading "0x" */
+ if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge \"%s\"\n",
+ iscsi, value );
+ return -EPROTO;
+ }
+ value += 2;
+
+ /* Process challenge an octet at a time */
+ for ( ; ( value[0] && value[1] ) ; value += 2 ) {
+ memcpy ( buf, value, 2 );
+ buf[2] = 0;
+ byte = strtoul ( buf, &endp, 16 );
+ if ( *endp != '\0' ) {
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP challenge "
+ "byte \"%s\"\n", iscsi, buf );
+ return -EPROTO;
+ }
+ chap_update ( &iscsi->chap, &byte, sizeof ( byte ) );
+ }
+
+ /* Build CHAP response */
+ DBGC ( iscsi, "iSCSI %p sending CHAP response\n", iscsi );
+ chap_respond ( &iscsi->chap );
+ iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_RESPONSE;
+
+ /* Send CHAP challenge, if applicable */
+ if ( iscsi->target_username ) {
+ iscsi->status |= ISCSI_STATUS_STRINGS_CHAP_CHALLENGE;
+ /* Generate CHAP challenge data */
+ for ( i = 0 ; i < sizeof ( iscsi->chap_challenge ) ; i++ ) {
+ iscsi->chap_challenge[i] = random();
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_N text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_N value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+
+ /* The target username isn't actually involved at any point in
+ * the authentication process; it merely serves to identify
+ * which password the target is using to generate the CHAP
+ * response. We unnecessarily verify that the username is as
+ * expected, in order to provide mildly helpful diagnostics if
+ * the target is supplying the wrong username/password
+ * combination.
+ */
+ if ( iscsi->target_username &&
+ ( strcmp ( iscsi->target_username, value ) != 0 ) ) {
+ DBGC ( iscsi, "iSCSI %p target username \"%s\" incorrect "
+ "(wanted \"%s\")\n",
+ iscsi, value, iscsi->target_username );
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle iSCSI CHAP_R text value
+ *
+ * @v iscsi iSCSI session
+ * @v value CHAP_R value
+ * @ret rc Return status code
+ */
+static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi,
+ const char *value ) {
+ char buf[3];
+ char *endp;
+ uint8_t byte;
+ unsigned int i;
+ int rc;
+
+ /* Generate CHAP response for verification */
+ chap_finish ( &iscsi->chap );
+ if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] );
+ if ( iscsi->target_password ) {
+ chap_update ( &iscsi->chap, iscsi->target_password,
+ strlen ( iscsi->target_password ) );
+ }
+ chap_update ( &iscsi->chap, &iscsi->chap_challenge[1],
+ ( sizeof ( iscsi->chap_challenge ) - 1 ) );
+ chap_respond ( &iscsi->chap );
+
+ /* Check and strip leading "0x" */
+ if ( ( value[0] != '0' ) || ( value[1] != 'x' ) ) {
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP response \"%s\"\n",
+ iscsi, value );
+ return -EPROTO;
+ }
+ value += 2;
+
+ /* Check CHAP response length */
+ if ( strlen ( value ) != ( 2 * iscsi->chap.response_len ) ) {
+ DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n",
+ iscsi );
+ return -EPROTO;
+ }
+
+ /* Process response an octet at a time */
+ for ( i = 0 ; ( value[0] && value[1] ) ; value += 2, i++ ) {
+ memcpy ( buf, value, 2 );
+ buf[2] = 0;
+ byte = strtoul ( buf, &endp, 16 );
+ if ( *endp != '\0' ) {
+ DBGC ( iscsi, "iSCSI %p saw invalid CHAP response "
+ "byte \"%s\"\n", iscsi, buf );
+ return -EPROTO;
+ }
+ if ( byte != iscsi->chap.response[i] ) {
+ DBGC ( iscsi, "iSCSI %p saw incorrect CHAP "
+ "response\n", iscsi );
+ return -EACCES;
+ }
+ }
+ assert ( i == iscsi->chap.response_len );
+
+ /* Mark session as authenticated */
+ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK;
+
+ return 0;
+}
+
+/** An iSCSI text string that we want to handle */
+struct iscsi_string_type {
+ /** String key
+ *
+ * This is the portion up to and including the "=" sign,
+ * e.g. "InitiatorName=", "CHAP_A=", etc.
+ */
+ const char *key;
+ /** Handle iSCSI string value
+ *
+ * @v iscsi iSCSI session
+ * @v value iSCSI string value
+ * @ret rc Return status code
+ */
+ int ( * handle ) ( struct iscsi_session *iscsi, const char *value );
+};
+
+/** iSCSI text strings that we want to handle */
+static struct iscsi_string_type iscsi_string_types[] = {
+ { "TargetAddress=", iscsi_handle_targetaddress_value },
+ { "AuthMethod=", iscsi_handle_authmethod_value },
+ { "CHAP_A=", iscsi_handle_chap_a_value },
+ { "CHAP_I=", iscsi_handle_chap_i_value },
+ { "CHAP_C=", iscsi_handle_chap_c_value },
+ { "CHAP_N=", iscsi_handle_chap_n_value },
+ { "CHAP_R=", iscsi_handle_chap_r_value },
+ { NULL, NULL }
+};
+
+/**
+ * Handle iSCSI string
+ *
+ * @v iscsi iSCSI session
+ * @v string iSCSI string (in "key=value" format)
+ * @ret rc Return status code
+ */
+static int iscsi_handle_string ( struct iscsi_session *iscsi,
+ const char *string ) {
+ struct iscsi_string_type *type;
+ size_t key_len;
+ int rc;
+
+ for ( type = iscsi_string_types ; type->key ; type++ ) {
+ key_len = strlen ( type->key );
+ if ( strncmp ( string, type->key, key_len ) != 0 )
+ continue;
+ DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string );
+ if ( ( rc = type->handle ( iscsi,
+ ( string + key_len ) ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n",
+ iscsi, string, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+ }
+ DBGC ( iscsi, "iSCSI %p ignoring %s\n", iscsi, string );
+ return 0;
+}
+
+/**
+ * Handle iSCSI strings
+ *
+ * @v iscsi iSCSI session
+ * @v string iSCSI string buffer
+ * @v len Length of string buffer
+ * @ret rc Return status code
+ */
+static int iscsi_handle_strings ( struct iscsi_session *iscsi,
+ const char *strings, size_t len ) {
+ size_t string_len;
+ int rc;
+
+ /* Handle each string in turn, taking care not to overrun the
+ * data buffer in case of badly-terminated data.
+ */
+ while ( 1 ) {
+ string_len = ( strnlen ( strings, len ) + 1 );
+ if ( string_len > len )
+ break;
+ if ( ( rc = iscsi_handle_string ( iscsi, strings ) ) != 0 )
+ return rc;
+ strings += string_len;
+ len -= string_len;
+ }
+ return 0;
+}
+
+/**
+ * Receive PDU data into buffer
+ *
+ * @v iscsi iSCSI session
+ * @v data Data to receive
+ * @v len Length of data
+ * @ret rc Return status code
+ *
+ * This can be used when the RX PDU type handler wishes to buffer up
+ * all received data and process the PDU as a single unit. The caller
+ * is repsonsible for calling iscsi_rx_buffered_data_done() after
+ * processing the data.
+ */
+static int iscsi_rx_buffered_data ( struct iscsi_session *iscsi,
+ const void *data, size_t len ) {
+
+ /* Allocate buffer on first call */
+ if ( ! iscsi->rx_buffer ) {
+ iscsi->rx_buffer = malloc ( iscsi->rx_len );
+ if ( ! iscsi->rx_buffer )
+ return -ENOMEM;
+ }
+
+ /* Copy data to buffer */
+ assert ( ( iscsi->rx_offset + len ) <= iscsi->rx_len );
+ memcpy ( ( iscsi->rx_buffer + iscsi->rx_offset ), data, len );
+
+ return 0;
+}
+
+/**
+ * Convert iSCSI response status to return status code
+ *
+ * @v status_class iSCSI status class
+ * @v status_detail iSCSI status detail
+ * @ret rc Return status code
+ */
+static int iscsi_status_to_rc ( unsigned int status_class,
+ unsigned int status_detail ) {
+ switch ( status_class ) {
+ case ISCSI_STATUS_INITIATOR_ERROR :
+ switch ( status_detail ) {
+ case ISCSI_STATUS_INITIATOR_ERROR_AUTHENTICATION :
+ return -EACCES;
+ case ISCSI_STATUS_INITIATOR_ERROR_AUTHORISATION :
+ return -EPERM;
+ case ISCSI_STATUS_INITIATOR_ERROR_NOT_FOUND :
+ case ISCSI_STATUS_INITIATOR_ERROR_REMOVED :
+ return -ENODEV;
+ default :
+ return -ENOTSUP;
+ }
+ case ISCSI_STATUS_TARGET_ERROR :
+ return -EIO;
+ default :
+ return -EINVAL;
+ }
+}
+
+/**
+ * Receive data segment of an iSCSI login response PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ */
+static int iscsi_rx_login_response ( struct iscsi_session *iscsi,
+ const void *data, size_t len,
+ size_t remaining ) {
+ struct iscsi_bhs_login_response *response
+ = &iscsi->rx_bhs.login_response;
+ int rc;
+
+ /* Buffer up the PDU data */
+ if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not buffer login response: %s\n",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ if ( remaining )
+ return 0;
+
+ /* Process string data and discard string buffer */
+ if ( ( rc = iscsi_handle_strings ( iscsi, iscsi->rx_buffer,
+ iscsi->rx_len ) ) != 0 )
+ return rc;
+ iscsi_rx_buffered_data_done ( iscsi );
+
+ /* Check for login redirection */
+ if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
+ DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
+ iscsi_close_connection ( iscsi, 0 );
+ if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not redirect: %s\n ",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+ }
+
+ /* Check for fatal errors */
+ if ( response->status_class != 0 ) {
+ DBGC ( iscsi, "iSCSI login failure: class %02x detail %02x\n",
+ response->status_class, response->status_detail );
+ rc = iscsi_status_to_rc ( response->status_class,
+ response->status_detail );
+ iscsi->instant_rc = rc;
+ return rc;
+ }
+
+ /* Handle login transitions */
+ if ( response->flags & ISCSI_LOGIN_FLAG_TRANSITION ) {
+ iscsi->status &= ~( ISCSI_STATUS_PHASE_MASK |
+ ISCSI_STATUS_STRINGS_MASK );
+ switch ( response->flags & ISCSI_LOGIN_NSG_MASK ) {
+ case ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION:
+ iscsi->status |=
+ ( ISCSI_STATUS_OPERATIONAL_NEGOTIATION_PHASE |
+ ISCSI_STATUS_STRINGS_OPERATIONAL );
+ break;
+ case ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE:
+ iscsi->status |= ISCSI_STATUS_FULL_FEATURE_PHASE;
+ break;
+ default:
+ DBGC ( iscsi, "iSCSI %p got invalid response flags "
+ "%02x\n", iscsi, response->flags );
+ return -EIO;
+ }
+ }
+
+ /* Send next login request PDU if we haven't reached the full
+ * feature phase yet.
+ */
+ if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) !=
+ ISCSI_STATUS_FULL_FEATURE_PHASE ) {
+ iscsi_start_login ( iscsi );
+ return 0;
+ }
+
+ /* Check that target authentication was successful (if required) */
+ if ( ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) &&
+ ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_OK ) ) {
+ DBGC ( iscsi, "iSCSI %p nefarious target tried to bypass "
+ "authentication\n", iscsi );
+ return -EPROTO;
+ }
+
+ /* Reset retry count */
+ iscsi->retry_count = 0;
+
+ /* Record TSIH for future reference */
+ iscsi->tsih = ntohl ( response->tsih );
+
+ /* Send the actual SCSI command */
+ iscsi_start_command ( iscsi );
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * iSCSI to socket interface
+ *
+ */
+
+/**
+ * Start up a new TX PDU
+ *
+ * @v iscsi iSCSI session
+ *
+ * This initiates the process of sending a new PDU. Only one PDU may
+ * be in transit at any one time.
+ */
+static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
+ assert ( iscsi->tx_state == ISCSI_TX_IDLE );
+
+ /* Initialise TX BHS */
+ memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
+
+ /* Flag TX engine to start transmitting */
+ iscsi->tx_state = ISCSI_TX_BHS;
+}
+
+/**
+ * Transmit nothing
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
+ return 0;
+}
+
+/**
+ * Transmit basic header segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+static int iscsi_tx_bhs ( struct iscsi_session *iscsi ) {
+ return xfer_deliver_raw ( &iscsi->socket, &iscsi->tx_bhs,
+ sizeof ( iscsi->tx_bhs ) );
+}
+
+/**
+ * Transmit data segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ *
+ * Handle transmission of part of a PDU data segment. iscsi::tx_bhs
+ * will be valid when this is called.
+ */
+static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+
+ switch ( common->opcode & ISCSI_OPCODE_MASK ) {
+ case ISCSI_OPCODE_DATA_OUT:
+ return iscsi_tx_data_out ( iscsi );
+ case ISCSI_OPCODE_LOGIN_REQUEST:
+ return iscsi_tx_login_request ( iscsi );
+ default:
+ /* Nothing to send in other states */
+ return 0;
+ }
+}
+
+/**
+ * Transmit data padding of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ *
+ * Handle transmission of any data padding in a PDU data segment.
+ * iscsi::tx_bhs will be valid when this is called.
+ */
+static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
+ static const char pad[] = { '\0', '\0', '\0' };
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+ size_t pad_len;
+
+ pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
+ if ( ! pad_len )
+ return 0;
+
+ return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
+}
+
+/**
+ * Complete iSCSI PDU transmission
+ *
+ * @v iscsi iSCSI session
+ *
+ * Called when a PDU has been completely transmitted and the TX state
+ * machine is about to enter the idle state. iscsi::tx_bhs will be
+ * valid for the just-completed PDU when this is called.
+ */
+static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+
+ switch ( common->opcode & ISCSI_OPCODE_MASK ) {
+ case ISCSI_OPCODE_DATA_OUT:
+ iscsi_data_out_done ( iscsi );
+ case ISCSI_OPCODE_LOGIN_REQUEST:
+ iscsi_login_request_done ( iscsi );
+ default:
+ /* No action */
+ break;
+ }
+}
+
+/**
+ * Transmit iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
+ *
+ * Constructs data to be sent for the current TX state
+ */
+static void iscsi_tx_step ( struct process *process ) {
+ struct iscsi_session *iscsi =
+ container_of ( process, struct iscsi_session, process );
+ struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
+ int ( * tx ) ( struct iscsi_session *iscsi );
+ enum iscsi_tx_state next_state;
+ size_t tx_len;
+ int rc;
+
+ /* Select fragment to transmit */
+ while ( 1 ) {
+ switch ( iscsi->tx_state ) {
+ case ISCSI_TX_IDLE:
+ /* Stop processing */
+ return;
+ case ISCSI_TX_BHS:
+ tx = iscsi_tx_bhs;
+ tx_len = sizeof ( iscsi->tx_bhs );
+ next_state = ISCSI_TX_AHS;
+ break;
+ case ISCSI_TX_AHS:
+ tx = iscsi_tx_nothing;
+ tx_len = 0;
+ next_state = ISCSI_TX_DATA;
+ break;
+ case ISCSI_TX_DATA:
+ tx = iscsi_tx_data;
+ tx_len = ISCSI_DATA_LEN ( common->lengths );
+ next_state = ISCSI_TX_DATA_PADDING;
+ break;
+ case ISCSI_TX_DATA_PADDING:
+ tx = iscsi_tx_data_padding;
+ tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
+ next_state = ISCSI_TX_IDLE;
+ break;
+ default:
+ assert ( 0 );
+ return;
+ }
+
+ /* Check for window availability, if needed */
+ if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
+ /* Cannot transmit at this point; stop processing */
+ return;
+ }
+
+ /* Transmit data */
+ if ( ( rc = tx ( iscsi ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
+ iscsi, strerror ( rc ) );
+ return;
+ }
+
+ /* Move to next state */
+ iscsi->tx_state = next_state;
+ if ( next_state == ISCSI_TX_IDLE )
+ iscsi_tx_done ( iscsi );
+ }
+}
+
+/**
+ * Receive basic header segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ *
+ * This fills in iscsi::rx_bhs with the data from the BHS portion of
+ * the received PDU.
+ */
+static int iscsi_rx_bhs ( struct iscsi_session *iscsi, const void *data,
+ size_t len, size_t remaining __unused ) {
+ memcpy ( &iscsi->rx_bhs.bytes[iscsi->rx_offset], data, len );
+ if ( ( iscsi->rx_offset + len ) >= sizeof ( iscsi->rx_bhs ) ) {
+ DBGC2 ( iscsi, "iSCSI %p received PDU opcode %#x len %#x\n",
+ iscsi, iscsi->rx_bhs.common.opcode,
+ ISCSI_DATA_LEN ( iscsi->rx_bhs.common.lengths ) );
+ }
+ return 0;
+}
+
+/**
+ * Discard portion of an iSCSI PDU.
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ *
+ * This discards data from a portion of a received PDU.
+ */
+static int iscsi_rx_discard ( struct iscsi_session *iscsi __unused,
+ const void *data __unused, size_t len __unused,
+ size_t remaining __unused ) {
+ /* Do nothing */
+ return 0;
+}
+
+/**
+ * Receive data segment of an iSCSI PDU
+ *
+ * @v iscsi iSCSI session
+ * @v data Received data
+ * @v len Length of received data
+ * @v remaining Data remaining after this data
+ * @ret rc Return status code
+ *
+ * Handle processing of part of a PDU data segment. iscsi::rx_bhs
+ * will be valid when this is called.
+ */
+static int iscsi_rx_data ( struct iscsi_session *iscsi, const void *data,
+ size_t len, size_t remaining ) {
+ struct iscsi_bhs_common_response *response
+ = &iscsi->rx_bhs.common_response;
+
+ /* Update cmdsn and statsn */
+ iscsi->cmdsn = ntohl ( response->expcmdsn );
+ iscsi->statsn = ntohl ( response->statsn );
+
+ switch ( response->opcode & ISCSI_OPCODE_MASK ) {
+ case ISCSI_OPCODE_LOGIN_RESPONSE:
+ return iscsi_rx_login_response ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_SCSI_RESPONSE:
+ return iscsi_rx_scsi_response ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_DATA_IN:
+ return iscsi_rx_data_in ( iscsi, data, len, remaining );
+ case ISCSI_OPCODE_R2T:
+ return iscsi_rx_r2t ( iscsi, data, len, remaining );
+ default:
+ if ( remaining )
+ return 0;
+ DBGC ( iscsi, "iSCSI %p unknown opcode %02x\n", iscsi,
+ response->opcode );
+ return -ENOTSUP;
+ }
+}
+
+/**
+ * Receive new data
+ *
+ * @v socket Transport layer interface
+ * @v data Received data
+ * @v len Length of received data
+ * @ret rc Return status code
+ *
+ * This handles received PDUs. The receive strategy is to fill in
+ * iscsi::rx_bhs with the contents of the BHS portion of the PDU,
+ * throw away any AHS portion, and then process each part of the data
+ * portion as it arrives. The data processing routine therefore
+ * always has a full copy of the BHS available, even for portions of
+ * the data in different packets to the BHS.
+ */
+static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
+ const void *data, size_t len ) {
+ struct iscsi_session *iscsi =
+ container_of ( socket, struct iscsi_session, socket );
+ struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
+ int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
+ size_t len, size_t remaining );
+ enum iscsi_rx_state next_state;
+ size_t frag_len;
+ size_t remaining;
+ int rc;
+
+ while ( 1 ) {
+ switch ( iscsi->rx_state ) {
+ case ISCSI_RX_BHS:
+ rx = iscsi_rx_bhs;
+ iscsi->rx_len = sizeof ( iscsi->rx_bhs );
+ next_state = ISCSI_RX_AHS;
+ break;
+ case ISCSI_RX_AHS:
+ rx = iscsi_rx_discard;
+ iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
+ next_state = ISCSI_RX_DATA;
+ break;
+ case ISCSI_RX_DATA:
+ rx = iscsi_rx_data;
+ iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
+ next_state = ISCSI_RX_DATA_PADDING;
+ break;
+ case ISCSI_RX_DATA_PADDING:
+ rx = iscsi_rx_discard;
+ iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
+ next_state = ISCSI_RX_BHS;
+ break;
+ default:
+ assert ( 0 );
+ return -EINVAL;
+ }
+
+ frag_len = iscsi->rx_len - iscsi->rx_offset;
+ if ( frag_len > len )
+ frag_len = len;
+ remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
+ if ( ( rc = rx ( iscsi, data, frag_len, remaining ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not process received "
+ "data: %s\n", iscsi, strerror ( rc ) );
+ iscsi_close_connection ( iscsi, rc );
+ iscsi_scsi_done ( iscsi, rc );
+ return rc;
+ }
+
+ iscsi->rx_offset += frag_len;
+ data += frag_len;
+ len -= frag_len;
+
+ /* If all the data for this state has not yet been
+ * received, stay in this state for now.
+ */
+ if ( iscsi->rx_offset != iscsi->rx_len )
+ return 0;
+
+ iscsi->rx_state = next_state;
+ iscsi->rx_offset = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * Handle stream connection closure
+ *
+ * @v socket Transport layer interface
+ * @v rc Reason for close
+ *
+ */
+static void iscsi_socket_close ( struct xfer_interface *socket, int rc ) {
+ struct iscsi_session *iscsi =
+ container_of ( socket, struct iscsi_session, socket );
+
+ /* Even a graceful close counts as an error for iSCSI */
+ if ( ! rc )
+ rc = -ECONNRESET;
+
+ /* Close session cleanly */
+ iscsi_close_connection ( iscsi, rc );
+
+ /* Retry connection if within the retry limit, otherwise fail */
+ if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
+ DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
+ iscsi, iscsi->retry_count );
+ if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not reconnect: %s\n",
+ iscsi, strerror ( rc ) );
+ iscsi_scsi_done ( iscsi, rc );
+ }
+ } else {
+ DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
+ iscsi->instant_rc = rc;
+ iscsi_scsi_done ( iscsi, rc );
+ }
+}
+
+/**
+ * Handle redirection event
+ *
+ * @v socket Transport layer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ */
+static int iscsi_vredirect ( struct xfer_interface *socket, int type,
+ va_list args ) {
+ struct iscsi_session *iscsi =
+ container_of ( socket, struct iscsi_session, socket );
+ va_list tmp;
+ struct sockaddr *peer;
+
+ /* Intercept redirects to a LOCATION_SOCKET and record the IP
+ * address for the iBFT. This is a bit of a hack, but avoids
+ * inventing an ioctl()-style call to retrieve the socket
+ * address from a data-xfer interface.
+ */
+ if ( type == LOCATION_SOCKET ) {
+ va_copy ( tmp, args );
+ ( void ) va_arg ( tmp, int ); /* Discard "semantics" */
+ peer = va_arg ( tmp, struct sockaddr * );
+ memcpy ( &iscsi->target_sockaddr, peer,
+ sizeof ( iscsi->target_sockaddr ) );
+ va_end ( tmp );
+ }
+
+ return xfer_vreopen ( socket, type, args );
+}
+
+
+/** iSCSI socket operations */
+static struct xfer_interface_operations iscsi_socket_operations = {
+ .close = iscsi_socket_close,
+ .vredirect = iscsi_vredirect,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = iscsi_socket_deliver_raw,
+};
+
+
+/****************************************************************************
+ *
+ * iSCSI command issuing
+ *
+ */
+
+/**
+ * Issue SCSI command
+ *
+ * @v scsi SCSI device
+ * @v command SCSI command
+ * @ret rc Return status code
+ */
+static int iscsi_command ( struct scsi_device *scsi,
+ struct scsi_command *command ) {
+ struct iscsi_session *iscsi =
+ container_of ( scsi->backend, struct iscsi_session, refcnt );
+ int rc;
+
+ /* Abort immediately if we have a recorded permanent failure */
+ if ( iscsi->instant_rc )
+ return iscsi->instant_rc;
+
+ /* Record SCSI command */
+ iscsi->command = command;
+
+ /* Issue command or open connection as appropriate */
+ if ( iscsi->status ) {
+ iscsi_start_command ( iscsi );
+ } else {
+ if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
+ iscsi->command = NULL;
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Shut down iSCSI interface
+ *
+ * @v scsi SCSI device
+ */
+void iscsi_detach ( struct scsi_device *scsi ) {
+ struct iscsi_session *iscsi =
+ container_of ( scsi->backend, struct iscsi_session, refcnt );
+
+ xfer_nullify ( &iscsi->socket );
+ iscsi_close_connection ( iscsi, 0 );
+ process_del ( &iscsi->process );
+ scsi->command = scsi_detached_command;
+ ref_put ( scsi->backend );
+ scsi->backend = NULL;
+}
+
+/****************************************************************************
+ *
+ * Instantiator
+ *
+ */
+
+/** iSCSI root path components (as per RFC4173) */
+enum iscsi_root_path_component {
+ RP_LITERAL = 0,
+ RP_SERVERNAME,
+ RP_PROTOCOL,
+ RP_PORT,
+ RP_LUN,
+ RP_TARGETNAME,
+ NUM_RP_COMPONENTS
+};
+
+/**
+ * Parse iSCSI root path
+ *
+ * @v iscsi iSCSI session
+ * @v root_path iSCSI root path (as per RFC4173)
+ * @ret rc Return status code
+ */
+static int iscsi_parse_root_path ( struct iscsi_session *iscsi,
+ const char *root_path ) {
+ char rp_copy[ strlen ( root_path ) + 1 ];
+ char *rp_comp[NUM_RP_COMPONENTS];
+ char *rp = rp_copy;
+ int i = 0;
+ int rc;
+
+ /* Split root path into component parts */
+ strcpy ( rp_copy, root_path );
+ while ( 1 ) {
+ rp_comp[i++] = rp;
+ if ( i == NUM_RP_COMPONENTS )
+ break;
+ for ( ; *rp != ':' ; rp++ ) {
+ if ( ! *rp ) {
+ DBGC ( iscsi, "iSCSI %p root path \"%s\" "
+ "too short\n", iscsi, root_path );
+ return -EINVAL;
+ }
+ }
+ *(rp++) = '\0';
+ }
+
+ /* Use root path components to configure iSCSI session */
+ iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] );
+ if ( ! iscsi->target_address )
+ return -ENOMEM;
+ iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 );
+ if ( ! iscsi->target_port )
+ iscsi->target_port = ISCSI_PORT;
+ if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n",
+ iscsi, rp_comp[RP_LUN] );
+ return rc;
+ }
+ iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] );
+ if ( ! iscsi->target_iqn )
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * Set iSCSI authentication details
+ *
+ * @v iscsi iSCSI session
+ * @v initiator_username Initiator username, if any
+ * @v initiator_password Initiator password, if any
+ * @v target_username Target username, if any
+ * @v target_password Target password, if any
+ * @ret rc Return status code
+ */
+static int iscsi_set_auth ( struct iscsi_session *iscsi,
+ const char *initiator_username,
+ const char *initiator_password,
+ const char *target_username,
+ const char *target_password ) {
+
+ /* Check for initiator or target credentials */
+ if ( initiator_username || initiator_password ||
+ target_username || target_password ) {
+
+ /* We must have at least an initiator username+password */
+ if ( ! ( initiator_username && initiator_password ) )
+ goto invalid_auth;
+
+ /* Store initiator credentials */
+ iscsi->initiator_username = strdup ( initiator_username );
+ if ( ! iscsi->initiator_username )
+ return -ENOMEM;
+ iscsi->initiator_password = strdup ( initiator_password );
+ if ( ! iscsi->initiator_password )
+ return -ENOMEM;
+
+ /* Check for target credentials */
+ if ( target_username || target_password ) {
+
+ /* We must have target username+password */
+ if ( ! ( target_username && target_password ) )
+ goto invalid_auth;
+
+ /* Store target credentials */
+ iscsi->target_username = strdup ( target_username );
+ if ( ! iscsi->target_username )
+ return -ENOMEM;
+ iscsi->target_password = strdup ( target_password );
+ if ( ! iscsi->target_password )
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+
+ invalid_auth:
+ DBGC ( iscsi, "iSCSI %p invalid credentials: initiator "
+ "%sname,%spw, target %sname,%spw\n", iscsi,
+ ( initiator_username ? "" : "no " ),
+ ( initiator_password ? "" : "no " ),
+ ( target_username ? "" : "no " ),
+ ( target_password ? "" : "no " ) );
+ return -EINVAL;
+}
+
+/**
+ * Attach iSCSI interface
+ *
+ * @v scsi SCSI device
+ * @v root_path iSCSI root path (as per RFC4173)
+ * @ret rc Return status code
+ */
+int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
+ struct iscsi_session *iscsi;
+ int rc;
+
+ /* Allocate and initialise structure */
+ iscsi = zalloc ( sizeof ( *iscsi ) );
+ if ( ! iscsi )
+ return -ENOMEM;
+ iscsi->refcnt.free = iscsi_free;
+ xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt );
+ process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt );
+
+ /* Parse root path */
+ if ( ( rc = iscsi_parse_root_path ( iscsi, root_path ) ) != 0 )
+ goto err;
+ /* Set fields not specified by root path */
+ if ( ( rc = iscsi_set_auth ( iscsi,
+ iscsi_initiator_username,
+ iscsi_initiator_password,
+ iscsi_target_username,
+ iscsi_target_password ) ) != 0 )
+ goto err;
+
+ /* Sanity checks */
+ if ( ! iscsi->target_address ) {
+ DBGC ( iscsi, "iSCSI %p does not yet support discovery\n",
+ iscsi );
+ rc = -ENOTSUP;
+ goto err;
+ }
+ if ( ! iscsi->target_iqn ) {
+ DBGC ( iscsi, "iSCSI %p no target address supplied in %s\n",
+ iscsi, root_path );
+ rc = -EINVAL;
+ goto err;
+ }
+
+ /* Attach parent interface, mortalise self, and return */
+ scsi->backend = ref_get ( &iscsi->refcnt );
+ scsi->command = iscsi_command;
+ ref_put ( &iscsi->refcnt );
+ return 0;
+
+ err:
+ ref_put ( &iscsi->refcnt );
+ return rc;
+}
+
+/****************************************************************************
+ *
+ * Settings
+ *
+ */
+
+/** iSCSI initiator IQN setting */
+struct setting initiator_iqn_setting __setting = {
+ .name = "initiator-iqn",
+ .description = "iSCSI initiator name",
+ .tag = DHCP_ISCSI_INITIATOR_IQN,
+ .type = &setting_type_string,
+};
+
+/** iSCSI reverse username setting */
+struct setting reverse_username_setting __setting = {
+ .name = "reverse-username",
+ .description = "Reverse user name",
+ .tag = DHCP_EB_REVERSE_USERNAME,
+ .type = &setting_type_string,
+};
+
+/** iSCSI reverse password setting */
+struct setting reverse_password_setting __setting = {
+ .name = "reverse-password",
+ .description = "Reverse password",
+ .tag = DHCP_EB_REVERSE_PASSWORD,
+ .type = &setting_type_string,
+};
+
+/** An iSCSI string setting */
+struct iscsi_string_setting {
+ /** Setting */
+ struct setting *setting;
+ /** String to update */
+ char **string;
+ /** String prefix */
+ const char *prefix;
+};
+
+/** iSCSI string settings */
+static struct iscsi_string_setting iscsi_string_settings[] = {
+ {
+ .setting = &initiator_iqn_setting,
+ .string = &iscsi_explicit_initiator_iqn,
+ .prefix = "",
+ },
+ {
+ .setting = &username_setting,
+ .string = &iscsi_initiator_username,
+ .prefix = "",
+ },
+ {
+ .setting = &password_setting,
+ .string = &iscsi_initiator_password,
+ .prefix = "",
+ },
+ {
+ .setting = &reverse_username_setting,
+ .string = &iscsi_target_username,
+ .prefix = "",
+ },
+ {
+ .setting = &reverse_password_setting,
+ .string = &iscsi_target_password,
+ .prefix = "",
+ },
+ {
+ .setting = &hostname_setting,
+ .string = &iscsi_default_initiator_iqn,
+ .prefix = "iqn.2000-01.org.etherboot:",
+ },
+};
+
+/**
+ * Apply iSCSI setting
+ *
+ * @v setting iSCSI string setting
+ * @ret rc Return status code
+ */
+static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
+ size_t prefix_len;
+ int setting_len;
+ size_t len;
+ int check_len;
+ char *p;
+
+ /* Free old string */
+ free ( *setting->string );
+ *setting->string = NULL;
+
+ /* Allocate new string */
+ prefix_len = strlen ( setting->prefix );
+ setting_len = fetch_setting_len ( NULL, setting->setting );
+ if ( setting_len < 0 ) {
+ /* Missing settings are not errors; leave strings as NULL */
+ return 0;
+ }
+ len = ( prefix_len + setting_len + 1 );
+ p = *setting->string = malloc ( len );
+ if ( ! p )
+ return -ENOMEM;
+
+ /* Fill new string */
+ strcpy ( p, setting->prefix );
+ check_len = fetch_string_setting ( NULL, setting->setting,
+ ( p + prefix_len ),
+ ( len - prefix_len ) );
+ assert ( check_len == setting_len );
+
+ return 0;
+}
+
+/**
+ * Apply iSCSI settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_iscsi_settings ( void ) {
+ struct iscsi_string_setting *setting;
+ unsigned int i;
+ int rc;
+
+ for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
+ sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
+ setting = &iscsi_string_settings[i];
+ if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
+ DBG ( "iSCSI could not apply setting %s\n",
+ setting->setting->name );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/** iSCSI settings applicator */
+struct settings_applicator iscsi_settings_applicator __settings_applicator = {
+ .apply = apply_iscsi_settings,
+};
+
+/****************************************************************************
+ *
+ * Initiator name
+ *
+ */
+
+/**
+ * Get iSCSI initiator IQN
+ *
+ * @v iscsi iSCSI session
+ * @ret rc Return status code
+ */
+const char * iscsi_initiator_iqn ( void ) {
+
+ if ( iscsi_explicit_initiator_iqn )
+ return iscsi_explicit_initiator_iqn;
+ if ( iscsi_default_initiator_iqn )
+ return iscsi_default_initiator_iqn;
+ return "iqn.2000-09.org.etherboot:UNKNOWN";
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/tcpip.c b/debian/grub-extras/disabled/gpxe/src/net/tcpip.c
new file mode 100644
index 0000000..932fd48
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/tcpip.c
@@ -0,0 +1,135 @@
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/tables.h>
+#include <gpxe/tcpip.h>
+
+/** @file
+ *
+ * Transport-network layer interface
+ *
+ * This file contains functions and utilities for the
+ * TCP/IP transport-network layer interface
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** Process a received TCP/IP packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_proto Transport-layer protocol number
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ *
+ * This function expects a transport-layer segment from the network
+ * layer. The network layer should fill in as much as it can of the
+ * source and destination addresses (i.e. it should fill in the
+ * address family and the network-layer addresses, but leave the ports
+ * and the rest of the structures as zero).
+ */
+int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
+ struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest,
+ uint16_t pshdr_csum ) {
+ struct tcpip_protocol *tcpip;
+
+ /* Hand off packet to the appropriate transport-layer protocol */
+ for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
+ if ( tcpip->tcpip_proto == tcpip_proto ) {
+ DBG ( "TCP/IP received %s packet\n", tcpip->name );
+ return tcpip->rx ( iobuf, st_src, st_dest, pshdr_csum );
+ }
+ }
+
+ DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
+ free_iob ( iobuf );
+ return -EPROTONOSUPPORT;
+}
+
+/** Transmit a TCP/IP packet
+ *
+ * @v iobuf I/O buffer
+ * @v tcpip_protocol Transport-layer protocol
+ * @v st_src Source address, or NULL to use route default
+ * @v st_dest Destination address
+ * @v netdev Network device to use if no route found, or NULL
+ * @v trans_csum Transport-layer checksum to complete, or NULL
+ * @ret rc Return status code
+ */
+int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
+ struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
+ struct net_device *netdev, uint16_t *trans_csum ) {
+ struct tcpip_net_protocol *tcpip_net;
+
+ /* Hand off packet to the appropriate network-layer protocol */
+ for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
+ if ( tcpip_net->sa_family == st_dest->st_family ) {
+ DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
+ return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
+ st_dest, netdev, trans_csum );
+ }
+ }
+
+ DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
+ free_iob ( iobuf );
+ return -EAFNOSUPPORT;
+}
+
+/**
+ * Calculate continued TCP/IP checkum
+ *
+ * @v partial Checksum of already-summed data, in network byte order
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret cksum Updated checksum, in network byte order
+ *
+ * Calculates a TCP/IP-style 16-bit checksum over the data block. The
+ * checksum is returned in network byte order.
+ *
+ * This function may be used to add new data to an existing checksum.
+ * The function assumes that both the old data and the new data start
+ * on even byte offsets; if this is not the case then you will need to
+ * byte-swap either the input partial checksum, the output checksum,
+ * or both. Deciding which to swap is left as an exercise for the
+ * interested reader.
+ */
+uint16_t tcpip_continue_chksum ( uint16_t partial, const void *data,
+ size_t len ) {
+ unsigned int cksum = ( ( ~partial ) & 0xffff );
+ unsigned int value;
+ unsigned int i;
+
+ for ( i = 0 ; i < len ; i++ ) {
+ value = * ( ( uint8_t * ) data + i );
+ if ( i & 1 ) {
+ /* Odd bytes: swap on little-endian systems */
+ value = be16_to_cpu ( value );
+ } else {
+ /* Even bytes: swap on big-endian systems */
+ value = le16_to_cpu ( value );
+ }
+ cksum += value;
+ if ( cksum > 0xffff )
+ cksum -= 0xffff;
+ }
+
+ return ( ~cksum );
+}
+
+/**
+ * Calculate TCP/IP checkum
+ *
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret cksum Checksum, in network byte order
+ *
+ * Calculates a TCP/IP-style 16-bit checksum over the data block. The
+ * checksum is returned in network byte order.
+ */
+uint16_t tcpip_chksum ( const void *data, size_t len ) {
+ return tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, len );
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/tls.c b/debian/grub-extras/disabled/gpxe/src/net/tls.c
new file mode 100644
index 0000000..a5b126e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/tls.c
@@ -0,0 +1,1759 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Transport Layer Security Protocol
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/hmac.h>
+#include <gpxe/md5.h>
+#include <gpxe/sha1.h>
+#include <gpxe/aes.h>
+#include <gpxe/rsa.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/filter.h>
+#include <gpxe/asn1.h>
+#include <gpxe/x509.h>
+#include <gpxe/tls.h>
+
+static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
+ const void *data, size_t len );
+static void tls_clear_cipher ( struct tls_session *tls,
+ struct tls_cipherspec *cipherspec );
+
+/******************************************************************************
+ *
+ * Utility functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Extract 24-bit field value
+ *
+ * @v field24 24-bit field
+ * @ret value Field value
+ *
+ * TLS uses 24-bit integers in several places, which are awkward to
+ * parse in C.
+ */
+static unsigned long tls_uint24 ( uint8_t field24[3] ) {
+ return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] );
+}
+
+/******************************************************************************
+ *
+ * Cleanup functions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Free TLS session
+ *
+ * @v refcnt Reference counter
+ */
+static void free_tls ( struct refcnt *refcnt ) {
+ struct tls_session *tls =
+ container_of ( refcnt, struct tls_session, refcnt );
+
+ /* Free dynamically-allocated resources */
+ tls_clear_cipher ( tls, &tls->tx_cipherspec );
+ tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
+ x509_free_rsa_public_key ( &tls->rsa );
+ free ( tls->rx_data );
+
+ /* Free TLS structure itself */
+ free ( tls );
+}
+
+/**
+ * Finish with TLS session
+ *
+ * @v tls TLS session
+ * @v rc Status code
+ */
+static void tls_close ( struct tls_session *tls, int rc ) {
+
+ /* Remove process */
+ process_del ( &tls->process );
+
+ /* Close ciphertext and plaintext streams */
+ xfer_nullify ( &tls->cipherstream.xfer );
+ xfer_close ( &tls->cipherstream.xfer, rc );
+ xfer_nullify ( &tls->plainstream.xfer );
+ xfer_close ( &tls->plainstream.xfer, rc );
+}
+
+/******************************************************************************
+ *
+ * Random number generation
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Generate random data
+ *
+ * @v data Buffer to fill
+ * @v len Length of buffer
+ */
+static void tls_generate_random ( void *data, size_t len ) {
+ /* FIXME: Some real random data source would be nice... */
+ memset ( data, 0x01, len );
+}
+
+/**
+ * Update HMAC with a list of ( data, len ) pairs
+ *
+ * @v digest Hash function to use
+ * @v digest_ctx Digest context
+ * @v args ( data, len ) pairs of data, terminated by NULL
+ */
+static void tls_hmac_update_va ( struct digest_algorithm *digest,
+ void *digest_ctx, va_list args ) {
+ void *data;
+ size_t len;
+
+ while ( ( data = va_arg ( args, void * ) ) ) {
+ len = va_arg ( args, size_t );
+ hmac_update ( digest, digest_ctx, data, len );
+ }
+}
+
+/**
+ * Generate secure pseudo-random data using a single hash function
+ *
+ * @v tls TLS session
+ * @v digest Hash function to use
+ * @v secret Secret
+ * @v secret_len Length of secret
+ * @v out Output buffer
+ * @v out_len Length of output buffer
+ * @v seeds ( data, len ) pairs of seed data, terminated by NULL
+ */
+static void tls_p_hash_va ( struct tls_session *tls,
+ struct digest_algorithm *digest,
+ void *secret, size_t secret_len,
+ void *out, size_t out_len,
+ va_list seeds ) {
+ uint8_t secret_copy[secret_len];
+ uint8_t digest_ctx[digest->ctxsize];
+ uint8_t digest_ctx_partial[digest->ctxsize];
+ uint8_t a[digest->digestsize];
+ uint8_t out_tmp[digest->digestsize];
+ size_t frag_len = digest->digestsize;
+ va_list tmp;
+
+ /* Copy the secret, in case HMAC modifies it */
+ memcpy ( secret_copy, secret, secret_len );
+ secret = secret_copy;
+ DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name );
+ DBGC2_HD ( tls, secret, secret_len );
+
+ /* Calculate A(1) */
+ hmac_init ( digest, digest_ctx, secret, &secret_len );
+ va_copy ( tmp, seeds );
+ tls_hmac_update_va ( digest, digest_ctx, tmp );
+ va_end ( tmp );
+ hmac_final ( digest, digest_ctx, secret, &secret_len, a );
+ DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name );
+ DBGC2_HD ( tls, &a, sizeof ( a ) );
+
+ /* Generate as much data as required */
+ while ( out_len ) {
+ /* Calculate output portion */
+ hmac_init ( digest, digest_ctx, secret, &secret_len );
+ hmac_update ( digest, digest_ctx, a, sizeof ( a ) );
+ memcpy ( digest_ctx_partial, digest_ctx, digest->ctxsize );
+ va_copy ( tmp, seeds );
+ tls_hmac_update_va ( digest, digest_ctx, tmp );
+ va_end ( tmp );
+ hmac_final ( digest, digest_ctx,
+ secret, &secret_len, out_tmp );
+
+ /* Copy output */
+ if ( frag_len > out_len )
+ frag_len = out_len;
+ memcpy ( out, out_tmp, frag_len );
+ DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name );
+ DBGC2_HD ( tls, out, frag_len );
+
+ /* Calculate A(i) */
+ hmac_final ( digest, digest_ctx_partial,
+ secret, &secret_len, a );
+ DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name );
+ DBGC2_HD ( tls, &a, sizeof ( a ) );
+
+ out += frag_len;
+ out_len -= frag_len;
+ }
+}
+
+/**
+ * Generate secure pseudo-random data
+ *
+ * @v tls TLS session
+ * @v secret Secret
+ * @v secret_len Length of secret
+ * @v out Output buffer
+ * @v out_len Length of output buffer
+ * @v ... ( data, len ) pairs of seed data, terminated by NULL
+ */
+static void tls_prf ( struct tls_session *tls, void *secret, size_t secret_len,
+ void *out, size_t out_len, ... ) {
+ va_list seeds;
+ va_list tmp;
+ size_t subsecret_len;
+ void *md5_secret;
+ void *sha1_secret;
+ uint8_t out_md5[out_len];
+ uint8_t out_sha1[out_len];
+ unsigned int i;
+
+ va_start ( seeds, out_len );
+
+ /* Split secret into two, with an overlap of up to one byte */
+ subsecret_len = ( ( secret_len + 1 ) / 2 );
+ md5_secret = secret;
+ sha1_secret = ( secret + secret_len - subsecret_len );
+
+ /* Calculate MD5 portion */
+ va_copy ( tmp, seeds );
+ tls_p_hash_va ( tls, &md5_algorithm, md5_secret, subsecret_len,
+ out_md5, out_len, seeds );
+ va_end ( tmp );
+
+ /* Calculate SHA1 portion */
+ va_copy ( tmp, seeds );
+ tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret, subsecret_len,
+ out_sha1, out_len, seeds );
+ va_end ( tmp );
+
+ /* XOR the two portions together into the final output buffer */
+ for ( i = 0 ; i < out_len ; i++ ) {
+ *( ( uint8_t * ) out + i ) = ( out_md5[i] ^ out_sha1[i] );
+ }
+
+ va_end ( seeds );
+}
+
+/**
+ * Generate secure pseudo-random data
+ *
+ * @v secret Secret
+ * @v secret_len Length of secret
+ * @v out Output buffer
+ * @v out_len Length of output buffer
+ * @v label String literal label
+ * @v ... ( data, len ) pairs of seed data
+ */
+#define tls_prf_label( tls, secret, secret_len, out, out_len, label, ... ) \
+ tls_prf ( (tls), (secret), (secret_len), (out), (out_len), \
+ label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL )
+
+/******************************************************************************
+ *
+ * Secret management
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Generate master secret
+ *
+ * @v tls TLS session
+ *
+ * The pre-master secret and the client and server random values must
+ * already be known.
+ */
+static void tls_generate_master_secret ( struct tls_session *tls ) {
+ DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
+ DBGC_HD ( tls, &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ) );
+ DBGC ( tls, "TLS %p client random bytes:\n", tls );
+ DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
+ DBGC ( tls, "TLS %p server random bytes:\n", tls );
+ DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
+
+ tls_prf_label ( tls, &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ),
+ &tls->master_secret, sizeof ( tls->master_secret ),
+ "master secret",
+ &tls->client_random, sizeof ( tls->client_random ),
+ &tls->server_random, sizeof ( tls->server_random ) );
+
+ DBGC ( tls, "TLS %p generated master secret:\n", tls );
+ DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
+}
+
+/**
+ * Generate key material
+ *
+ * @v tls TLS session
+ *
+ * The master secret must already be known.
+ */
+static int tls_generate_keys ( struct tls_session *tls ) {
+ struct tls_cipherspec *tx_cipherspec = &tls->tx_cipherspec_pending;
+ struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending;
+ size_t hash_size = tx_cipherspec->digest->digestsize;
+ size_t key_size = tx_cipherspec->key_len;
+ size_t iv_size = tx_cipherspec->cipher->blocksize;
+ size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
+ uint8_t key_block[total];
+ uint8_t *key;
+ int rc;
+
+ /* Generate key block */
+ tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
+ key_block, sizeof ( key_block ), "key expansion",
+ &tls->server_random, sizeof ( tls->server_random ),
+ &tls->client_random, sizeof ( tls->client_random ) );
+
+ /* Split key block into portions */
+ key = key_block;
+
+ /* TX MAC secret */
+ memcpy ( tx_cipherspec->mac_secret, key, hash_size );
+ DBGC ( tls, "TLS %p TX MAC secret:\n", tls );
+ DBGC_HD ( tls, key, hash_size );
+ key += hash_size;
+
+ /* RX MAC secret */
+ memcpy ( rx_cipherspec->mac_secret, key, hash_size );
+ DBGC ( tls, "TLS %p RX MAC secret:\n", tls );
+ DBGC_HD ( tls, key, hash_size );
+ key += hash_size;
+
+ /* TX key */
+ if ( ( rc = cipher_setkey ( tx_cipherspec->cipher,
+ tx_cipherspec->cipher_ctx,
+ key, key_size ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not set TX key: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( tls, "TLS %p TX key:\n", tls );
+ DBGC_HD ( tls, key, key_size );
+ key += key_size;
+
+ /* RX key */
+ if ( ( rc = cipher_setkey ( rx_cipherspec->cipher,
+ rx_cipherspec->cipher_ctx,
+ key, key_size ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not set TX key: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ DBGC ( tls, "TLS %p RX key:\n", tls );
+ DBGC_HD ( tls, key, key_size );
+ key += key_size;
+
+ /* TX initialisation vector */
+ cipher_setiv ( tx_cipherspec->cipher, tx_cipherspec->cipher_ctx, key );
+ DBGC ( tls, "TLS %p TX IV:\n", tls );
+ DBGC_HD ( tls, key, iv_size );
+ key += iv_size;
+
+ /* RX initialisation vector */
+ cipher_setiv ( rx_cipherspec->cipher, rx_cipherspec->cipher_ctx, key );
+ DBGC ( tls, "TLS %p RX IV:\n", tls );
+ DBGC_HD ( tls, key, iv_size );
+ key += iv_size;
+
+ assert ( ( key_block + total ) == key );
+
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Cipher suite management
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Clear cipher suite
+ *
+ * @v cipherspec TLS cipher specification
+ */
+static void tls_clear_cipher ( struct tls_session *tls __unused,
+ struct tls_cipherspec *cipherspec ) {
+ free ( cipherspec->dynamic );
+ memset ( cipherspec, 0, sizeof ( cipherspec ) );
+ cipherspec->pubkey = &pubkey_null;
+ cipherspec->cipher = &cipher_null;
+ cipherspec->digest = &digest_null;
+}
+
+/**
+ * Set cipher suite
+ *
+ * @v tls TLS session
+ * @v cipherspec TLS cipher specification
+ * @v pubkey Public-key encryption elgorithm
+ * @v cipher Bulk encryption cipher algorithm
+ * @v digest MAC digest algorithm
+ * @v key_len Key length
+ * @ret rc Return status code
+ */
+static int tls_set_cipher ( struct tls_session *tls,
+ struct tls_cipherspec *cipherspec,
+ struct pubkey_algorithm *pubkey,
+ struct cipher_algorithm *cipher,
+ struct digest_algorithm *digest,
+ size_t key_len ) {
+ size_t total;
+ void *dynamic;
+
+ /* Clear out old cipher contents, if any */
+ tls_clear_cipher ( tls, cipherspec );
+
+ /* Allocate dynamic storage */
+ total = ( pubkey->ctxsize + 2 * cipher->ctxsize + digest->digestsize );
+ dynamic = malloc ( total );
+ if ( ! dynamic ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
+ "context\n", tls, total );
+ return -ENOMEM;
+ }
+ memset ( dynamic, 0, total );
+
+ /* Assign storage */
+ cipherspec->dynamic = dynamic;
+ cipherspec->pubkey_ctx = dynamic; dynamic += pubkey->ctxsize;
+ cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize;
+ cipherspec->cipher_next_ctx = dynamic; dynamic += cipher->ctxsize;
+ cipherspec->mac_secret = dynamic; dynamic += digest->digestsize;
+ assert ( ( cipherspec->dynamic + total ) == dynamic );
+
+ /* Store parameters */
+ cipherspec->pubkey = pubkey;
+ cipherspec->cipher = cipher;
+ cipherspec->digest = digest;
+ cipherspec->key_len = key_len;
+
+ return 0;
+}
+
+/**
+ * Select next cipher suite
+ *
+ * @v tls TLS session
+ * @v cipher_suite Cipher suite specification
+ * @ret rc Return status code
+ */
+static int tls_select_cipher ( struct tls_session *tls,
+ unsigned int cipher_suite ) {
+ struct pubkey_algorithm *pubkey = &pubkey_null;
+ struct cipher_algorithm *cipher = &cipher_null;
+ struct digest_algorithm *digest = &digest_null;
+ unsigned int key_len = 0;
+ int rc;
+
+ switch ( cipher_suite ) {
+ case htons ( TLS_RSA_WITH_AES_128_CBC_SHA ):
+ key_len = ( 128 / 8 );
+ cipher = &aes_cbc_algorithm;
+ digest = &sha1_algorithm;
+ break;
+ case htons ( TLS_RSA_WITH_AES_256_CBC_SHA ):
+ key_len = ( 256 / 8 );
+ cipher = &aes_cbc_algorithm;
+ digest = &sha1_algorithm;
+ break;
+ default:
+ DBGC ( tls, "TLS %p does not support cipher %04x\n",
+ tls, ntohs ( cipher_suite ) );
+ return -ENOTSUP;
+ }
+
+ /* Set ciphers */
+ if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending, pubkey,
+ cipher, digest, key_len ) ) != 0 )
+ return rc;
+ if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending, pubkey,
+ cipher, digest, key_len ) ) != 0 )
+ return rc;
+
+ DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls,
+ pubkey->name, cipher->name, ( key_len * 8 ), digest->name );
+
+ return 0;
+}
+
+/**
+ * Activate next cipher suite
+ *
+ * @v tls TLS session
+ * @v pending Pending cipher specification
+ * @v active Active cipher specification to replace
+ * @ret rc Return status code
+ */
+static int tls_change_cipher ( struct tls_session *tls,
+ struct tls_cipherspec *pending,
+ struct tls_cipherspec *active ) {
+
+ /* Sanity check */
+ if ( /* FIXME (when pubkey is not hard-coded to RSA):
+ * ( pending->pubkey == &pubkey_null ) || */
+ ( pending->cipher == &cipher_null ) ||
+ ( pending->digest == &digest_null ) ) {
+ DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
+ return -ENOTSUP;
+ }
+
+ tls_clear_cipher ( tls, active );
+ memswap ( active, pending, sizeof ( *active ) );
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * Handshake verification
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Add handshake record to verification hash
+ *
+ * @v tls TLS session
+ * @v data Handshake record
+ * @v len Length of handshake record
+ */
+static void tls_add_handshake ( struct tls_session *tls,
+ const void *data, size_t len ) {
+
+ digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len );
+ digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len );
+}
+
+/**
+ * Calculate handshake verification hash
+ *
+ * @v tls TLS session
+ * @v out Output buffer
+ *
+ * Calculates the MD5+SHA1 digest over all handshake messages seen so
+ * far.
+ */
+static void tls_verify_handshake ( struct tls_session *tls, void *out ) {
+ struct digest_algorithm *md5 = &md5_algorithm;
+ struct digest_algorithm *sha1 = &sha1_algorithm;
+ uint8_t md5_ctx[md5->ctxsize];
+ uint8_t sha1_ctx[sha1->ctxsize];
+ void *md5_digest = out;
+ void *sha1_digest = ( out + md5->digestsize );
+
+ memcpy ( md5_ctx, tls->handshake_md5_ctx, sizeof ( md5_ctx ) );
+ memcpy ( sha1_ctx, tls->handshake_sha1_ctx, sizeof ( sha1_ctx ) );
+ digest_final ( md5, md5_ctx, md5_digest );
+ digest_final ( sha1, sha1_ctx, sha1_digest );
+}
+
+/******************************************************************************
+ *
+ * Record handling
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Transmit Handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_send_handshake ( struct tls_session *tls,
+ void *data, size_t len ) {
+
+ /* Add to handshake digest */
+ tls_add_handshake ( tls, data, len );
+
+ /* Send record */
+ return tls_send_plaintext ( tls, TLS_TYPE_HANDSHAKE, data, len );
+}
+
+/**
+ * Transmit Client Hello record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_client_hello ( struct tls_session *tls ) {
+ struct {
+ uint32_t type_length;
+ uint16_t version;
+ uint8_t random[32];
+ uint8_t session_id_len;
+ uint16_t cipher_suite_len;
+ uint16_t cipher_suites[2];
+ uint8_t compression_methods_len;
+ uint8_t compression_methods[1];
+ } __attribute__ (( packed )) hello;
+
+ memset ( &hello, 0, sizeof ( hello ) );
+ hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
+ htonl ( sizeof ( hello ) -
+ sizeof ( hello.type_length ) ) );
+ hello.version = htons ( TLS_VERSION_TLS_1_0 );
+ memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
+ hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
+ hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA );
+ hello.cipher_suites[1] = htons ( TLS_RSA_WITH_AES_256_CBC_SHA );
+ hello.compression_methods_len = sizeof ( hello.compression_methods );
+
+ return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
+}
+
+/**
+ * Transmit Client Key Exchange record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_client_key_exchange ( struct tls_session *tls ) {
+ /* FIXME: Hack alert */
+ RSA_CTX *rsa_ctx;
+ RSA_pub_key_new ( &rsa_ctx, tls->rsa.modulus, tls->rsa.modulus_len,
+ tls->rsa.exponent, tls->rsa.exponent_len );
+ struct {
+ uint32_t type_length;
+ uint16_t encrypted_pre_master_secret_len;
+ uint8_t encrypted_pre_master_secret[rsa_ctx->num_octets];
+ } __attribute__ (( packed )) key_xchg;
+
+ memset ( &key_xchg, 0, sizeof ( key_xchg ) );
+ key_xchg.type_length = ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
+ htonl ( sizeof ( key_xchg ) -
+ sizeof ( key_xchg.type_length ) ) );
+ key_xchg.encrypted_pre_master_secret_len
+ = htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) );
+
+ /* FIXME: Hack alert */
+ DBGC ( tls, "RSA encrypting plaintext, modulus, exponent:\n" );
+ DBGC_HD ( tls, &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ) );
+ DBGC_HD ( tls, tls->rsa.modulus, tls->rsa.modulus_len );
+ DBGC_HD ( tls, tls->rsa.exponent, tls->rsa.exponent_len );
+ RSA_encrypt ( rsa_ctx, ( const uint8_t * ) &tls->pre_master_secret,
+ sizeof ( tls->pre_master_secret ),
+ key_xchg.encrypted_pre_master_secret, 0 );
+ DBGC ( tls, "RSA encrypt done. Ciphertext:\n" );
+ DBGC_HD ( tls, &key_xchg.encrypted_pre_master_secret,
+ sizeof ( key_xchg.encrypted_pre_master_secret ) );
+ RSA_free ( rsa_ctx );
+
+
+ return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) );
+}
+
+/**
+ * Transmit Change Cipher record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_change_cipher ( struct tls_session *tls ) {
+ static const uint8_t change_cipher[1] = { 1 };
+ return tls_send_plaintext ( tls, TLS_TYPE_CHANGE_CIPHER,
+ change_cipher, sizeof ( change_cipher ) );
+}
+
+/**
+ * Transmit Finished record
+ *
+ * @v tls TLS session
+ * @ret rc Return status code
+ */
+static int tls_send_finished ( struct tls_session *tls ) {
+ struct {
+ uint32_t type_length;
+ uint8_t verify_data[12];
+ } __attribute__ (( packed )) finished;
+ uint8_t digest[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
+
+ memset ( &finished, 0, sizeof ( finished ) );
+ finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
+ htonl ( sizeof ( finished ) -
+ sizeof ( finished.type_length ) ) );
+ tls_verify_handshake ( tls, digest );
+ tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
+ finished.verify_data, sizeof ( finished.verify_data ),
+ "client finished", digest, sizeof ( digest ) );
+
+ return tls_send_handshake ( tls, &finished, sizeof ( finished ) );
+}
+
+/**
+ * Receive new Change Cipher record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_change_cipher ( struct tls_session *tls,
+ void *data, size_t len ) {
+ int rc;
+
+ if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) {
+ DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending,
+ &tls->rx_cipherspec ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
+ tls, strerror ( rc ) );
+ return rc;
+ }
+ tls->rx_seq = ~( ( uint64_t ) 0 );
+
+ return 0;
+}
+
+/**
+ * Receive new Alert record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_alert ( struct tls_session *tls, void *data, size_t len ) {
+ struct {
+ uint8_t level;
+ uint8_t description;
+ char next[0];
+ } __attribute__ (( packed )) *alert = data;
+ void *end = alert->next;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Alert\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ switch ( alert->level ) {
+ case TLS_ALERT_WARNING:
+ DBGC ( tls, "TLS %p received warning alert %d\n",
+ tls, alert->description );
+ return 0;
+ case TLS_ALERT_FATAL:
+ DBGC ( tls, "TLS %p received fatal alert %d\n",
+ tls, alert->description );
+ return -EPERM;
+ default:
+ DBGC ( tls, "TLS %p received unknown alert level %d"
+ "(alert %d)\n", tls, alert->level, alert->description );
+ return -EIO;
+ }
+}
+
+/**
+ * Receive new Server Hello handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_server_hello ( struct tls_session *tls,
+ void *data, size_t len ) {
+ struct {
+ uint16_t version;
+ uint8_t random[32];
+ uint8_t session_id_len;
+ char next[0];
+ } __attribute__ (( packed )) *hello_a = data;
+ struct {
+ uint8_t session_id[hello_a->session_id_len];
+ uint16_t cipher_suite;
+ uint8_t compression_method;
+ char next[0];
+ } __attribute__ (( packed )) *hello_b = ( void * ) &hello_a->next;
+ void *end = hello_b->next;
+ int rc;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Server Hello\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Check protocol version */
+ if ( ntohs ( hello_a->version ) < TLS_VERSION_TLS_1_0 ) {
+ DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
+ tls, ( ntohs ( hello_a->version ) >> 8 ),
+ ( ntohs ( hello_a->version ) & 0xff ) );
+ return -ENOTSUP;
+ }
+
+ /* Copy out server random bytes */
+ memcpy ( &tls->server_random, &hello_a->random,
+ sizeof ( tls->server_random ) );
+
+ /* Select cipher suite */
+ if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
+ return rc;
+
+ /* Generate secrets */
+ tls_generate_master_secret ( tls );
+ if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Receive new Certificate handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_certificate ( struct tls_session *tls,
+ void *data, size_t len ) {
+ struct {
+ uint8_t length[3];
+ uint8_t certificates[0];
+ } __attribute__ (( packed )) *certificate = data;
+ struct {
+ uint8_t length[3];
+ uint8_t certificate[0];
+ } __attribute__ (( packed )) *element =
+ ( ( void * ) certificate->certificates );
+ size_t elements_len = tls_uint24 ( certificate->length );
+ void *end = ( certificate->certificates + elements_len );
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Server Certificate\n",
+ tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Traverse certificate chain */
+ do {
+ cursor.data = element->certificate;
+ cursor.len = tls_uint24 ( element->length );
+ if ( ( cursor.data + cursor.len ) > end ) {
+ DBGC ( tls, "TLS %p received corrupt Server "
+ "Certificate\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ // HACK
+ if ( ( rc = x509_rsa_public_key ( &cursor,
+ &tls->rsa ) ) != 0 ) {
+ DBGC ( tls, "TLS %p cannot determine RSA public key: "
+ "%s\n", tls, strerror ( rc ) );
+ return rc;
+ }
+ return 0;
+
+ element = ( cursor.data + cursor.len );
+ } while ( element != end );
+
+ return -EINVAL;
+}
+
+/**
+ * Receive new Server Hello Done handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_server_hello_done ( struct tls_session *tls,
+ void *data, size_t len ) {
+ struct {
+ char next[0];
+ } __attribute__ (( packed )) *hello_done = data;
+ void *end = hello_done->next;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
+ tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ /* Check that we are ready to send the Client Key Exchange */
+ if ( tls->tx_state != TLS_TX_NONE ) {
+ DBGC ( tls, "TLS %p received Server Hello Done while in "
+ "TX state %d\n", tls, tls->tx_state );
+ return -EIO;
+ }
+
+ /* Start sending the Client Key Exchange */
+ tls->tx_state = TLS_TX_CLIENT_KEY_EXCHANGE;
+
+ return 0;
+}
+
+/**
+ * Receive new Finished handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext handshake record
+ * @v len Length of plaintext handshake record
+ * @ret rc Return status code
+ */
+static int tls_new_finished ( struct tls_session *tls,
+ void *data, size_t len ) {
+
+ /* FIXME: Handle this properly */
+ tls->tx_state = TLS_TX_DATA;
+ ( void ) data;
+ ( void ) len;
+ return 0;
+}
+
+/**
+ * Receive new Handshake record
+ *
+ * @v tls TLS session
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_handshake ( struct tls_session *tls,
+ void *data, size_t len ) {
+ struct {
+ uint8_t type;
+ uint8_t length[3];
+ uint8_t payload[0];
+ } __attribute__ (( packed )) *handshake = data;
+ void *payload = &handshake->payload;
+ size_t payload_len = tls_uint24 ( handshake->length );
+ void *end = ( payload + payload_len );
+ int rc;
+
+ /* Sanity check */
+ if ( end != ( data + len ) ) {
+ DBGC ( tls, "TLS %p received overlength Handshake\n", tls );
+ DBGC_HD ( tls, data, len );
+ return -EINVAL;
+ }
+
+ switch ( handshake->type ) {
+ case TLS_SERVER_HELLO:
+ rc = tls_new_server_hello ( tls, payload, payload_len );
+ break;
+ case TLS_CERTIFICATE:
+ rc = tls_new_certificate ( tls, payload, payload_len );
+ break;
+ case TLS_SERVER_HELLO_DONE:
+ rc = tls_new_server_hello_done ( tls, payload, payload_len );
+ break;
+ case TLS_FINISHED:
+ rc = tls_new_finished ( tls, payload, payload_len );
+ break;
+ default:
+ DBGC ( tls, "TLS %p ignoring handshake type %d\n",
+ tls, handshake->type );
+ rc = 0;
+ break;
+ }
+
+ /* Add to handshake digest (except for Hello Requests, which
+ * are explicitly excluded).
+ */
+ if ( handshake->type != TLS_HELLO_REQUEST )
+ tls_add_handshake ( tls, data, len );
+
+ return rc;
+}
+
+/**
+ * Receive new record
+ *
+ * @v tls TLS session
+ * @v type Record type
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_new_record ( struct tls_session *tls,
+ unsigned int type, void *data, size_t len ) {
+
+ switch ( type ) {
+ case TLS_TYPE_CHANGE_CIPHER:
+ return tls_new_change_cipher ( tls, data, len );
+ case TLS_TYPE_ALERT:
+ return tls_new_alert ( tls, data, len );
+ case TLS_TYPE_HANDSHAKE:
+ return tls_new_handshake ( tls, data, len );
+ case TLS_TYPE_DATA:
+ return xfer_deliver_raw ( &tls->plainstream.xfer, data, len );
+ default:
+ /* RFC4346 says that we should just ignore unknown
+ * record types.
+ */
+ DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
+ return 0;
+ }
+}
+
+/******************************************************************************
+ *
+ * Record encryption/decryption
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Calculate HMAC
+ *
+ * @v tls TLS session
+ * @v cipherspec Cipher specification
+ * @v seq Sequence number
+ * @v tlshdr TLS header
+ * @v data Data
+ * @v len Length of data
+ * @v mac HMAC to fill in
+ */
+static void tls_hmac ( struct tls_session *tls __unused,
+ struct tls_cipherspec *cipherspec,
+ uint64_t seq, struct tls_header *tlshdr,
+ const void *data, size_t len, void *hmac ) {
+ struct digest_algorithm *digest = cipherspec->digest;
+ uint8_t digest_ctx[digest->ctxsize];
+
+ hmac_init ( digest, digest_ctx, cipherspec->mac_secret,
+ &digest->digestsize );
+ seq = cpu_to_be64 ( seq );
+ hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) );
+ hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) );
+ hmac_update ( digest, digest_ctx, data, len );
+ hmac_final ( digest, digest_ctx, cipherspec->mac_secret,
+ &digest->digestsize, hmac );
+}
+
+/**
+ * Allocate and assemble stream-ciphered record from data and MAC portions
+ *
+ * @v tls TLS session
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret plaintext_len Length of plaintext record
+ * @ret plaintext Allocated plaintext record
+ */
+static void * __malloc tls_assemble_stream ( struct tls_session *tls,
+ const void *data, size_t len,
+ void *digest, size_t *plaintext_len ) {
+ size_t mac_len = tls->tx_cipherspec.digest->digestsize;
+ void *plaintext;
+ void *content;
+ void *mac;
+
+ /* Calculate stream-ciphered struct length */
+ *plaintext_len = ( len + mac_len );
+
+ /* Allocate stream-ciphered struct */
+ plaintext = malloc ( *plaintext_len );
+ if ( ! plaintext )
+ return NULL;
+ content = plaintext;
+ mac = ( content + len );
+
+ /* Fill in stream-ciphered struct */
+ memcpy ( content, data, len );
+ memcpy ( mac, digest, mac_len );
+
+ return plaintext;
+}
+
+/**
+ * Allocate and assemble block-ciphered record from data and MAC portions
+ *
+ * @v tls TLS session
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret plaintext_len Length of plaintext record
+ * @ret plaintext Allocated plaintext record
+ */
+static void * tls_assemble_block ( struct tls_session *tls,
+ const void *data, size_t len,
+ void *digest, size_t *plaintext_len ) {
+ size_t blocksize = tls->tx_cipherspec.cipher->blocksize;
+ size_t iv_len = blocksize;
+ size_t mac_len = tls->tx_cipherspec.digest->digestsize;
+ size_t padding_len;
+ void *plaintext;
+ void *iv;
+ void *content;
+ void *mac;
+ void *padding;
+
+ /* FIXME: TLSv1.1 has an explicit IV */
+ iv_len = 0;
+
+ /* Calculate block-ciphered struct length */
+ padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
+ *plaintext_len = ( iv_len + len + mac_len + padding_len + 1 );
+
+ /* Allocate block-ciphered struct */
+ plaintext = malloc ( *plaintext_len );
+ if ( ! plaintext )
+ return NULL;
+ iv = plaintext;
+ content = ( iv + iv_len );
+ mac = ( content + len );
+ padding = ( mac + mac_len );
+
+ /* Fill in block-ciphered struct */
+ memset ( iv, 0, iv_len );
+ memcpy ( content, data, len );
+ memcpy ( mac, digest, mac_len );
+ memset ( padding, padding_len, ( padding_len + 1 ) );
+
+ return plaintext;
+}
+
+/**
+ * Send plaintext record
+ *
+ * @v tls TLS session
+ * @v type Record type
+ * @v data Plaintext record
+ * @v len Length of plaintext record
+ * @ret rc Return status code
+ */
+static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
+ const void *data, size_t len ) {
+ struct tls_header plaintext_tlshdr;
+ struct tls_header *tlshdr;
+ struct tls_cipherspec *cipherspec = &tls->tx_cipherspec;
+ void *plaintext = NULL;
+ size_t plaintext_len;
+ struct io_buffer *ciphertext = NULL;
+ size_t ciphertext_len;
+ size_t mac_len = cipherspec->digest->digestsize;
+ uint8_t mac[mac_len];
+ int rc;
+
+ /* Construct header */
+ plaintext_tlshdr.type = type;
+ plaintext_tlshdr.version = htons ( TLS_VERSION_TLS_1_0 );
+ plaintext_tlshdr.length = htons ( len );
+
+ /* Calculate MAC */
+ tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr,
+ data, len, mac );
+
+ /* Allocate and assemble plaintext struct */
+ if ( is_stream_cipher ( cipherspec->cipher ) ) {
+ plaintext = tls_assemble_stream ( tls, data, len, mac,
+ &plaintext_len );
+ } else {
+ plaintext = tls_assemble_block ( tls, data, len, mac,
+ &plaintext_len );
+ }
+ if ( ! plaintext ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for "
+ "plaintext\n", tls, plaintext_len );
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ DBGC2 ( tls, "Sending plaintext data:\n" );
+ DBGC2_HD ( tls, plaintext, plaintext_len );
+
+ /* Allocate ciphertext */
+ ciphertext_len = ( sizeof ( *tlshdr ) + plaintext_len );
+ ciphertext = xfer_alloc_iob ( &tls->cipherstream.xfer,
+ ciphertext_len );
+ if ( ! ciphertext ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for "
+ "ciphertext\n", tls, ciphertext_len );
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ /* Assemble ciphertext */
+ tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) );
+ tlshdr->type = type;
+ tlshdr->version = htons ( TLS_VERSION_TLS_1_0 );
+ tlshdr->length = htons ( plaintext_len );
+ memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx,
+ cipherspec->cipher->ctxsize );
+ cipher_encrypt ( cipherspec->cipher, cipherspec->cipher_next_ctx,
+ plaintext, iob_put ( ciphertext, plaintext_len ),
+ plaintext_len );
+
+ /* Free plaintext as soon as possible to conserve memory */
+ free ( plaintext );
+ plaintext = NULL;
+
+ /* Send ciphertext */
+ rc = xfer_deliver_iob ( &tls->cipherstream.xfer, ciphertext );
+ ciphertext = NULL;
+ if ( rc != 0 ) {
+ DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
+ tls, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Update TX state machine to next record */
+ tls->tx_seq += 1;
+ memcpy ( tls->tx_cipherspec.cipher_ctx,
+ tls->tx_cipherspec.cipher_next_ctx,
+ tls->tx_cipherspec.cipher->ctxsize );
+
+ done:
+ free ( plaintext );
+ free_iob ( ciphertext );
+ return rc;
+}
+
+/**
+ * Split stream-ciphered record into data and MAC portions
+ *
+ * @v tls TLS session
+ * @v plaintext Plaintext record
+ * @v plaintext_len Length of record
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret rc Return status code
+ */
+static int tls_split_stream ( struct tls_session *tls,
+ void *plaintext, size_t plaintext_len,
+ void **data, size_t *len, void **digest ) {
+ void *content;
+ size_t content_len;
+ void *mac;
+ size_t mac_len;
+
+ /* Decompose stream-ciphered data */
+ mac_len = tls->rx_cipherspec.digest->digestsize;
+ if ( plaintext_len < mac_len ) {
+ DBGC ( tls, "TLS %p received underlength record\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ content_len = ( plaintext_len - mac_len );
+ content = plaintext;
+ mac = ( content + content_len );
+
+ /* Fill in return values */
+ *data = content;
+ *len = content_len;
+ *digest = mac;
+
+ return 0;
+}
+
+/**
+ * Split block-ciphered record into data and MAC portions
+ *
+ * @v tls TLS session
+ * @v plaintext Plaintext record
+ * @v plaintext_len Length of record
+ * @ret data Data
+ * @ret len Length of data
+ * @ret digest MAC digest
+ * @ret rc Return status code
+ */
+static int tls_split_block ( struct tls_session *tls,
+ void *plaintext, size_t plaintext_len,
+ void **data, size_t *len,
+ void **digest ) {
+ void *iv;
+ size_t iv_len;
+ void *content;
+ size_t content_len;
+ void *mac;
+ size_t mac_len;
+ void *padding;
+ size_t padding_len;
+ unsigned int i;
+
+ /* Decompose block-ciphered data */
+ if ( plaintext_len < 1 ) {
+ DBGC ( tls, "TLS %p received underlength record\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ iv_len = tls->rx_cipherspec.cipher->blocksize;
+
+ /* FIXME: TLSv1.1 uses an explicit IV */
+ iv_len = 0;
+
+ mac_len = tls->rx_cipherspec.digest->digestsize;
+ padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
+ if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
+ DBGC ( tls, "TLS %p received underlength record\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 );
+ iv = plaintext;
+ content = ( iv + iv_len );
+ mac = ( content + content_len );
+ padding = ( mac + mac_len );
+
+ /* Verify padding bytes */
+ for ( i = 0 ; i < padding_len ; i++ ) {
+ if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) {
+ DBGC ( tls, "TLS %p received bad padding\n", tls );
+ DBGC_HD ( tls, plaintext, plaintext_len );
+ return -EINVAL;
+ }
+ }
+
+ /* Fill in return values */
+ *data = content;
+ *len = content_len;
+ *digest = mac;
+
+ return 0;
+}
+
+/**
+ * Receive new ciphertext record
+ *
+ * @v tls TLS session
+ * @v tlshdr Record header
+ * @v ciphertext Ciphertext record
+ * @ret rc Return status code
+ */
+static int tls_new_ciphertext ( struct tls_session *tls,
+ struct tls_header *tlshdr, void *ciphertext ) {
+ struct tls_header plaintext_tlshdr;
+ struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
+ size_t record_len = ntohs ( tlshdr->length );
+ void *plaintext = NULL;
+ void *data;
+ size_t len;
+ void *mac;
+ size_t mac_len = cipherspec->digest->digestsize;
+ uint8_t verify_mac[mac_len];
+ int rc;
+
+ /* Allocate buffer for plaintext */
+ plaintext = malloc ( record_len );
+ if ( ! plaintext ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes for "
+ "decryption buffer\n", tls, record_len );
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ /* Decrypt the record */
+ cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx,
+ ciphertext, plaintext, record_len );
+
+ /* Split record into content and MAC */
+ if ( is_stream_cipher ( cipherspec->cipher ) ) {
+ if ( ( rc = tls_split_stream ( tls, plaintext, record_len,
+ &data, &len, &mac ) ) != 0 )
+ goto done;
+ } else {
+ if ( ( rc = tls_split_block ( tls, plaintext, record_len,
+ &data, &len, &mac ) ) != 0 )
+ goto done;
+ }
+
+ /* Verify MAC */
+ plaintext_tlshdr.type = tlshdr->type;
+ plaintext_tlshdr.version = tlshdr->version;
+ plaintext_tlshdr.length = htons ( len );
+ tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr,
+ data, len, verify_mac);
+ if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) {
+ DBGC ( tls, "TLS %p failed MAC verification\n", tls );
+ DBGC_HD ( tls, plaintext, record_len );
+ goto done;
+ }
+
+ DBGC2 ( tls, "Received plaintext data:\n" );
+ DBGC2_HD ( tls, data, len );
+
+ /* Process plaintext record */
+ if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 )
+ goto done;
+
+ rc = 0;
+ done:
+ free ( plaintext );
+ return rc;
+}
+
+/******************************************************************************
+ *
+ * Plaintext stream operations
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Close interface
+ *
+ * @v xfer Plainstream data transfer interface
+ * @v rc Reason for close
+ */
+static void tls_plainstream_close ( struct xfer_interface *xfer, int rc ) {
+ struct tls_session *tls =
+ container_of ( xfer, struct tls_session, plainstream.xfer );
+
+ tls_close ( tls, rc );
+}
+
+/**
+ * Check flow control window
+ *
+ * @v xfer Plainstream data transfer interface
+ * @ret len Length of window
+ */
+static size_t tls_plainstream_window ( struct xfer_interface *xfer ) {
+ struct tls_session *tls =
+ container_of ( xfer, struct tls_session, plainstream.xfer );
+
+ /* Block window unless we are ready to accept data */
+ if ( tls->tx_state != TLS_TX_DATA )
+ return 0;
+
+ return filter_window ( xfer );
+}
+
+/**
+ * Deliver datagram as raw data
+ *
+ * @v xfer Plainstream data transfer interface
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int tls_plainstream_deliver_raw ( struct xfer_interface *xfer,
+ const void *data, size_t len ) {
+ struct tls_session *tls =
+ container_of ( xfer, struct tls_session, plainstream.xfer );
+
+ /* Refuse unless we are ready to accept data */
+ if ( tls->tx_state != TLS_TX_DATA )
+ return -ENOTCONN;
+
+ return tls_send_plaintext ( tls, TLS_TYPE_DATA, data, len );
+}
+
+/** TLS plaintext stream operations */
+static struct xfer_interface_operations tls_plainstream_operations = {
+ .close = tls_plainstream_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = tls_plainstream_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = tls_plainstream_deliver_raw,
+};
+
+/******************************************************************************
+ *
+ * Ciphertext stream operations
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Close interface
+ *
+ * @v xfer Plainstream data transfer interface
+ * @v rc Reason for close
+ */
+static void tls_cipherstream_close ( struct xfer_interface *xfer, int rc ) {
+ struct tls_session *tls =
+ container_of ( xfer, struct tls_session, cipherstream.xfer );
+
+ tls_close ( tls, rc );
+}
+
+/**
+ * Handle received TLS header
+ *
+ * @v tls TLS session
+ * @ret rc Returned status code
+ */
+static int tls_newdata_process_header ( struct tls_session *tls ) {
+ size_t data_len = ntohs ( tls->rx_header.length );
+
+ /* Allocate data buffer now that we know the length */
+ assert ( tls->rx_data == NULL );
+ tls->rx_data = malloc ( data_len );
+ if ( ! tls->rx_data ) {
+ DBGC ( tls, "TLS %p could not allocate %zd bytes "
+ "for receive buffer\n", tls, data_len );
+ return -ENOMEM;
+ }
+
+ /* Move to data state */
+ tls->rx_state = TLS_RX_DATA;
+
+ return 0;
+}
+
+/**
+ * Handle received TLS data payload
+ *
+ * @v tls TLS session
+ * @ret rc Returned status code
+ */
+static int tls_newdata_process_data ( struct tls_session *tls ) {
+ int rc;
+
+ /* Process record */
+ if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
+ tls->rx_data ) ) != 0 )
+ return rc;
+
+ /* Increment RX sequence number */
+ tls->rx_seq += 1;
+
+ /* Free data buffer */
+ free ( tls->rx_data );
+ tls->rx_data = NULL;
+
+ /* Return to header state */
+ tls->rx_state = TLS_RX_HEADER;
+
+ return 0;
+}
+
+/**
+ * Receive new ciphertext
+ *
+ * @v app Stream application
+ * @v data Data received
+ * @v len Length of received data
+ * @ret rc Return status code
+ */
+static int tls_cipherstream_deliver_raw ( struct xfer_interface *xfer,
+ const void *data, size_t len ) {
+ struct tls_session *tls =
+ container_of ( xfer, struct tls_session, cipherstream.xfer );
+ size_t frag_len;
+ void *buf;
+ size_t buf_len;
+ int ( * process ) ( struct tls_session *tls );
+ int rc;
+
+ while ( len ) {
+ /* Select buffer according to current state */
+ switch ( tls->rx_state ) {
+ case TLS_RX_HEADER:
+ buf = &tls->rx_header;
+ buf_len = sizeof ( tls->rx_header );
+ process = tls_newdata_process_header;
+ break;
+ case TLS_RX_DATA:
+ buf = tls->rx_data;
+ buf_len = ntohs ( tls->rx_header.length );
+ process = tls_newdata_process_data;
+ break;
+ default:
+ assert ( 0 );
+ return -EINVAL;
+ }
+
+ /* Copy data portion to buffer */
+ frag_len = ( buf_len - tls->rx_rcvd );
+ if ( frag_len > len )
+ frag_len = len;
+ memcpy ( ( buf + tls->rx_rcvd ), data, frag_len );
+ tls->rx_rcvd += frag_len;
+ data += frag_len;
+ len -= frag_len;
+
+ /* Process data if buffer is now full */
+ if ( tls->rx_rcvd == buf_len ) {
+ if ( ( rc = process ( tls ) ) != 0 ) {
+ tls_close ( tls, rc );
+ return rc;
+ }
+ tls->rx_rcvd = 0;
+ }
+ }
+
+ return 0;
+}
+
+/** TLS ciphertext stream operations */
+static struct xfer_interface_operations tls_cipherstream_operations = {
+ .close = tls_cipherstream_close,
+ .vredirect = xfer_vreopen,
+ .window = filter_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = tls_cipherstream_deliver_raw,
+};
+
+/******************************************************************************
+ *
+ * Controlling process
+ *
+ ******************************************************************************
+ */
+
+/**
+ * TLS TX state machine
+ *
+ * @v process TLS process
+ */
+static void tls_step ( struct process *process ) {
+ struct tls_session *tls =
+ container_of ( process, struct tls_session, process );
+ int rc;
+
+ /* Wait for cipherstream to become ready */
+ if ( ! xfer_window ( &tls->cipherstream.xfer ) )
+ return;
+
+ switch ( tls->tx_state ) {
+ case TLS_TX_NONE:
+ /* Nothing to do */
+ break;
+ case TLS_TX_CLIENT_HELLO:
+ /* Send Client Hello */
+ if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_state = TLS_TX_NONE;
+ break;
+ case TLS_TX_CLIENT_KEY_EXCHANGE:
+ /* Send Client Key Exchange */
+ if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could send Client Key Exchange: "
+ "%s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_state = TLS_TX_CHANGE_CIPHER;
+ break;
+ case TLS_TX_CHANGE_CIPHER:
+ /* Send Change Cipher, and then change the cipher in use */
+ if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Change Cipher: "
+ "%s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ if ( ( rc = tls_change_cipher ( tls,
+ &tls->tx_cipherspec_pending,
+ &tls->tx_cipherspec )) != 0 ){
+ DBGC ( tls, "TLS %p could not activate TX cipher: "
+ "%s\n", tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_seq = 0;
+ tls->tx_state = TLS_TX_FINISHED;
+ break;
+ case TLS_TX_FINISHED:
+ /* Send Finished */
+ if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not send Finished: %s\n",
+ tls, strerror ( rc ) );
+ goto err;
+ }
+ tls->tx_state = TLS_TX_NONE;
+ break;
+ case TLS_TX_DATA:
+ /* Nothing to do */
+ break;
+ default:
+ assert ( 0 );
+ }
+
+ return;
+
+ err:
+ tls_close ( tls, rc );
+}
+
+/******************************************************************************
+ *
+ * Instantiator
+ *
+ ******************************************************************************
+ */
+
+int add_tls ( struct xfer_interface *xfer, struct xfer_interface **next ) {
+ struct tls_session *tls;
+
+ /* Allocate and initialise TLS structure */
+ tls = malloc ( sizeof ( *tls ) );
+ if ( ! tls )
+ return -ENOMEM;
+ memset ( tls, 0, sizeof ( *tls ) );
+ tls->refcnt.free = free_tls;
+ filter_init ( &tls->plainstream, &tls_plainstream_operations,
+ &tls->cipherstream, &tls_cipherstream_operations,
+ &tls->refcnt );
+ tls_clear_cipher ( tls, &tls->tx_cipherspec );
+ tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec );
+ tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
+ tls->client_random.gmt_unix_time = 0;
+ tls_generate_random ( &tls->client_random.random,
+ ( sizeof ( tls->client_random.random ) ) );
+ tls->pre_master_secret.version = htons ( TLS_VERSION_TLS_1_0 );
+ tls_generate_random ( &tls->pre_master_secret.random,
+ ( sizeof ( tls->pre_master_secret.random ) ) );
+ digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
+ digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
+ tls->tx_state = TLS_TX_CLIENT_HELLO;
+ process_init ( &tls->process, tls_step, &tls->refcnt );
+
+ /* Attach to parent interface, mortalise self, and return */
+ xfer_plug_plug ( &tls->plainstream.xfer, xfer );
+ *next = &tls->cipherstream.xfer;
+ ref_put ( &tls->refcnt );
+ return 0;
+}
+
diff --git a/debian/grub-extras/disabled/gpxe/src/net/udp.c b/debian/grub-extras/disabled/gpxe/src/net/udp.c
new file mode 100644
index 0000000..771655e
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/udp.c
@@ -0,0 +1,463 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/uri.h>
+#include <gpxe/udp.h>
+
+/** @file
+ *
+ * UDP protocol
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * A UDP connection
+ *
+ */
+struct udp_connection {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** List of UDP connections */
+ struct list_head list;
+
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+
+ /** Local socket address */
+ struct sockaddr_tcpip local;
+ /** Remote socket address */
+ struct sockaddr_tcpip peer;
+};
+
+/**
+ * List of registered UDP connections
+ */
+static LIST_HEAD ( udp_conns );
+
+/* Forward declatations */
+static struct xfer_interface_operations udp_xfer_operations;
+struct tcpip_protocol udp_protocol;
+
+/**
+ * Bind UDP connection to local port
+ *
+ * @v udp UDP connection
+ * @ret rc Return status code
+ *
+ * Opens the UDP connection and binds to the specified local port. If
+ * no local port is specified, the first available port will be used.
+ */
+static int udp_bind ( struct udp_connection *udp ) {
+ struct udp_connection *existing;
+ static uint16_t try_port = 1023;
+
+ /* If no port specified, find the first available port */
+ if ( ! udp->local.st_port ) {
+ while ( try_port ) {
+ try_port++;
+ if ( try_port < 1024 )
+ continue;
+ udp->local.st_port = htons ( try_port );
+ if ( udp_bind ( udp ) == 0 )
+ return 0;
+ }
+ return -EADDRINUSE;
+ }
+
+ /* Attempt bind to local port */
+ list_for_each_entry ( existing, &udp_conns, list ) {
+ if ( existing->local.st_port == udp->local.st_port ) {
+ DBGC ( udp, "UDP %p could not bind: port %d in use\n",
+ udp, ntohs ( udp->local.st_port ) );
+ return -EADDRINUSE;
+ }
+ }
+
+ /* Add to UDP connection list */
+ DBGC ( udp, "UDP %p bound to port %d\n",
+ udp, ntohs ( udp->local.st_port ) );
+
+ return 0;
+}
+
+/**
+ * Open a UDP connection
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address, or NULL
+ * @v local Local socket address, or NULL
+ * @v promisc Socket is promiscuous
+ * @ret rc Return status code
+ */
+static int udp_open_common ( struct xfer_interface *xfer,
+ struct sockaddr *peer, struct sockaddr *local,
+ int promisc ) {
+ struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
+ struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
+ struct udp_connection *udp;
+ int rc;
+
+ /* Allocate and initialise structure */
+ udp = zalloc ( sizeof ( *udp ) );
+ if ( ! udp )
+ return -ENOMEM;
+ DBGC ( udp, "UDP %p allocated\n", udp );
+ xfer_init ( &udp->xfer, &udp_xfer_operations, &udp->refcnt );
+ if ( st_peer )
+ memcpy ( &udp->peer, st_peer, sizeof ( udp->peer ) );
+ if ( st_local )
+ memcpy ( &udp->local, st_local, sizeof ( udp->local ) );
+
+ /* Bind to local port */
+ if ( ! promisc ) {
+ if ( ( rc = udp_bind ( udp ) ) != 0 )
+ goto err;
+ }
+
+ /* Attach parent interface, transfer reference to connection
+ * list and return
+ */
+ xfer_plug_plug ( &udp->xfer, xfer );
+ list_add ( &udp->list, &udp_conns );
+ return 0;
+
+ err:
+ ref_put ( &udp->refcnt );
+ return rc;
+}
+
+/**
+ * Open a UDP connection
+ *
+ * @v xfer Data transfer interface
+ * @v peer Peer socket address
+ * @v local Local socket address, or NULL
+ * @ret rc Return status code
+ */
+int udp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
+ struct sockaddr *local ) {
+ return udp_open_common ( xfer, peer, local, 0 );
+}
+
+/**
+ * Open a promiscuous UDP connection
+ *
+ * @v xfer Data transfer interface
+ * @ret rc Return status code
+ *
+ * Promiscuous UDP connections are required in order to support the
+ * PXE API.
+ */
+int udp_open_promisc ( struct xfer_interface *xfer ) {
+ return udp_open_common ( xfer, NULL, NULL, 1 );
+}
+
+/**
+ * Close a UDP connection
+ *
+ * @v udp UDP connection
+ * @v rc Reason for close
+ */
+static void udp_close ( struct udp_connection *udp, int rc ) {
+
+ /* Close data transfer interface */
+ xfer_nullify ( &udp->xfer );
+ xfer_close ( &udp->xfer, rc );
+
+ /* Remove from list of connections and drop list's reference */
+ list_del ( &udp->list );
+ ref_put ( &udp->refcnt );
+
+ DBGC ( udp, "UDP %p closed\n", udp );
+}
+
+/**
+ * Transmit data via a UDP connection to a specified address
+ *
+ * @v udp UDP connection
+ * @v iobuf I/O buffer
+ * @v src Source address, or NULL to use default
+ * @v dest Destination address, or NULL to use default
+ * @v netdev Network device, or NULL to use default
+ * @ret rc Return status code
+ */
+static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
+ struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
+ struct net_device *netdev ) {
+ struct udp_header *udphdr;
+ size_t len;
+ int rc;
+
+ /* Check we can accommodate the header */
+ if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
+ free_iob ( iobuf );
+ return rc;
+ }
+
+ /* Fill in default values if not explicitly provided */
+ if ( ! src )
+ src = &udp->local;
+ if ( ! dest )
+ dest = &udp->peer;
+
+ /* Add the UDP header */
+ udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
+ len = iob_len ( iobuf );
+ udphdr->dest = dest->st_port;
+ udphdr->src = src->st_port;
+ udphdr->len = htons ( len );
+ udphdr->chksum = 0;
+ udphdr->chksum = tcpip_chksum ( udphdr, len );
+
+ /* Dump debugging information */
+ DBGC ( udp, "UDP %p TX %d->%d len %d\n", udp,
+ ntohs ( udphdr->src ), ntohs ( udphdr->dest ),
+ ntohs ( udphdr->len ) );
+
+ /* Send it to the next layer for processing */
+ if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
+ &udphdr->chksum ) ) != 0 ) {
+ DBGC ( udp, "UDP %p could not transmit packet: %s\n",
+ udp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Identify UDP connection by local address
+ *
+ * @v local Local address
+ * @ret udp UDP connection, or NULL
+ */
+static struct udp_connection * udp_demux ( struct sockaddr_tcpip *local ) {
+ static const struct sockaddr_tcpip empty_sockaddr = { .pad = { 0, } };
+ struct udp_connection *udp;
+
+ list_for_each_entry ( udp, &udp_conns, list ) {
+ if ( ( ( udp->local.st_family == local->st_family ) ||
+ ( udp->local.st_family == 0 ) ) &&
+ ( ( udp->local.st_port == local->st_port ) ||
+ ( udp->local.st_port == 0 ) ) &&
+ ( ( memcmp ( udp->local.pad, local->pad,
+ sizeof ( udp->local.pad ) ) == 0 ) ||
+ ( memcmp ( udp->local.pad, empty_sockaddr.pad,
+ sizeof ( udp->local.pad ) ) == 0 ) ) ) {
+ return udp;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Process a received packet
+ *
+ * @v iobuf I/O buffer
+ * @v st_src Partially-filled source address
+ * @v st_dest Partially-filled destination address
+ * @v pshdr_csum Pseudo-header checksum
+ * @ret rc Return status code
+ */
+static int udp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
+ struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
+ struct udp_header *udphdr = iobuf->data;
+ struct udp_connection *udp;
+ struct xfer_metadata meta;
+ size_t ulen;
+ unsigned int csum;
+ int rc = 0;
+
+ /* Sanity check packet */
+ if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
+ DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
+ iob_len ( iobuf ), sizeof ( *udphdr ) );
+
+ rc = -EINVAL;
+ goto done;
+ }
+ ulen = ntohs ( udphdr->len );
+ if ( ulen < sizeof ( *udphdr ) ) {
+ DBG ( "UDP length too short at %zd bytes "
+ "(header is %zd bytes)\n", ulen, sizeof ( *udphdr ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( ulen > iob_len ( iobuf ) ) {
+ DBG ( "UDP length too long at %zd bytes (packet is %zd "
+ "bytes)\n", ulen, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( udphdr->chksum ) {
+ csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data, ulen );
+ if ( csum != 0 ) {
+ DBG ( "UDP checksum incorrect (is %04x including "
+ "checksum field, should be 0000)\n", csum );
+ rc = -EINVAL;
+ goto done;
+ }
+ }
+
+ /* Parse parameters from header and strip header */
+ st_src->st_port = udphdr->src;
+ st_dest->st_port = udphdr->dest;
+ udp = udp_demux ( st_dest );
+ iob_unput ( iobuf, ( iob_len ( iobuf ) - ulen ) );
+ iob_pull ( iobuf, sizeof ( *udphdr ) );
+
+ /* Dump debugging information */
+ DBGC ( udp, "UDP %p RX %d<-%d len %zd\n", udp,
+ ntohs ( udphdr->dest ), ntohs ( udphdr->src ), ulen );
+
+ /* Ignore if no matching connection found */
+ if ( ! udp ) {
+ DBG ( "No UDP connection listening on port %d\n",
+ ntohs ( udphdr->dest ) );
+ rc = -ENOTCONN;
+ goto done;
+ }
+
+ /* Pass data to application */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.src = ( struct sockaddr * ) st_src;
+ meta.dest = ( struct sockaddr * ) st_dest;
+ rc = xfer_deliver_iob_meta ( &udp->xfer, iob_disown ( iobuf ), &meta );
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+struct tcpip_protocol udp_protocol __tcpip_protocol = {
+ .name = "UDP",
+ .rx = udp_rx,
+ .tcpip_proto = IP_UDP,
+};
+
+/***************************************************************************
+ *
+ * Data transfer interface
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Close interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void udp_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct udp_connection *udp =
+ container_of ( xfer, struct udp_connection, xfer );
+
+ /* Close connection */
+ udp_close ( udp, rc );
+}
+
+/**
+ * Allocate I/O buffer for UDP
+ *
+ * @v xfer Data transfer interface
+ * @v len Payload size
+ * @ret iobuf I/O buffer, or NULL
+ */
+static struct io_buffer * udp_alloc_iob ( struct xfer_interface *xfer,
+ size_t len ) {
+ struct udp_connection *udp =
+ container_of ( xfer, struct udp_connection, xfer );
+ struct io_buffer *iobuf;
+
+ iobuf = alloc_iob ( UDP_MAX_HLEN + len );
+ if ( ! iobuf ) {
+ DBGC ( udp, "UDP %p cannot allocate buffer of length %zd\n",
+ udp, len );
+ return NULL;
+ }
+ iob_reserve ( iobuf, UDP_MAX_HLEN );
+ return iobuf;
+}
+
+/**
+ * Deliver datagram as I/O buffer
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf Datagram I/O buffer
+ * @v meta Data transfer metadata
+ * @ret rc Return status code
+ */
+static int udp_xfer_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct udp_connection *udp =
+ container_of ( xfer, struct udp_connection, xfer );
+
+ /* Transmit data, if possible */
+ udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ),
+ ( ( struct sockaddr_tcpip * ) meta->dest ), meta->netdev );
+
+ return 0;
+}
+
+/** UDP data transfer interface operations */
+static struct xfer_interface_operations udp_xfer_operations = {
+ .close = udp_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = unlimited_xfer_window,
+ .alloc_iob = udp_alloc_iob,
+ .deliver_iob = udp_xfer_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/***************************************************************************
+ *
+ * Openers
+ *
+ ***************************************************************************
+ */
+
+/** UDP socket opener */
+struct socket_opener udp_socket_opener __socket_opener = {
+ .semantics = UDP_SOCK_DGRAM,
+ .family = AF_INET,
+ .open = udp_open,
+};
+
+/** Linkage hack */
+int udp_sock_dgram = UDP_SOCK_DGRAM;
+
+/**
+ * Open UDP URI
+ *
+ * @v xfer Data transfer interface
+ * @v uri URI
+ * @ret rc Return status code
+ */
+static int udp_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
+ struct sockaddr_tcpip peer;
+
+ /* Sanity check */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ memset ( &peer, 0, sizeof ( peer ) );
+ peer.st_port = htons ( uri_port ( uri, 0 ) );
+ return xfer_open_named_socket ( xfer, SOCK_DGRAM,
+ ( struct sockaddr * ) &peer,
+ uri->host, NULL );
+}
+
+/** UDP URI opener */
+struct uri_opener udp_uri_opener __uri_opener = {
+ .scheme = "udp",
+ .open = udp_open_uri,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/udp/dhcp.c b/debian/grub-extras/disabled/gpxe/src/net/udp/dhcp.c
new file mode 100644
index 0000000..aaf691f
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/udp/dhcp.c
@@ -0,0 +1,1430 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/device.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/job.h>
+#include <gpxe/retry.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/ip.h>
+#include <gpxe/uuid.h>
+#include <gpxe/timer.h>
+#include <gpxe/settings.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/dhcpopts.h>
+#include <gpxe/dhcppkt.h>
+#include <gpxe/features.h>
+
+/** @file
+ *
+ * Dynamic Host Configuration Protocol
+ *
+ */
+
+struct dhcp_session;
+static int dhcp_tx ( struct dhcp_session *dhcp );
+
+/**
+ * DHCP operation types
+ *
+ * This table maps from DHCP message types (i.e. values of the @c
+ * DHCP_MESSAGE_TYPE option) to values of the "op" field within a DHCP
+ * packet.
+ */
+static const uint8_t dhcp_op[] = {
+ [DHCPDISCOVER] = BOOTP_REQUEST,
+ [DHCPOFFER] = BOOTP_REPLY,
+ [DHCPREQUEST] = BOOTP_REQUEST,
+ [DHCPDECLINE] = BOOTP_REQUEST,
+ [DHCPACK] = BOOTP_REPLY,
+ [DHCPNAK] = BOOTP_REPLY,
+ [DHCPRELEASE] = BOOTP_REQUEST,
+ [DHCPINFORM] = BOOTP_REQUEST,
+};
+
+/** Raw option data for options common to all DHCP requests */
+static uint8_t dhcp_request_options_data[] = {
+ DHCP_MAX_MESSAGE_SIZE,
+ DHCP_WORD ( ETH_MAX_MTU - 20 /* IP header */ - 8 /* UDP header */ ),
+ DHCP_CLIENT_ARCHITECTURE, DHCP_WORD ( 0 ),
+ DHCP_CLIENT_NDI, DHCP_OPTION ( 1 /* UNDI */ , 2, 1 /* v2.1 */ ),
+ DHCP_VENDOR_CLASS_ID,
+ DHCP_STRING ( 'P', 'X', 'E', 'C', 'l', 'i', 'e', 'n', 't', ':',
+ 'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '0', ':',
+ 'U', 'N', 'D', 'I', ':', '0', '0', '2', '0', '0', '1' ),
+ DHCP_USER_CLASS_ID,
+ DHCP_STRING ( 'g', 'P', 'X', 'E' ),
+ DHCP_PARAMETER_REQUEST_LIST,
+ DHCP_OPTION ( DHCP_SUBNET_MASK, DHCP_ROUTERS, DHCP_DNS_SERVERS,
+ DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
+ DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
+ DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
+ DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
+ DHCP_END
+};
+
+/** Version number feature */
+FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
+
+/** DHCP server address setting */
+struct setting dhcp_server_setting __setting = {
+ .name = "dhcp-server",
+ .description = "DHCP server address",
+ .tag = DHCP_SERVER_IDENTIFIER,
+ .type = &setting_type_ipv4,
+};
+
+/** DHCP user class setting */
+struct setting user_class_setting __setting = {
+ .name = "user-class",
+ .description = "User class identifier",
+ .tag = DHCP_USER_CLASS_ID,
+ .type = &setting_type_string,
+};
+
+/**
+ * Name a DHCP packet type
+ *
+ * @v msgtype DHCP message type
+ * @ret string DHCP mesasge type name
+ */
+static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
+ switch ( msgtype ) {
+ case DHCPNONE: return "BOOTP"; /* Non-DHCP packet */
+ case DHCPDISCOVER: return "DHCPDISCOVER";
+ case DHCPOFFER: return "DHCPOFFER";
+ case DHCPREQUEST: return "DHCPREQUEST";
+ case DHCPDECLINE: return "DHCPDECLINE";
+ case DHCPACK: return "DHCPACK";
+ case DHCPNAK: return "DHCPNAK";
+ case DHCPRELEASE: return "DHCPRELEASE";
+ case DHCPINFORM: return "DHCPINFORM";
+ default: return "DHCP<invalid>";
+ }
+}
+
+/**
+ * Calculate DHCP transaction ID for a network device
+ *
+ * @v netdev Network device
+ * @ret xid DHCP XID
+ *
+ * Extract the least significant bits of the hardware address for use
+ * as the transaction ID.
+ */
+static uint32_t dhcp_xid ( struct net_device *netdev ) {
+ uint32_t xid;
+
+ memcpy ( &xid, ( netdev->ll_addr + netdev->ll_protocol->ll_addr_len
+ - sizeof ( xid ) ), sizeof ( xid ) );
+ return xid;
+}
+
+/****************************************************************************
+ *
+ * DHCP session
+ *
+ */
+
+struct dhcp_session;
+
+/** DHCP session state operations */
+struct dhcp_session_state {
+ /** State name */
+ const char *name;
+ /**
+ * Construct transmitted packet
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+ int ( * tx ) ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer );
+ /** Handle received packet
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+ void ( * rx ) ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer,
+ uint8_t msgtype, struct in_addr server_id );
+ /** Handle timer expiry
+ *
+ * @v dhcp DHCP session
+ */
+ void ( * expired ) ( struct dhcp_session *dhcp );
+ /** Transmitted message type */
+ uint8_t tx_msgtype;
+ /** Apply minimum timeout */
+ uint8_t apply_min_timeout;
+};
+
+static struct dhcp_session_state dhcp_state_discover;
+static struct dhcp_session_state dhcp_state_request;
+static struct dhcp_session_state dhcp_state_proxy;
+static struct dhcp_session_state dhcp_state_pxebs;
+
+/** A DHCP session */
+struct dhcp_session {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Job control interface */
+ struct job_interface job;
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+
+ /** Network device being configured */
+ struct net_device *netdev;
+ /** Local socket address */
+ struct sockaddr_in local;
+ /** State of the session */
+ struct dhcp_session_state *state;
+
+ /** Offered IP address */
+ struct in_addr offer;
+ /** DHCP server */
+ struct in_addr server;
+ /** DHCP offer priority */
+ int priority;
+
+ /** ProxyDHCP protocol extensions should be ignored */
+ int no_pxedhcp;
+ /** ProxyDHCP server */
+ struct in_addr proxy_server;
+ /** ProxyDHCP port */
+ uint16_t proxy_port;
+ /** ProxyDHCP server priority */
+ int proxy_priority;
+
+ /** PXE Boot Server type */
+ uint16_t pxe_type;
+ /** List of PXE Boot Servers to attempt */
+ struct in_addr *pxe_attempt;
+ /** List of PXE Boot Servers to accept */
+ struct in_addr *pxe_accept;
+
+ /** Retransmission timer */
+ struct retry_timer timer;
+ /** Start time of the current state (in ticks) */
+ unsigned long start;
+};
+
+/**
+ * Free DHCP session
+ *
+ * @v refcnt Reference counter
+ */
+static void dhcp_free ( struct refcnt *refcnt ) {
+ struct dhcp_session *dhcp =
+ container_of ( refcnt, struct dhcp_session, refcnt );
+
+ netdev_put ( dhcp->netdev );
+ free ( dhcp );
+}
+
+/**
+ * Mark DHCP session as complete
+ *
+ * @v dhcp DHCP session
+ * @v rc Return status code
+ */
+static void dhcp_finished ( struct dhcp_session *dhcp, int rc ) {
+
+ /* Block futher incoming messages */
+ job_nullify ( &dhcp->job );
+ xfer_nullify ( &dhcp->xfer );
+
+ /* Stop retry timer */
+ stop_timer ( &dhcp->timer );
+
+ /* Free resources and close interfaces */
+ xfer_close ( &dhcp->xfer, rc );
+ job_done ( &dhcp->job, rc );
+}
+
+/**
+ * Transition to new DHCP session state
+ *
+ * @v dhcp DHCP session
+ * @v state New session state
+ */
+static void dhcp_set_state ( struct dhcp_session *dhcp,
+ struct dhcp_session_state *state ) {
+
+ DBGC ( dhcp, "DHCP %p entering %s state\n", dhcp, state->name );
+ dhcp->state = state;
+ dhcp->start = currticks();
+ stop_timer ( &dhcp->timer );
+ dhcp->timer.min_timeout =
+ ( state->apply_min_timeout ? DHCP_MIN_TIMEOUT : 0 );
+ dhcp->timer.max_timeout = DHCP_MAX_TIMEOUT;
+ start_timer_nodelay ( &dhcp->timer );
+}
+
+/****************************************************************************
+ *
+ * DHCP state machine
+ *
+ */
+
+/**
+ * Construct transmitted packet for DHCP discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt __unused,
+ struct sockaddr_in *peer ) {
+
+ DBGC ( dhcp, "DHCP %p DHCPDISCOVER\n", dhcp );
+
+ /* Set server address */
+ peer->sin_addr.s_addr = INADDR_BROADCAST;
+ peer->sin_port = htons ( BOOTPS_PORT );
+
+ return 0;
+}
+
+/**
+ * Handle received packet during DHCP discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct in_addr ip;
+ char vci[9]; /* "PXEClient" */
+ int vci_len;
+ int has_pxeclient;
+ int pxeopts_len;
+ int has_pxeopts;
+ int8_t priority = 0;
+ uint8_t no_pxedhcp = 0;
+ unsigned long elapsed;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+
+ /* Identify offered IP address */
+ ip = dhcppkt->dhcphdr->yiaddr;
+ if ( ip.s_addr )
+ DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
+
+ /* Identify "PXEClient" vendor class */
+ vci_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_CLASS_ID,
+ vci, sizeof ( vci ) );
+ has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) &&
+ ( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 ));
+
+ /* Identify presence of vendor-specific options */
+ pxeopts_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_ENCAP, NULL, 0 );
+ has_pxeopts = ( pxeopts_len >= 0 );
+ if ( has_pxeclient )
+ DBGC ( dhcp, "%s", ( has_pxeopts ? " pxe" : " proxy" ) );
+
+ /* Identify priority */
+ dhcppkt_fetch ( dhcppkt, DHCP_EB_PRIORITY, &priority,
+ sizeof ( priority ) );
+ if ( priority )
+ DBGC ( dhcp, " pri %d", priority );
+
+ /* Identify ignore-PXE flag */
+ dhcppkt_fetch ( dhcppkt, DHCP_EB_NO_PXEDHCP, &no_pxedhcp,
+ sizeof ( no_pxedhcp ) );
+ if ( no_pxedhcp )
+ DBGC ( dhcp, " nopxe" );
+ DBGC ( dhcp, "\n" );
+
+ /* Select as DHCP offer, if applicable */
+ if ( ip.s_addr && ( peer->sin_port == htons ( BOOTPS_PORT ) ) &&
+ ( ( msgtype == DHCPOFFER ) || ( ! msgtype /* BOOTP */ ) ) &&
+ ( priority >= dhcp->priority ) ) {
+ dhcp->offer = ip;
+ dhcp->server = server_id;
+ dhcp->priority = priority;
+ dhcp->no_pxedhcp = no_pxedhcp;
+ }
+
+ /* Select as ProxyDHCP offer, if applicable */
+ if ( has_pxeclient && ( msgtype == DHCPOFFER ) &&
+ ( priority >= dhcp->proxy_priority ) ) {
+ /* If the offer already includes the PXE options, then
+ * assume that we can send the ProxyDHCPREQUEST to
+ * port 67 (since the DHCPDISCOVER that triggered this
+ * ProxyDHCPOFFER was sent to port 67). Otherwise,
+ * send the ProxyDHCPREQUEST to port 4011.
+ */
+ dhcp->proxy_server = server_id;
+ dhcp->proxy_port = ( has_pxeopts ? htons ( BOOTPS_PORT )
+ : htons ( PXE_PORT ) );
+ dhcp->proxy_priority = priority;
+ }
+
+ /* We can exit the discovery state when we have a valid
+ * DHCPOFFER, and either:
+ *
+ * o The DHCPOFFER instructs us to ignore ProxyDHCPOFFERs, or
+ * o We have a valid ProxyDHCPOFFER, or
+ * o We have allowed sufficient time for ProxyDHCPOFFERs.
+ */
+
+ /* If we don't yet have a DHCPOFFER, do nothing */
+ if ( ! dhcp->offer.s_addr )
+ return;
+
+ /* If we can't yet transition to DHCPREQUEST, do nothing */
+ elapsed = ( currticks() - dhcp->start );
+ if ( ! ( dhcp->no_pxedhcp || dhcp->proxy_server.s_addr ||
+ ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) )
+ return;
+
+ /* Transition to DHCPREQUEST */
+ dhcp_set_state ( dhcp, &dhcp_state_request );
+}
+
+/**
+ * Handle timer expiry during DHCP discovery
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
+ unsigned long elapsed = ( currticks() - dhcp->start );
+
+ /* Give up waiting for ProxyDHCP before we reach the failure point */
+ if ( dhcp->offer.s_addr && ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) {
+ dhcp_set_state ( dhcp, &dhcp_state_request );
+ return;
+ }
+
+ /* Otherwise, retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** DHCP discovery state operations */
+static struct dhcp_session_state dhcp_state_discover = {
+ .name = "discovery",
+ .tx = dhcp_discovery_tx,
+ .rx = dhcp_discovery_rx,
+ .expired = dhcp_discovery_expired,
+ .tx_msgtype = DHCPDISCOVER,
+ .apply_min_timeout = 1,
+};
+
+/**
+ * Construct transmitted packet for DHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_request_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer ) {
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p DHCPREQUEST to %s:%d",
+ dhcp, inet_ntoa ( dhcp->server ), BOOTPS_PORT );
+ DBGC ( dhcp, " for %s\n", inet_ntoa ( dhcp->offer ) );
+
+ /* Set server ID */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &dhcp->server,
+ sizeof ( dhcp->server ) ) ) != 0 )
+ return rc;
+
+ /* Set requested IP address */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
+ &dhcp->offer,
+ sizeof ( dhcp->offer ) ) ) != 0 )
+ return rc;
+
+ /* Set server address */
+ peer->sin_addr.s_addr = INADDR_BROADCAST;
+ peer->sin_port = htons ( BOOTPS_PORT );
+
+ return 0;
+}
+
+/**
+ * Handle received packet during DHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_request_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct in_addr ip;
+ struct settings *parent;
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+
+ /* Identify leased IP address */
+ ip = dhcppkt->dhcphdr->yiaddr;
+ if ( ip.s_addr )
+ DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
+ DBGC ( dhcp, "\n" );
+
+ /* Filter out unacceptable responses */
+ if ( peer->sin_port != htons ( BOOTPS_PORT ) )
+ return;
+ if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
+ return;
+ if ( server_id.s_addr != dhcp->server.s_addr )
+ return;
+
+ /* Record assigned address */
+ dhcp->local.sin_addr = ip;
+
+ /* Register settings */
+ parent = netdev_settings ( dhcp->netdev );
+ if ( ( rc = register_settings ( &dhcppkt->settings, parent ) ) != 0 ){
+ DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+
+ /* Start ProxyDHCPREQUEST if applicable */
+ if ( dhcp->proxy_server.s_addr /* Have ProxyDHCP server */ &&
+ ( ! dhcp->no_pxedhcp ) /* ProxyDHCP not disabled */ &&
+ ( /* ProxyDHCP server is not just the DHCP server itself */
+ ( dhcp->proxy_server.s_addr != dhcp->server.s_addr ) ||
+ ( dhcp->proxy_port != htons ( BOOTPS_PORT ) ) ) ) {
+ dhcp_set_state ( dhcp, &dhcp_state_proxy );
+ return;
+ }
+
+ /* Terminate DHCP */
+ dhcp_finished ( dhcp, 0 );
+}
+
+/**
+ * Handle timer expiry during DHCP discovery
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_request_expired ( struct dhcp_session *dhcp ) {
+
+ /* Retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** DHCP request state operations */
+static struct dhcp_session_state dhcp_state_request = {
+ .name = "request",
+ .tx = dhcp_request_tx,
+ .rx = dhcp_request_rx,
+ .expired = dhcp_request_expired,
+ .tx_msgtype = DHCPREQUEST,
+ .apply_min_timeout = 0,
+};
+
+/**
+ * Construct transmitted packet for ProxyDHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer ) {
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s:%d\n", dhcp,
+ inet_ntoa ( dhcp->proxy_server ), ntohs ( dhcp->proxy_port ) );
+
+ /* Set server ID */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &dhcp->proxy_server,
+ sizeof ( dhcp->proxy_server ) ) ) != 0 )
+ return rc;
+
+ /* Set server address */
+ peer->sin_addr = dhcp->proxy_server;
+ peer->sin_port = dhcp->proxy_port;
+
+ return 0;
+}
+
+/**
+ * Handle received packet during ProxyDHCP request
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+ DBGC ( dhcp, "\n" );
+
+ /* Filter out unacceptable responses */
+ if ( peer->sin_port != dhcp->proxy_port )
+ return;
+ if ( msgtype != DHCPACK )
+ return;
+ if ( server_id.s_addr /* Linux PXE server omits server ID */ &&
+ ( server_id.s_addr != dhcp->proxy_server.s_addr ) )
+ return;
+
+ /* Register settings */
+ dhcppkt->settings.name = PROXYDHCP_SETTINGS_NAME;
+ if ( ( rc = register_settings ( &dhcppkt->settings, NULL ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+
+ /* Terminate DHCP */
+ dhcp_finished ( dhcp, 0 );
+}
+
+/**
+ * Handle timer expiry during ProxyDHCP request
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_proxy_expired ( struct dhcp_session *dhcp ) {
+ unsigned long elapsed = ( currticks() - dhcp->start );
+
+ /* Give up waiting for ProxyDHCP before we reach the failure point */
+ if ( elapsed > PROXYDHCP_MAX_TIMEOUT ) {
+ dhcp_finished ( dhcp, 0 );
+ return;
+ }
+
+ /* Retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** ProxyDHCP request state operations */
+static struct dhcp_session_state dhcp_state_proxy = {
+ .name = "ProxyDHCP",
+ .tx = dhcp_proxy_tx,
+ .rx = dhcp_proxy_rx,
+ .expired = dhcp_proxy_expired,
+ .tx_msgtype = DHCPREQUEST,
+ .apply_min_timeout = 0,
+};
+
+/**
+ * Construct transmitted packet for PXE Boot Server Discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer Destination address
+ */
+static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer ) {
+ struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
+ int rc;
+
+ /* Set server address */
+ peer->sin_addr = *(dhcp->pxe_attempt);
+ peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ?
+ htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) );
+
+ DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
+ dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
+ ntohs ( dhcp->pxe_type ) );
+
+ /* Set boot menu item */
+ menu_item.type = dhcp->pxe_type;
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
+ &menu_item, sizeof ( menu_item ) ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Check to see if PXE Boot Server address is acceptable
+ *
+ * @v dhcp DHCP session
+ * @v bs Boot Server address
+ * @ret accept Boot Server is acceptable
+ */
+static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
+ struct in_addr bs ) {
+ struct in_addr *accept;
+
+ /* Accept if we have no acceptance filter */
+ if ( ! dhcp->pxe_accept )
+ return 1;
+
+ /* Scan through acceptance list */
+ for ( accept = dhcp->pxe_accept ; accept->s_addr ; accept++ ) {
+ if ( accept->s_addr == bs.s_addr )
+ return 1;
+ }
+
+ DBGC ( dhcp, "DHCP %p rejecting server %s\n",
+ dhcp, inet_ntoa ( bs ) );
+ return 0;
+}
+
+/**
+ * Handle received packet during PXE Boot Server Discovery
+ *
+ * @v dhcp DHCP session
+ * @v dhcppkt DHCP packet
+ * @v peer DHCP server address
+ * @v msgtype DHCP message type
+ * @v server_id DHCP server ID
+ */
+static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
+ struct dhcp_packet *dhcppkt,
+ struct sockaddr_in *peer, uint8_t msgtype,
+ struct in_addr server_id ) {
+ struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
+ int rc;
+
+ DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
+ dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ if ( server_id.s_addr != peer->sin_addr.s_addr )
+ DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
+
+ /* Identify boot menu item */
+ dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
+ &menu_item, sizeof ( menu_item ) );
+ if ( menu_item.type )
+ DBGC ( dhcp, " for type %d", ntohs ( menu_item.type ) );
+ DBGC ( dhcp, "\n" );
+
+ /* Filter out unacceptable responses */
+ if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) &&
+ ( peer->sin_port != htons ( PXE_PORT ) ) )
+ return;
+ if ( msgtype != DHCPACK )
+ return;
+ if ( menu_item.type != dhcp->pxe_type )
+ return;
+ if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ?
+ server_id : peer->sin_addr ) ) )
+ return;
+
+ /* Register settings */
+ dhcppkt->settings.name = PXEBS_SETTINGS_NAME;
+ if ( ( rc = register_settings ( &dhcppkt->settings, NULL ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
+ dhcp, strerror ( rc ) );
+ dhcp_finished ( dhcp, rc );
+ return;
+ }
+
+ /* Terminate DHCP */
+ dhcp_finished ( dhcp, 0 );
+}
+
+/**
+ * Handle timer expiry during PXE Boot Server Discovery
+ *
+ * @v dhcp DHCP session
+ */
+static void dhcp_pxebs_expired ( struct dhcp_session *dhcp ) {
+ unsigned long elapsed = ( currticks() - dhcp->start );
+
+ /* Give up waiting before we reach the failure point, and fail
+ * over to the next server in the attempt list
+ */
+ if ( elapsed > PXEBS_MAX_TIMEOUT ) {
+ dhcp->pxe_attempt++;
+ if ( dhcp->pxe_attempt->s_addr ) {
+ dhcp_set_state ( dhcp, &dhcp_state_pxebs );
+ return;
+ } else {
+ dhcp_finished ( dhcp, -ETIMEDOUT );
+ return;
+ }
+ }
+
+ /* Retransmit current packet */
+ dhcp_tx ( dhcp );
+}
+
+/** PXE Boot Server Discovery state operations */
+static struct dhcp_session_state dhcp_state_pxebs = {
+ .name = "PXEBS",
+ .tx = dhcp_pxebs_tx,
+ .rx = dhcp_pxebs_rx,
+ .expired = dhcp_pxebs_expired,
+ .tx_msgtype = DHCPREQUEST,
+ .apply_min_timeout = 1,
+};
+
+/****************************************************************************
+ *
+ * Packet construction
+ *
+ */
+
+/**
+ * Construct DHCP client hardware address field and broadcast flag
+ *
+ * @v netdev Network device
+ * @v hlen DHCP hardware address length to fill in
+ * @v flags DHCP flags to fill in
+ * @ret chaddr DHCP client hardware address
+ */
+void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen,
+ uint16_t *flags ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
+ typeof ( ( ( struct dhcphdr * ) NULL )->chaddr ) chaddr;
+
+ /* If the link-layer address cannot fit into the chaddr field
+ * (as is the case for IPoIB) then try using the hardware
+ * address instead. If we do this, set the broadcast flag,
+ * since chaddr then does not represent a valid link-layer
+ * address for the return path.
+ *
+ * If even the hardware address is too large, use an empty
+ * chaddr field and set the broadcast flag.
+ *
+ * This goes against RFC4390, but RFC4390 mandates that we use
+ * a DHCP client identifier that conforms with RFC4361, which
+ * we cannot do without either persistent (NIC-independent)
+ * storage, or by eliminating the hardware address completely
+ * from the DHCP packet, which seems unfriendly to users.
+ */
+ if ( ( *hlen = ll_protocol->ll_addr_len ) <= sizeof ( chaddr ) ) {
+ return netdev->ll_addr;
+ }
+ *flags = htons ( BOOTP_FL_BROADCAST );
+ if ( ( *hlen = ll_protocol->hw_addr_len ) <= sizeof ( chaddr ) ) {
+ return netdev->hw_addr;
+ } else {
+ *hlen = 0;
+ return NULL;
+ }
+}
+
+/**
+ * Create a DHCP packet
+ *
+ * @v dhcppkt DHCP packet structure to fill in
+ * @v netdev Network device
+ * @v msgtype DHCP message type
+ * @v options Initial options to include (or NULL)
+ * @v options_len Length of initial options
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Creates a DHCP packet in the specified buffer, and initialise a
+ * DHCP packet structure.
+ */
+int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, uint8_t msgtype,
+ const void *options, size_t options_len,
+ void *data, size_t max_len ) {
+ struct dhcphdr *dhcphdr = data;
+ void *chaddr;
+ int rc;
+
+ /* Sanity check */
+ if ( max_len < ( sizeof ( *dhcphdr ) + options_len ) )
+ return -ENOSPC;
+
+ /* Initialise DHCP packet content */
+ memset ( dhcphdr, 0, max_len );
+ dhcphdr->xid = dhcp_xid ( netdev );
+ dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
+ dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
+ dhcphdr->op = dhcp_op[msgtype];
+ chaddr = dhcp_chaddr ( netdev, &dhcphdr->hlen, &dhcphdr->flags );
+ memcpy ( dhcphdr->chaddr, chaddr, dhcphdr->hlen );
+ memcpy ( dhcphdr->options, options, options_len );
+
+ /* Initialise DHCP packet structure */
+ memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
+ dhcppkt_init ( dhcppkt, data, max_len );
+
+ /* Set DHCP_MESSAGE_TYPE option */
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE,
+ &msgtype, sizeof ( msgtype ) ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
+ * Create DHCP request packet
+ *
+ * @v dhcppkt DHCP packet structure to fill in
+ * @v netdev Network device
+ * @v msgtype DHCP message type
+ * @v ciaddr Client IP address
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Creates a DHCP request packet in the specified buffer, and
+ * initialise a DHCP packet structure.
+ */
+int dhcp_create_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, unsigned int msgtype,
+ struct in_addr ciaddr, void *data, size_t max_len ) {
+ struct device_description *desc = &netdev->dev->desc;
+ struct dhcp_netdev_desc dhcp_desc;
+ struct dhcp_client_id client_id;
+ struct dhcp_client_uuid client_uuid;
+ uint8_t *dhcp_features;
+ size_t dhcp_features_len;
+ size_t ll_addr_len;
+ ssize_t len;
+ int rc;
+
+ /* Create DHCP packet */
+ if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype,
+ dhcp_request_options_data,
+ sizeof ( dhcp_request_options_data ),
+ data, max_len ) ) != 0 ) {
+ DBG ( "DHCP could not create DHCP packet: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Set client IP address */
+ dhcppkt->dhcphdr->ciaddr = ciaddr;
+
+ /* Add options to identify the feature list */
+#if 0
+ dhcp_features = table_start ( DHCP_FEATURES );
+ dhcp_features_len = table_num_entries ( DHCP_FEATURES );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features,
+ dhcp_features_len ) ) != 0 ) {
+ DBG ( "DHCP could not set features list option: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+#endif
+
+ /* Add options to identify the network device */
+ dhcp_desc.type = desc->bus_type;
+ dhcp_desc.vendor = htons ( desc->vendor );
+ dhcp_desc.device = htons ( desc->device );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc,
+ sizeof ( dhcp_desc ) ) ) != 0 ) {
+ DBG ( "DHCP could not set bus ID option: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Add DHCP client identifier. Required for Infiniband, and
+ * doesn't hurt other link layers.
+ */
+ client_id.ll_proto = ntohs ( netdev->ll_protocol->ll_proto );
+ ll_addr_len = netdev->ll_protocol->ll_addr_len;
+ assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
+ memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id,
+ ( ll_addr_len + 1 ) ) ) != 0 ) {
+ DBG ( "DHCP could not set client ID: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+#if 0
+ /* Add client UUID, if we have one. Required for PXE. */
+ client_uuid.type = DHCP_CLIENT_UUID_TYPE;
+ if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
+ &client_uuid.uuid ) ) >= 0 ) {
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
+ &client_uuid,
+ sizeof ( client_uuid ) ) ) != 0 ) {
+ DBG ( "DHCP could not set client UUID: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ }
+#endif
+
+ /* Add user class, if we have one. */
+ if ( ( len = fetch_setting_len ( NULL, &user_class_setting ) ) >= 0 ) {
+ char user_class[len];
+ fetch_setting ( NULL, &user_class_setting, user_class,
+ sizeof ( user_class ) );
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_USER_CLASS_ID,
+ &user_class,
+ sizeof ( user_class ) ) ) != 0 ) {
+ DBG ( "DHCP could not set user class: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/**
+ * Transmit DHCP request
+ *
+ * @v dhcp DHCP session
+ * @ret rc Return status code
+ */
+static int dhcp_tx ( struct dhcp_session *dhcp ) {
+ static struct sockaddr_in peer = {
+ .sin_family = AF_INET,
+ };
+ struct xfer_metadata meta = {
+ .netdev = dhcp->netdev,
+ .src = ( struct sockaddr * ) &dhcp->local,
+ .dest = ( struct sockaddr * ) &peer,
+ };
+ struct io_buffer *iobuf;
+ uint8_t msgtype = dhcp->state->tx_msgtype;
+ struct dhcp_packet dhcppkt;
+ int rc;
+
+ /* Start retry timer. Do this first so that failures to
+ * transmit will be retried.
+ */
+ start_timer ( &dhcp->timer );
+
+ /* Allocate buffer for packet */
+ iobuf = xfer_alloc_iob ( &dhcp->xfer, DHCP_MIN_LEN );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Create basic DHCP packet in temporary buffer */
+ if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
+ dhcp->local.sin_addr, iobuf->data,
+ iob_tailroom ( iobuf ) ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
+ dhcp, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Fill in packet based on current state */
+ if ( ( rc = dhcp->state->tx ( dhcp, &dhcppkt, &peer ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not fill DHCP request: %s\n",
+ dhcp, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Transmit the packet */
+ iob_put ( iobuf, dhcppkt.len );
+ if ( ( rc = xfer_deliver_iob_meta ( &dhcp->xfer, iob_disown ( iobuf ),
+ &meta ) ) != 0 ) {
+ DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
+ dhcp, strerror ( rc ) );
+ goto done;
+ }
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Receive new data
+ *
+ * @v xfer Data transfer interface
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int dhcp_deliver_iob ( struct xfer_interface *xfer,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct dhcp_session *dhcp =
+ container_of ( xfer, struct dhcp_session, xfer );
+ struct sockaddr_in *peer;
+ size_t data_len;
+ struct dhcp_packet *dhcppkt;
+ struct dhcphdr *dhcphdr;
+ uint8_t msgtype = 0;
+ struct in_addr server_id = { 0 };
+ int rc = 0;
+
+ /* Sanity checks */
+ if ( ! meta->src ) {
+ DBGC ( dhcp, "DHCP %p received packet without source port\n",
+ dhcp );
+ rc = -EINVAL;
+ goto err_no_src;
+ }
+ peer = ( struct sockaddr_in * ) meta->src;
+
+ /* Create a DHCP packet containing the I/O buffer contents.
+ * Whilst we could just use the original buffer in situ, that
+ * would waste the unused space in the packet buffer, and also
+ * waste a relatively scarce fully-aligned I/O buffer.
+ */
+ data_len = iob_len ( iobuf );
+ dhcppkt = zalloc ( sizeof ( *dhcppkt ) + data_len );
+ if ( ! dhcppkt ) {
+ rc = -ENOMEM;
+ goto err_alloc_dhcppkt;
+ }
+ dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
+ memcpy ( dhcphdr, iobuf->data, data_len );
+ dhcppkt_init ( dhcppkt, dhcphdr, data_len );
+
+ /* Identify message type */
+ dhcppkt_fetch ( dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
+ sizeof ( msgtype ) );
+
+ /* Identify server ID */
+ dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &server_id, sizeof ( server_id ) );
+
+ /* Check for matching transaction ID */
+ if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
+ DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
+ "ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
+ inet_ntoa ( peer->sin_addr ),
+ ntohs ( peer->sin_port ) );
+ rc = -EINVAL;
+ goto err_xid;
+ };
+
+ /* Handle packet based on current state */
+ dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
+
+ err_xid:
+ dhcppkt_put ( dhcppkt );
+ err_alloc_dhcppkt:
+ err_no_src:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/** DHCP data transfer interface operations */
+static struct xfer_interface_operations dhcp_xfer_operations = {
+ .close = ignore_xfer_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = dhcp_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/**
+ * Handle DHCP retry timer expiry
+ *
+ * @v timer DHCP retry timer
+ * @v fail Failure indicator
+ */
+static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct dhcp_session *dhcp =
+ container_of ( timer, struct dhcp_session, timer );
+
+ /* If we have failed, terminate DHCP */
+ if ( fail ) {
+ dhcp_finished ( dhcp, -ETIMEDOUT );
+ return;
+ }
+
+ /* Handle timer expiry based on current state */
+ dhcp->state->expired ( dhcp );
+}
+
+/****************************************************************************
+ *
+ * Job control interface
+ *
+ */
+
+/**
+ * Handle kill() event received via job control interface
+ *
+ * @v job DHCP job control interface
+ */
+static void dhcp_job_kill ( struct job_interface *job ) {
+ struct dhcp_session *dhcp =
+ container_of ( job, struct dhcp_session, job );
+
+ /* Terminate DHCP session */
+ dhcp_finished ( dhcp, -ECANCELED );
+}
+
+/** DHCP job control interface operations */
+static struct job_interface_operations dhcp_job_operations = {
+ .done = ignore_job_done,
+ .kill = dhcp_job_kill,
+ .progress = ignore_job_progress,
+};
+
+/****************************************************************************
+ *
+ * Instantiators
+ *
+ */
+
+/**
+ * DHCP peer address for socket opening
+ *
+ * This is a dummy address; the only useful portion is the socket
+ * family (so that we get a UDP connection). The DHCP client will set
+ * the IP address and source port explicitly on each transmission.
+ */
+static struct sockaddr dhcp_peer = {
+ .sa_family = AF_INET,
+};
+
+/**
+ * Start DHCP state machine on a network device
+ *
+ * @v job Job control interface
+ * @v netdev Network device
+ * @ret rc Return status code
+ *
+ * Starts DHCP on the specified network device. If successful, the
+ * DHCPACK (and ProxyDHCPACK, if applicable) will be registered as
+ * option sources.
+ */
+int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
+ struct dhcp_session *dhcp;
+ int rc;
+
+ /* Allocate and initialise structure */
+ dhcp = zalloc ( sizeof ( *dhcp ) );
+ if ( ! dhcp )
+ return -ENOMEM;
+ dhcp->refcnt.free = dhcp_free;
+ job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt );
+ xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt );
+ dhcp->netdev = netdev_get ( netdev );
+ dhcp->local.sin_family = AF_INET;
+ dhcp->local.sin_port = htons ( BOOTPC_PORT );
+ dhcp->timer.expired = dhcp_timer_expired;
+
+ /* Instantiate child objects and attach to our interfaces */
+ if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
+ ( struct sockaddr * ) &dhcp->local ) ) != 0 )
+ goto err;
+
+ /* Enter DHCPDISCOVER state */
+ dhcp_set_state ( dhcp, &dhcp_state_discover );
+
+ /* Attach parent interface, mortalise self, and return */
+ job_plug_plug ( &dhcp->job, job );
+ ref_put ( &dhcp->refcnt );
+ return 0;
+
+ err:
+ dhcp_finished ( dhcp, rc );
+ ref_put ( &dhcp->refcnt );
+ return rc;
+}
+
+/**
+ * Retrieve list of PXE boot servers for a given server type
+ *
+ * @v dhcp DHCP session
+ * @v raw DHCP PXE boot server list
+ * @v raw_len Length of DHCP PXE boot server list
+ * @v ip IP address list to fill in
+ *
+ * The caller must ensure that the IP address list has sufficient
+ * space.
+ */
+static void pxebs_list ( struct dhcp_session *dhcp, void *raw,
+ size_t raw_len, struct in_addr *ip ) {
+ struct dhcp_pxe_boot_server *server = raw;
+ size_t server_len;
+ unsigned int i;
+
+ while ( raw_len ) {
+ if ( raw_len < sizeof ( *server ) ) {
+ DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
+ dhcp );
+ break;
+ }
+ server_len = offsetof ( typeof ( *server ),
+ ip[ server->num_ip ] );
+ if ( raw_len < server_len ) {
+ DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
+ dhcp );
+ break;
+ }
+ if ( server->type == dhcp->pxe_type ) {
+ for ( i = 0 ; i < server->num_ip ; i++ )
+ *(ip++) = server->ip[i];
+ }
+ server = ( ( ( void * ) server ) + server_len );
+ raw_len -= server_len;
+ }
+}
+
+/**
+ * Start PXE Boot Server Discovery on a network device
+ *
+ * @v job Job control interface
+ * @v netdev Network device
+ * @v pxe_type PXE server type
+ * @ret rc Return status code
+ *
+ * Starts PXE Boot Server Discovery on the specified network device.
+ * If successful, the Boot Server ACK will be registered as an option
+ * source.
+ */
+int start_pxebs ( struct job_interface *job, struct net_device *netdev,
+ unsigned int pxe_type ) {
+ struct setting pxe_discovery_control_setting =
+ { .tag = DHCP_PXE_DISCOVERY_CONTROL };
+ struct setting pxe_boot_servers_setting =
+ { .tag = DHCP_PXE_BOOT_SERVERS };
+ struct setting pxe_boot_server_mcast_setting =
+ { .tag = DHCP_PXE_BOOT_SERVER_MCAST };
+ ssize_t pxebs_list_len;
+ struct dhcp_session *dhcp;
+ struct in_addr *ip;
+ unsigned int pxe_discovery_control;
+ int rc;
+
+ /* Get upper bound for PXE boot server IP address list */
+ pxebs_list_len = fetch_setting_len ( NULL, &pxe_boot_servers_setting );
+ if ( pxebs_list_len < 0 )
+ pxebs_list_len = 0;
+
+ /* Allocate and initialise structure */
+ dhcp = zalloc ( sizeof ( *dhcp ) + sizeof ( *ip ) /* mcast */ +
+ sizeof ( *ip ) /* bcast */ + pxebs_list_len +
+ sizeof ( *ip ) /* terminator */ );
+ if ( ! dhcp )
+ return -ENOMEM;
+ dhcp->refcnt.free = dhcp_free;
+ job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt );
+ xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt );
+ dhcp->netdev = netdev_get ( netdev );
+ dhcp->local.sin_family = AF_INET;
+ fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting,
+ &dhcp->local.sin_addr );
+ dhcp->local.sin_port = htons ( BOOTPC_PORT );
+ dhcp->pxe_type = htons ( pxe_type );
+ dhcp->timer.expired = dhcp_timer_expired;
+
+ /* Construct PXE boot server IP address lists */
+ pxe_discovery_control =
+ fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
+ ip = ( ( ( void * ) dhcp ) + sizeof ( *dhcp ) );
+ dhcp->pxe_attempt = ip;
+ if ( ! ( pxe_discovery_control & PXEBS_NO_MULTICAST ) ) {
+ fetch_ipv4_setting ( NULL, &pxe_boot_server_mcast_setting, ip);
+ if ( ip->s_addr )
+ ip++;
+ }
+ if ( ! ( pxe_discovery_control & PXEBS_NO_BROADCAST ) )
+ (ip++)->s_addr = INADDR_BROADCAST;
+ if ( pxe_discovery_control & PXEBS_NO_UNKNOWN_SERVERS )
+ dhcp->pxe_accept = ip;
+ if ( pxebs_list_len ) {
+ uint8_t buf[pxebs_list_len];
+
+ fetch_setting ( NULL, &pxe_boot_servers_setting,
+ buf, sizeof ( buf ) );
+ pxebs_list ( dhcp, buf, sizeof ( buf ), ip );
+ }
+ if ( ! dhcp->pxe_attempt->s_addr ) {
+ DBGC ( dhcp, "DHCP %p has no PXE boot servers for type %04x\n",
+ dhcp, pxe_type );
+ rc = -EINVAL;
+ goto err;
+ }
+
+ /* Dump out PXE server lists */
+ DBGC ( dhcp, "DHCP %p attempting", dhcp );
+ for ( ip = dhcp->pxe_attempt ; ip->s_addr ; ip++ )
+ DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
+ DBGC ( dhcp, "\n" );
+ if ( dhcp->pxe_accept ) {
+ DBGC ( dhcp, "DHCP %p accepting", dhcp );
+ for ( ip = dhcp->pxe_accept ; ip->s_addr ; ip++ )
+ DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
+ DBGC ( dhcp, "\n" );
+ }
+
+ /* Instantiate child objects and attach to our interfaces */
+ if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
+ ( struct sockaddr * ) &dhcp->local ) ) != 0 )
+ goto err;
+
+ /* Enter PXEBS state */
+ dhcp_set_state ( dhcp, &dhcp_state_pxebs );
+
+ /* Attach parent interface, mortalise self, and return */
+ job_plug_plug ( &dhcp->job, job );
+ ref_put ( &dhcp->refcnt );
+ return 0;
+
+ err:
+ dhcp_finished ( dhcp, rc );
+ ref_put ( &dhcp->refcnt );
+ return rc;
+}
diff --git a/debian/grub-extras/disabled/gpxe/src/net/udp/dns.c b/debian/grub-extras/disabled/gpxe/src/net/udp/dns.c
new file mode 100644
index 0000000..3bb6829
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/udp/dns.c
@@ -0,0 +1,602 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * Portions copyright (C) 2004 Anselm M. Hoffmeister
+ * <stockholm@users.sourceforge.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/resolv.h>
+#include <gpxe/retry.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/settings.h>
+#include <gpxe/features.h>
+#include <gpxe/dns.h>
+
+/** @file
+ *
+ * DNS protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "DNS", DHCP_EB_FEATURE_DNS, 1 );
+
+/** The DNS server */
+static struct sockaddr_tcpip nameserver = {
+ .st_port = htons ( DNS_PORT ),
+};
+
+/** The local domain */
+static char *localdomain;
+
+/** A DNS request */
+struct dns_request {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Name resolution interface */
+ struct resolv_interface resolv;
+ /** Data transfer interface */
+ struct xfer_interface socket;
+ /** Retry timer */
+ struct retry_timer timer;
+
+ /** Socket address to fill in with resolved address */
+ struct sockaddr sa;
+ /** Current query packet */
+ struct dns_query query;
+ /** Location of query info structure within current packet
+ *
+ * The query info structure is located immediately after the
+ * compressed name.
+ */
+ struct dns_query_info *qinfo;
+ /** Recursion counter */
+ unsigned int recursion;
+};
+
+/**
+ * Mark DNS request as complete
+ *
+ * @v dns DNS request
+ * @v rc Return status code
+ */
+static void dns_done ( struct dns_request *dns, int rc ) {
+
+ /* Stop the retry timer */
+ stop_timer ( &dns->timer );
+
+ /* Close data transfer interface */
+ xfer_nullify ( &dns->socket );
+ xfer_close ( &dns->socket, rc );
+
+ /* Mark name resolution as complete */
+ resolv_done ( &dns->resolv, &dns->sa, rc );
+}
+
+/**
+ * Compare DNS reply name against the query name from the original request
+ *
+ * @v dns DNS request
+ * @v reply DNS reply
+ * @v rname Reply name
+ * @ret zero Names match
+ * @ret non-zero Names do not match
+ */
+static int dns_name_cmp ( struct dns_request *dns,
+ const struct dns_header *reply,
+ const char *rname ) {
+ const char *qname = dns->query.payload;
+ int i;
+
+ while ( 1 ) {
+ /* Obtain next section of rname */
+ while ( ( *rname ) & 0xc0 ) {
+ rname = ( ( ( char * ) reply ) +
+ ( ntohs( *((uint16_t *)rname) ) & ~0xc000 ));
+ }
+ /* Check that lengths match */
+ if ( *rname != *qname )
+ return -1;
+ /* If length is zero, we have reached the end */
+ if ( ! *qname )
+ return 0;
+ /* Check that data matches */
+ for ( i = *qname + 1; i > 0 ; i-- ) {
+ if ( *(rname++) != *(qname++) )
+ return -1;
+ }
+ }
+}
+
+/**
+ * Skip over a (possibly compressed) DNS name
+ *
+ * @v name DNS name
+ * @ret name Next DNS name
+ */
+static const char * dns_skip_name ( const char *name ) {
+ while ( 1 ) {
+ if ( ! *name ) {
+ /* End of name */
+ return ( name + 1);
+ }
+ if ( *name & 0xc0 ) {
+ /* Start of a compressed name */
+ return ( name + 2 );
+ }
+ /* Uncompressed name portion */
+ name += *name + 1;
+ }
+}
+
+/**
+ * Find an RR in a reply packet corresponding to our query
+ *
+ * @v dns DNS request
+ * @v reply DNS reply
+ * @ret rr DNS RR, or NULL if not found
+ */
+static union dns_rr_info * dns_find_rr ( struct dns_request *dns,
+ const struct dns_header *reply ) {
+ int i, cmp;
+ const char *p = ( ( char * ) reply ) + sizeof ( struct dns_header );
+ union dns_rr_info *rr_info;
+
+ /* Skip over the questions section */
+ for ( i = ntohs ( reply->qdcount ) ; i > 0 ; i-- ) {
+ p = dns_skip_name ( p ) + sizeof ( struct dns_query_info );
+ }
+
+ /* Process the answers section */
+ for ( i = ntohs ( reply->ancount ) ; i > 0 ; i-- ) {
+ cmp = dns_name_cmp ( dns, reply, p );
+ p = dns_skip_name ( p );
+ rr_info = ( ( union dns_rr_info * ) p );
+ if ( cmp == 0 )
+ return rr_info;
+ p += ( sizeof ( rr_info->common ) +
+ ntohs ( rr_info->common.rdlength ) );
+ }
+
+ return NULL;
+}
+
+/**
+ * Append DHCP domain name if available and name is not fully qualified
+ *
+ * @v string Name as a NUL-terminated string
+ * @ret fqdn Fully-qualified domain name, malloc'd copy
+ *
+ * The caller must free fqdn which is allocated even if the name is already
+ * fully qualified.
+ */
+static char * dns_qualify_name ( const char *string ) {
+ char *fqdn;
+
+ /* Leave unchanged if already fully-qualified or no local domain */
+ if ( ( ! localdomain ) || ( strchr ( string, '.' ) != 0 ) )
+ return strdup ( string );
+
+ /* Append local domain to name */
+ return grub_xasprintf ( "%s.%s", string, localdomain );
+}
+
+/**
+ * Convert a standard NUL-terminated string to a DNS name
+ *
+ * @v string Name as a NUL-terminated string
+ * @v buf Buffer in which to place DNS name
+ * @ret next Byte following constructed DNS name
+ *
+ * DNS names consist of "<length>element" pairs.
+ */
+static char * dns_make_name ( const char *string, char *buf ) {
+ char *length_byte = buf++;
+ char c;
+
+ while ( ( c = *(string++) ) ) {
+ if ( c == '.' ) {
+ *length_byte = buf - length_byte - 1;
+ length_byte = buf;
+ }
+ *(buf++) = c;
+ }
+ *length_byte = buf - length_byte - 1;
+ *(buf++) = '\0';
+ return buf;
+}
+
+/**
+ * Convert an uncompressed DNS name to a NUL-terminated string
+ *
+ * @v name DNS name
+ * @ret string NUL-terminated string
+ *
+ * Produce a printable version of a DNS name. Used only for debugging.
+ */
+static inline char * dns_unmake_name ( char *name ) {
+ char *p;
+ unsigned int len;
+
+ p = name;
+ while ( ( len = *p ) ) {
+ *(p++) = '.';
+ p += len;
+ }
+
+ return name + 1;
+}
+
+/**
+ * Decompress a DNS name
+ *
+ * @v reply DNS replay
+ * @v name DNS name
+ * @v buf Buffer into which to decompress DNS name
+ * @ret next Byte following decompressed DNS name
+ */
+static char * dns_decompress_name ( const struct dns_header *reply,
+ const char *name, char *buf ) {
+ int i, len;
+
+ do {
+ /* Obtain next section of name */
+ while ( ( *name ) & 0xc0 ) {
+ name = ( ( char * ) reply +
+ ( ntohs ( *((uint16_t *)name) ) & ~0xc000 ) );
+ }
+ /* Copy data */
+ len = *name;
+ for ( i = len + 1 ; i > 0 ; i-- ) {
+ *(buf++) = *(name++);
+ }
+ } while ( len );
+ return buf;
+}
+
+/**
+ * Send next packet in DNS request
+ *
+ * @v dns DNS request
+ */
+static int dns_send_packet ( struct dns_request *dns ) {
+ static unsigned int qid = 0;
+ size_t qlen;
+
+ /* Increment query ID */
+ dns->query.dns.id = htons ( ++qid );
+
+ DBGC ( dns, "DNS %p sending query ID %d\n", dns, qid );
+
+ /* Start retransmission timer */
+ start_timer ( &dns->timer );
+
+ /* Send the data */
+ qlen = ( ( ( void * ) dns->qinfo ) - ( ( void * ) &dns->query )
+ + sizeof ( dns->qinfo ) );
+ return xfer_deliver_raw ( &dns->socket, &dns->query, qlen );
+}
+
+/**
+ * Handle DNS retransmission timer expiry
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ */
+static void dns_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct dns_request *dns =
+ container_of ( timer, struct dns_request, timer );
+
+ if ( fail ) {
+ dns_done ( dns, -ETIMEDOUT );
+ } else {
+ dns_send_packet ( dns );
+ }
+}
+
+/**
+ * Receive new data
+ *
+ * @v socket UDP socket
+ * @v data DNS reply
+ * @v len Length of DNS reply
+ * @ret rc Return status code
+ */
+static int dns_xfer_deliver_raw ( struct xfer_interface *socket,
+ const void *data, size_t len ) {
+ struct dns_request *dns =
+ container_of ( socket, struct dns_request, socket );
+ const struct dns_header *reply = data;
+ union dns_rr_info *rr_info;
+ struct sockaddr_in *sin;
+ unsigned int qtype = dns->qinfo->qtype;
+
+ /* Sanity check */
+ if ( len < sizeof ( *reply ) ) {
+ DBGC ( dns, "DNS %p received underlength packet length %zd\n",
+ dns, len );
+ return -EINVAL;
+ }
+
+ /* Check reply ID matches query ID */
+ if ( reply->id != dns->query.dns.id ) {
+ DBGC ( dns, "DNS %p received unexpected reply ID %d "
+ "(wanted %d)\n", dns, ntohs ( reply->id ),
+ ntohs ( dns->query.dns.id ) );
+ return -EINVAL;
+ }
+
+ DBGC ( dns, "DNS %p received reply ID %d\n", dns, ntohs ( reply->id ));
+
+ /* Stop the retry timer. After this point, each code path
+ * must either restart the timer by calling dns_send_packet(),
+ * or mark the DNS operation as complete by calling
+ * dns_done()
+ */
+ stop_timer ( &dns->timer );
+
+ /* Search through response for useful answers. Do this
+ * multiple times, to take advantage of useful nameservers
+ * which send us e.g. the CNAME *and* the A record for the
+ * pointed-to name.
+ */
+ while ( ( rr_info = dns_find_rr ( dns, reply ) ) ) {
+ switch ( rr_info->common.type ) {
+
+ case htons ( DNS_TYPE_A ):
+
+ /* Found the target A record */
+ DBGC ( dns, "DNS %p found address %s\n",
+ dns, inet_ntoa ( rr_info->a.in_addr ) );
+ sin = ( struct sockaddr_in * ) &dns->sa;
+ sin->sin_family = AF_INET;
+ sin->sin_addr = rr_info->a.in_addr;
+
+ /* Mark operation as complete */
+ dns_done ( dns, 0 );
+ return 0;
+
+ case htons ( DNS_TYPE_CNAME ):
+
+ /* Found a CNAME record; update query and recurse */
+ DBGC ( dns, "DNS %p found CNAME\n", dns );
+ dns->qinfo = ( void * ) dns_decompress_name ( reply,
+ rr_info->cname.cname,
+ dns->query.payload );
+ dns->qinfo->qtype = htons ( DNS_TYPE_A );
+ dns->qinfo->qclass = htons ( DNS_CLASS_IN );
+
+ /* Terminate the operation if we recurse too far */
+ if ( ++dns->recursion > DNS_MAX_CNAME_RECURSION ) {
+ DBGC ( dns, "DNS %p recursion exceeded\n",
+ dns );
+ dns_done ( dns, -ELOOP );
+ return 0;
+ }
+ break;
+
+ default:
+ DBGC ( dns, "DNS %p got unknown record type %d\n",
+ dns, ntohs ( rr_info->common.type ) );
+ break;
+ }
+ }
+
+ /* Determine what to do next based on the type of query we
+ * issued and the reponse we received
+ */
+ switch ( qtype ) {
+
+ case htons ( DNS_TYPE_A ):
+ /* We asked for an A record and got nothing;
+ * try the CNAME.
+ */
+ DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns );
+ dns->qinfo->qtype = htons ( DNS_TYPE_CNAME );
+ dns_send_packet ( dns );
+ return 0;
+
+ case htons ( DNS_TYPE_CNAME ):
+ /* We asked for a CNAME record. If we got a response
+ * (i.e. if the next A query is already set up), then
+ * issue it, otherwise abort.
+ */
+ if ( dns->qinfo->qtype == htons ( DNS_TYPE_A ) ) {
+ dns_send_packet ( dns );
+ return 0;
+ } else {
+ DBGC ( dns, "DNS %p found no CNAME record\n", dns );
+ dns_done ( dns, -ENXIO );
+ return 0;
+ }
+
+ default:
+ assert ( 0 );
+ dns_done ( dns, -EINVAL );
+ return 0;
+ }
+}
+
+/**
+ * Receive new data
+ *
+ * @v socket UDP socket
+ * @v rc Reason for close
+ */
+static void dns_xfer_close ( struct xfer_interface *socket, int rc ) {
+ struct dns_request *dns =
+ container_of ( socket, struct dns_request, socket );
+
+ if ( ! rc )
+ rc = -ECONNABORTED;
+
+ dns_done ( dns, rc );
+}
+
+/** DNS socket operations */
+static struct xfer_interface_operations dns_socket_operations = {
+ .close = dns_xfer_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = dns_xfer_deliver_raw,
+};
+
+/**
+ * Resolve name using DNS
+ *
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
+ * @v sa Socket address to fill in
+ * @ret rc Return status code
+ */
+static int dns_resolv ( struct resolv_interface *resolv,
+ const char *name, struct sockaddr *sa ) {
+ struct dns_request *dns;
+ char *fqdn;
+ int rc;
+
+ /* Fail immediately if no DNS servers */
+ if ( ! nameserver.st_family ) {
+ DBG ( "DNS not attempting to resolve \"%s\": "
+ "no DNS servers\n", name );
+ rc = -ENXIO;
+ goto err_no_nameserver;
+ }
+
+ /* Ensure fully-qualified domain name if DHCP option was given */
+ fqdn = dns_qualify_name ( name );
+ if ( ! fqdn ) {
+ rc = -ENOMEM;
+ goto err_qualify_name;
+ }
+
+ /* Allocate DNS structure */
+ dns = zalloc ( sizeof ( *dns ) );
+ if ( ! dns ) {
+ rc = -ENOMEM;
+ goto err_alloc_dns;
+ }
+ resolv_init ( &dns->resolv, &null_resolv_ops, &dns->refcnt );
+ xfer_init ( &dns->socket, &dns_socket_operations, &dns->refcnt );
+ dns->timer.expired = dns_timer_expired;
+ memcpy ( &dns->sa, sa, sizeof ( dns->sa ) );
+
+ /* Create query */
+ dns->query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY |
+ DNS_FLAG_RD );
+ dns->query.dns.qdcount = htons ( 1 );
+ dns->qinfo = ( void * ) dns_make_name ( fqdn, dns->query.payload );
+ dns->qinfo->qtype = htons ( DNS_TYPE_A );
+ dns->qinfo->qclass = htons ( DNS_CLASS_IN );
+
+ /* Open UDP connection */
+ if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &nameserver,
+ NULL ) ) != 0 ) {
+ DBGC ( dns, "DNS %p could not open socket: %s\n",
+ dns, strerror ( rc ) );
+ goto err_open_socket;
+ }
+
+ /* Send first DNS packet */
+ dns_send_packet ( dns );
+
+ /* Attach parent interface, mortalise self, and return */
+ resolv_plug_plug ( &dns->resolv, resolv );
+ ref_put ( &dns->refcnt );
+ free ( fqdn );
+ return 0;
+
+ err_open_socket:
+ err_alloc_dns:
+ ref_put ( &dns->refcnt );
+ err_qualify_name:
+ free ( fqdn );
+ err_no_nameserver:
+ return rc;
+}
+
+/** DNS name resolver */
+struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
+ .name = "DNS",
+ .resolv = dns_resolv,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** DNS server setting */
+struct setting dns_setting __setting = {
+ .name = "dns",
+ .description = "DNS server",
+ .tag = DHCP_DNS_SERVERS,
+ .type = &setting_type_ipv4,
+};
+
+/** Domain name setting */
+struct setting domain_setting __setting = {
+ .name = "domain",
+ .description = "Local domain",
+ .tag = DHCP_DOMAIN_NAME,
+ .type = &setting_type_string,
+};
+
+/**
+ * Apply DNS settings
+ *
+ * @ret rc Return status code
+ */
+static int apply_dns_settings ( void ) {
+ struct sockaddr_in *sin_nameserver =
+ ( struct sockaddr_in * ) &nameserver;
+ int len;
+
+ if ( ( len = fetch_ipv4_setting ( NULL, &dns_setting,
+ &sin_nameserver->sin_addr ) ) >= 0 ){
+ sin_nameserver->sin_family = AF_INET;
+ DBG ( "DNS using nameserver %s\n",
+ inet_ntoa ( sin_nameserver->sin_addr ) );
+ }
+
+ /* Get local domain DHCP option */
+ if ( ( len = fetch_string_setting_copy ( NULL, &domain_setting,
+ &localdomain ) ) >= 0 )
+ DBG ( "DNS local domain %s\n", localdomain );
+
+ return 0;
+}
+
+/** DNS settings applicator */
+struct settings_applicator dns_applicator __settings_applicator = {
+ .apply = apply_dns_settings,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/udp/slam.c b/debian/grub-extras/disabled/gpxe/src/net/udp/slam.c
new file mode 100644
index 0000000..396f69b
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/udp/slam.c
@@ -0,0 +1,812 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <gpxe/features.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/bitmap.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/uri.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/timer.h>
+#include <gpxe/retry.h>
+
+/** @file
+ *
+ * Scalable Local Area Multicast protocol
+ *
+ * The SLAM protocol is supported only by Etherboot; it was designed
+ * and implemented by Eric Biederman. A server implementation is
+ * available in contrib/mini-slamd. There does not appear to be any
+ * documentation beyond a few sparse comments in Etherboot's
+ * proto_slam.c.
+ *
+ * SLAM packets use three types of data field:
+ *
+ * Nul : A single NUL (0) byte, used as a list terminator
+ *
+ * Raw : A block of raw data
+ *
+ * Int : A variable-length integer, in big-endian order. The length
+ * of the integer is encoded in the most significant three bits.
+ *
+ * Packets received by the client have the following layout:
+ *
+ * Int : Transaction identifier. This is an opaque value.
+ *
+ * Int : Total number of bytes in the transfer.
+ *
+ * Int : Block size, in bytes.
+ *
+ * Int : Packet sequence number within the transfer (if this packet
+ * contains data).
+ *
+ * Raw : Packet data (if this packet contains data).
+ *
+ * Packets transmitted by the client consist of a run-length-encoded
+ * representation of the received-blocks bitmap, looking something
+ * like:
+ *
+ * Int : Number of consecutive successfully-received packets
+ * Int : Number of consecutive missing packets
+ * Int : Number of consecutive successfully-received packets
+ * Int : Number of consecutive missing packets
+ * ....
+ * Nul
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "SLAM", DHCP_EB_FEATURE_SLAM, 1 );
+
+/** Default SLAM server port */
+#define SLAM_DEFAULT_PORT 10000
+
+/** Default SLAM multicast IP address */
+#define SLAM_DEFAULT_MULTICAST_IP \
+ ( ( 239 << 24 ) | ( 255 << 16 ) | ( 1 << 8 ) | ( 1 << 0 ) )
+
+/** Default SLAM multicast port */
+#define SLAM_DEFAULT_MULTICAST_PORT 10000
+
+/** Maximum SLAM header length */
+#define SLAM_MAX_HEADER_LEN ( 7 /* transaction id */ + 7 /* total_bytes */ + \
+ 7 /* block_size */ )
+
+/** Maximum number of blocks to request per NACK
+ *
+ * This is a policy decision equivalent to selecting a TCP window
+ * size.
+ */
+#define SLAM_MAX_BLOCKS_PER_NACK 4
+
+/** Maximum SLAM NACK length
+ *
+ * We only ever send a NACK for a single range of up to @c
+ * SLAM_MAX_BLOCKS_PER_NACK blocks.
+ */
+#define SLAM_MAX_NACK_LEN ( 7 /* block */ + 7 /* #blocks */ + 1 /* NUL */ )
+
+/** SLAM slave timeout */
+#define SLAM_SLAVE_TIMEOUT ( 1 * TICKS_PER_SEC )
+
+/** A SLAM request */
+struct slam_request {
+ /** Reference counter */
+ struct refcnt refcnt;
+
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+ /** Unicast socket */
+ struct xfer_interface socket;
+ /** Multicast socket */
+ struct xfer_interface mc_socket;
+
+ /** Master client retry timer */
+ struct retry_timer master_timer;
+ /** Slave client retry timer */
+ struct retry_timer slave_timer;
+
+ /** Cached header */
+ uint8_t header[SLAM_MAX_HEADER_LEN];
+ /** Size of cached header */
+ size_t header_len;
+ /** Total number of bytes in transfer */
+ unsigned long total_bytes;
+ /** Transfer block size */
+ unsigned long block_size;
+ /** Number of blocks in transfer */
+ unsigned long num_blocks;
+ /** Block bitmap */
+ struct bitmap bitmap;
+ /** NACK sent flag */
+ int nack_sent;
+};
+
+/**
+ * Free a SLAM request
+ *
+ * @v refcnt Reference counter
+ */
+static void slam_free ( struct refcnt *refcnt ) {
+ struct slam_request *slam =
+ container_of ( refcnt, struct slam_request, refcnt );
+
+ bitmap_free ( &slam->bitmap );
+ free ( slam );
+}
+
+/**
+ * Mark SLAM request as complete
+ *
+ * @v slam SLAM request
+ * @v rc Return status code
+ */
+static void slam_finished ( struct slam_request *slam, int rc ) {
+ static const uint8_t slam_disconnect[] = { 0 };
+
+ DBGC ( slam, "SLAM %p finished with status code %d (%s)\n",
+ slam, rc, strerror ( rc ) );
+
+ /* Send a disconnect message if we ever sent anything to the
+ * server.
+ */
+ if ( slam->nack_sent ) {
+ xfer_deliver_raw ( &slam->socket, slam_disconnect,
+ sizeof ( slam_disconnect ) );
+ }
+
+ /* Stop the retry timers */
+ stop_timer ( &slam->master_timer );
+ stop_timer ( &slam->slave_timer );
+
+ /* Close all data transfer interfaces */
+ xfer_nullify ( &slam->socket );
+ xfer_close ( &slam->socket, rc );
+ xfer_nullify ( &slam->mc_socket );
+ xfer_close ( &slam->mc_socket, rc );
+ xfer_nullify ( &slam->xfer );
+ xfer_close ( &slam->xfer, rc );
+}
+
+/****************************************************************************
+ *
+ * TX datapath
+ *
+ */
+
+/**
+ * Add a variable-length value to a SLAM packet
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @v value Value to add
+ * @ret rc Return status code
+ *
+ * Adds a variable-length value to the end of an I/O buffer. Will
+ * always leave at least one byte of tailroom in the I/O buffer (to
+ * allow space for the terminating NUL).
+ */
+static int slam_put_value ( struct slam_request *slam,
+ struct io_buffer *iobuf, unsigned long value ) {
+ uint8_t *data;
+ size_t len;
+ unsigned int i;
+
+ /* Calculate variable length required to store value. Always
+ * leave at least one byte in the I/O buffer.
+ */
+ len = ( ( flsl ( value ) + 10 ) / 8 );
+ if ( len >= iob_tailroom ( iobuf ) ) {
+ DBGC2 ( slam, "SLAM %p cannot add %zd-byte value\n",
+ slam, len );
+ return -ENOBUFS;
+ }
+ /* There is no valid way within the protocol that we can end
+ * up trying to push a full-sized long (i.e. without space for
+ * the length encoding).
+ */
+ assert ( len <= sizeof ( value ) );
+
+ /* Add value */
+ data = iob_put ( iobuf, len );
+ for ( i = len ; i-- ; ) {
+ data[i] = value;
+ value >>= 8;
+ }
+ *data |= ( len << 5 );
+ assert ( value == 0 );
+
+ return 0;
+}
+
+/**
+ * Send SLAM NACK packet
+ *
+ * @v slam SLAM request
+ * @ret rc Return status code
+ */
+static int slam_tx_nack ( struct slam_request *slam ) {
+ struct io_buffer *iobuf;
+ unsigned long first_block;
+ unsigned long num_blocks;
+ uint8_t *nul;
+ int rc;
+
+ /* Mark NACK as sent, so that we know we have to disconnect later */
+ slam->nack_sent = 1;
+
+ /* Allocate I/O buffer */
+ iobuf = xfer_alloc_iob ( &slam->socket, SLAM_MAX_NACK_LEN );
+ if ( ! iobuf ) {
+ DBGC ( slam, "SLAM %p could not allocate I/O buffer\n",
+ slam );
+ return -ENOMEM;
+ }
+
+ /* Construct NACK. We always request only a single packet;
+ * this allows us to force multicast-TFTP-style flow control
+ * on the SLAM server, which will otherwise just blast the
+ * data out as fast as it can. On a gigabit network, without
+ * RX checksumming, this would inevitably cause packet drops.
+ */
+ first_block = bitmap_first_gap ( &slam->bitmap );
+ for ( num_blocks = 1 ; ; num_blocks++ ) {
+ if ( num_blocks >= SLAM_MAX_BLOCKS_PER_NACK )
+ break;
+ if ( ( first_block + num_blocks ) >= slam->num_blocks )
+ break;
+ if ( bitmap_test ( &slam->bitmap,
+ ( first_block + num_blocks ) ) )
+ break;
+ }
+ if ( first_block ) {
+ DBGCP ( slam, "SLAM %p transmitting NACK for blocks "
+ "%ld-%ld\n", slam, first_block,
+ ( first_block + num_blocks - 1 ) );
+ } else {
+ DBGC ( slam, "SLAM %p transmitting initial NACK for blocks "
+ "0-%ld\n", slam, ( num_blocks - 1 ) );
+ }
+ if ( ( rc = slam_put_value ( slam, iobuf, first_block ) ) != 0 )
+ return rc;
+ if ( ( rc = slam_put_value ( slam, iobuf, num_blocks ) ) != 0 )
+ return rc;
+ nul = iob_put ( iobuf, 1 );
+ *nul = 0;
+
+ /* Transmit packet */
+ return xfer_deliver_iob ( &slam->socket, iobuf );
+}
+
+/**
+ * Handle SLAM master client retry timer expiry
+ *
+ * @v timer Master retry timer
+ * @v fail Failure indicator
+ */
+static void slam_master_timer_expired ( struct retry_timer *timer,
+ int fail ) {
+ struct slam_request *slam =
+ container_of ( timer, struct slam_request, master_timer );
+
+ if ( fail ) {
+ /* Allow timer to stop running. We will terminate the
+ * connection only if the slave timer times out.
+ */
+ DBGC ( slam, "SLAM %p giving up acting as master client\n",
+ slam );
+ } else {
+ /* Retransmit NACK */
+ start_timer ( timer );
+ slam_tx_nack ( slam );
+ }
+}
+
+/**
+ * Handle SLAM slave client retry timer expiry
+ *
+ * @v timer Master retry timer
+ * @v fail Failure indicator
+ */
+static void slam_slave_timer_expired ( struct retry_timer *timer,
+ int fail ) {
+ struct slam_request *slam =
+ container_of ( timer, struct slam_request, slave_timer );
+
+ if ( fail ) {
+ /* Terminate connection */
+ slam_finished ( slam, -ETIMEDOUT );
+ } else {
+ /* Try sending a NACK */
+ DBGC ( slam, "SLAM %p trying to become master client\n",
+ slam );
+ start_timer ( timer );
+ slam_tx_nack ( slam );
+ }
+}
+
+/****************************************************************************
+ *
+ * RX datapath
+ *
+ */
+
+/**
+ * Read and strip a variable-length value from a SLAM packet
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @v value Value to fill in, or NULL to ignore value
+ * @ret rc Return status code
+ *
+ * Reads a variable-length value from the start of the I/O buffer.
+ */
+static int slam_pull_value ( struct slam_request *slam,
+ struct io_buffer *iobuf,
+ unsigned long *value ) {
+ uint8_t *data;
+ size_t len;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) == 0 ) {
+ DBGC ( slam, "SLAM %p empty value\n", slam );
+ return -EINVAL;
+ }
+
+ /* Read and verify length of value */
+ data = iobuf->data;
+ len = ( *data >> 5 );
+ if ( ( len == 0 ) ||
+ ( value && ( len > sizeof ( *value ) ) ) ) {
+ DBGC ( slam, "SLAM %p invalid value length %zd bytes\n",
+ slam, len );
+ return -EINVAL;
+ }
+ if ( len > iob_len ( iobuf ) ) {
+ DBGC ( slam, "SLAM %p value extends beyond I/O buffer\n",
+ slam );
+ return -EINVAL;
+ }
+
+ /* Read value */
+ iob_pull ( iobuf, len );
+ *value = ( *data & 0x1f );
+ while ( --len ) {
+ *value <<= 8;
+ *value |= *(++data);
+ }
+
+ return 0;
+}
+
+/**
+ * Read and strip SLAM header
+ *
+ * @v slam SLAM request
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int slam_pull_header ( struct slam_request *slam,
+ struct io_buffer *iobuf ) {
+ void *header = iobuf->data;
+ int rc;
+
+ /* If header matches cached header, just pull it and return */
+ if ( ( slam->header_len <= iob_len ( iobuf ) ) &&
+ ( memcmp ( slam->header, iobuf->data, slam->header_len ) == 0 )){
+ iob_pull ( iobuf, slam->header_len );
+ return 0;
+ }
+
+ DBGC ( slam, "SLAM %p detected changed header; resetting\n", slam );
+
+ /* Read and strip transaction ID, total number of bytes, and
+ * block size.
+ */
+ if ( ( rc = slam_pull_value ( slam, iobuf, NULL ) ) != 0 )
+ return rc;
+ if ( ( rc = slam_pull_value ( slam, iobuf,
+ &slam->total_bytes ) ) != 0 )
+ return rc;
+ if ( ( rc = slam_pull_value ( slam, iobuf,
+ &slam->block_size ) ) != 0 )
+ return rc;
+
+ /* Update the cached header */
+ slam->header_len = ( iobuf->data - header );
+ assert ( slam->header_len <= sizeof ( slam->header ) );
+ memcpy ( slam->header, header, slam->header_len );
+
+ /* Calculate number of blocks */
+ slam->num_blocks = ( ( slam->total_bytes + slam->block_size - 1 ) /
+ slam->block_size );
+
+ DBGC ( slam, "SLAM %p has total bytes %ld, block size %ld, num "
+ "blocks %ld\n", slam, slam->total_bytes, slam->block_size,
+ slam->num_blocks );
+
+ /* Discard and reset the bitmap */
+ bitmap_free ( &slam->bitmap );
+ memset ( &slam->bitmap, 0, sizeof ( slam->bitmap ) );
+
+ /* Allocate a new bitmap */
+ if ( ( rc = bitmap_resize ( &slam->bitmap,
+ slam->num_blocks ) ) != 0 ) {
+ /* Failure to allocate a bitmap is fatal */
+ DBGC ( slam, "SLAM %p could not allocate bitmap for %ld "
+ "blocks: %s\n", slam, slam->num_blocks,
+ strerror ( rc ) );
+ slam_finished ( slam, rc );
+ return rc;
+ }
+
+ /* Notify recipient of file size */
+ xfer_seek ( &slam->xfer, slam->total_bytes, SEEK_SET );
+
+ return 0;
+}
+
+/**
+ * Receive SLAM data packet
+ *
+ * @v mc_socket SLAM multicast socket
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int slam_mc_socket_deliver ( struct xfer_interface *mc_socket,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *rx_meta __unused ) {
+ struct slam_request *slam =
+ container_of ( mc_socket, struct slam_request, mc_socket );
+ struct xfer_metadata meta;
+ unsigned long packet;
+ size_t len;
+ int rc;
+
+ /* Stop the master client timer. Restart the slave client timer. */
+ stop_timer ( &slam->master_timer );
+ stop_timer ( &slam->slave_timer );
+ start_timer_fixed ( &slam->slave_timer, SLAM_SLAVE_TIMEOUT );
+
+ /* Read and strip packet header */
+ if ( ( rc = slam_pull_header ( slam, iobuf ) ) != 0 )
+ goto err_discard;
+
+ /* Read and strip packet number */
+ if ( ( rc = slam_pull_value ( slam, iobuf, &packet ) ) != 0 )
+ goto err_discard;
+
+ /* Sanity check packet number */
+ if ( packet >= slam->num_blocks ) {
+ DBGC ( slam, "SLAM %p received out-of-range packet %ld "
+ "(num_blocks=%ld)\n", slam, packet, slam->num_blocks );
+ rc = -EINVAL;
+ goto err_discard;
+ }
+
+ /* Sanity check length */
+ len = iob_len ( iobuf );
+ if ( len > slam->block_size ) {
+ DBGC ( slam, "SLAM %p received oversize packet of %zd bytes "
+ "(block_size=%ld)\n", slam, len, slam->block_size );
+ rc = -EINVAL;
+ goto err_discard;
+ }
+ if ( ( packet != ( slam->num_blocks - 1 ) ) &&
+ ( len < slam->block_size ) ) {
+ DBGC ( slam, "SLAM %p received short packet of %zd bytes "
+ "(block_size=%ld)\n", slam, len, slam->block_size );
+ rc = -EINVAL;
+ goto err_discard;
+ }
+
+ /* If we have already seen this packet, discard it */
+ if ( bitmap_test ( &slam->bitmap, packet ) ) {
+ goto discard;
+ }
+
+ /* Pass to recipient */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.whence = SEEK_SET;
+ meta.offset = ( packet * slam->block_size );
+ if ( ( rc = xfer_deliver_iob_meta ( &slam->xfer, iobuf,
+ &meta ) ) != 0 )
+ goto err;
+
+ /* Mark block as received */
+ bitmap_set ( &slam->bitmap, packet );
+
+ /* If we have received all blocks, terminate */
+ if ( bitmap_full ( &slam->bitmap ) )
+ slam_finished ( slam, 0 );
+
+ return 0;
+
+ err_discard:
+ discard:
+ free_iob ( iobuf );
+ err:
+ return rc;
+}
+
+/**
+ * Receive SLAM non-data packet
+ *
+ * @v socket SLAM unicast socket
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int slam_socket_deliver ( struct xfer_interface *socket,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *rx_meta __unused ) {
+ struct slam_request *slam =
+ container_of ( socket, struct slam_request, socket );
+ int rc;
+
+ /* Restart the master client timer */
+ stop_timer ( &slam->master_timer );
+ start_timer ( &slam->master_timer );
+
+ /* Read and strip packet header */
+ if ( ( rc = slam_pull_header ( slam, iobuf ) ) != 0 )
+ goto discard;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) != 0 ) {
+ DBGC ( slam, "SLAM %p received trailing garbage:\n", slam );
+ DBGC_HD ( slam, iobuf->data, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto discard;
+ }
+
+ /* Discard packet */
+ free_iob ( iobuf );
+
+ /* Send NACK in reply */
+ slam_tx_nack ( slam );
+
+ return 0;
+
+ discard:
+ free_iob ( iobuf );
+ return rc;
+
+}
+
+/**
+ * Close SLAM unicast socket
+ *
+ * @v socket SLAM unicast socket
+ * @v rc Reason for close
+ */
+static void slam_socket_close ( struct xfer_interface *socket, int rc ) {
+ struct slam_request *slam =
+ container_of ( socket, struct slam_request, socket );
+
+ DBGC ( slam, "SLAM %p unicast socket closed: %s\n",
+ slam, strerror ( rc ) );
+
+ slam_finished ( slam, rc );
+}
+
+/** SLAM unicast socket data transfer operations */
+static struct xfer_interface_operations slam_socket_operations = {
+ .close = slam_socket_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = slam_socket_deliver,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/**
+ * Close SLAM multicast socket
+ *
+ * @v mc_socket SLAM multicast socket
+ * @v rc Reason for close
+ */
+static void slam_mc_socket_close ( struct xfer_interface *mc_socket, int rc ){
+ struct slam_request *slam =
+ container_of ( mc_socket, struct slam_request, mc_socket );
+
+ DBGC ( slam, "SLAM %p multicast socket closed: %s\n",
+ slam, strerror ( rc ) );
+
+ slam_finished ( slam, rc );
+}
+
+/** SLAM multicast socket data transfer operations */
+static struct xfer_interface_operations slam_mc_socket_operations = {
+ .close = slam_mc_socket_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = slam_mc_socket_deliver,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/****************************************************************************
+ *
+ * Data transfer interface
+ *
+ */
+
+/**
+ * Close SLAM data transfer interface
+ *
+ * @v xfer SLAM data transfer interface
+ * @v rc Reason for close
+ */
+static void slam_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct slam_request *slam =
+ container_of ( xfer, struct slam_request, xfer );
+
+ DBGC ( slam, "SLAM %p data transfer interface closed: %s\n",
+ slam, strerror ( rc ) );
+
+ slam_finished ( slam, rc );
+}
+
+/** SLAM data transfer operations */
+static struct xfer_interface_operations slam_xfer_operations = {
+ .close = slam_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = ignore_xfer_deliver_raw,
+};
+
+/**
+ * Parse SLAM URI multicast address
+ *
+ * @v slam SLAM request
+ * @v path Path portion of x-slam:// URI
+ * @v address Socket address to fill in
+ * @ret rc Return status code
+ */
+static int slam_parse_multicast_address ( struct slam_request *slam,
+ const char *path,
+ struct sockaddr_in *address ) {
+ char path_dup[ strlen ( path ) /* no +1 */ ];
+ char *sep;
+ char *end;
+
+ /* Create temporary copy of path, minus the leading '/' */
+ assert ( *path == '/' );
+ memcpy ( path_dup, ( path + 1 ) , sizeof ( path_dup ) );
+
+ /* Parse port, if present */
+ sep = strchr ( path_dup, ':' );
+ if ( sep ) {
+ *(sep++) = '\0';
+ address->sin_port = htons ( strtoul ( sep, &end, 0 ) );
+ if ( *end != '\0' ) {
+ DBGC ( slam, "SLAM %p invalid multicast port "
+ "\"%s\"\n", slam, sep );
+ return -EINVAL;
+ }
+ }
+
+ /* Parse address */
+ if ( inet_aton ( path_dup, &address->sin_addr ) == 0 ) {
+ DBGC ( slam, "SLAM %p invalid multicast address \"%s\"\n",
+ slam, path_dup );
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Initiate a SLAM request
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int slam_open ( struct xfer_interface *xfer, struct uri *uri ) {
+ static const struct sockaddr_in default_multicast = {
+ .sin_family = AF_INET,
+ .sin_port = htons ( SLAM_DEFAULT_MULTICAST_PORT ),
+ .sin_addr = { htonl ( SLAM_DEFAULT_MULTICAST_IP ) },
+ };
+ struct slam_request *slam;
+ struct sockaddr_tcpip server;
+ struct sockaddr_in multicast;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->host )
+ return -EINVAL;
+
+ /* Allocate and populate structure */
+ slam = zalloc ( sizeof ( *slam ) );
+ if ( ! slam )
+ return -ENOMEM;
+ slam->refcnt.free = slam_free;
+ xfer_init ( &slam->xfer, &slam_xfer_operations, &slam->refcnt );
+ xfer_init ( &slam->socket, &slam_socket_operations, &slam->refcnt );
+ xfer_init ( &slam->mc_socket, &slam_mc_socket_operations,
+ &slam->refcnt );
+ slam->master_timer.expired = slam_master_timer_expired;
+ slam->slave_timer.expired = slam_slave_timer_expired;
+ /* Fake an invalid cached header of { 0x00, ... } */
+ slam->header_len = 1;
+ /* Fake parameters for initial NACK */
+ slam->num_blocks = 1;
+ if ( ( rc = bitmap_resize ( &slam->bitmap, 1 ) ) != 0 ) {
+ DBGC ( slam, "SLAM %p could not allocate initial bitmap: "
+ "%s\n", slam, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Open unicast socket */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( uri_port ( uri, SLAM_DEFAULT_PORT ) );
+ if ( ( rc = xfer_open_named_socket ( &slam->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &server,
+ uri->host, NULL ) ) != 0 ) {
+ DBGC ( slam, "SLAM %p could not open unicast socket: %s\n",
+ slam, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Open multicast socket */
+ memcpy ( &multicast, &default_multicast, sizeof ( multicast ) );
+ if ( uri->path &&
+ ( ( rc = slam_parse_multicast_address ( slam, uri->path,
+ &multicast ) ) != 0 ) ) {
+ goto err;
+ }
+ if ( ( rc = xfer_open_socket ( &slam->mc_socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &multicast,
+ ( struct sockaddr * ) &multicast ) ) != 0 ) {
+ DBGC ( slam, "SLAM %p could not open multicast socket: %s\n",
+ slam, strerror ( rc ) );
+ goto err;
+ }
+
+ /* Start slave retry timer */
+ start_timer_fixed ( &slam->slave_timer, SLAM_SLAVE_TIMEOUT );
+
+ /* Attach to parent interface, mortalise self, and return */
+ xfer_plug_plug ( &slam->xfer, xfer );
+ ref_put ( &slam->refcnt );
+ return 0;
+
+ err:
+ slam_finished ( slam, rc );
+ ref_put ( &slam->refcnt );
+ return rc;
+}
+
+/** SLAM URI opener */
+struct uri_opener slam_uri_opener __uri_opener = {
+ .scheme = "x-slam",
+ .open = slam_open,
+};
diff --git a/debian/grub-extras/disabled/gpxe/src/net/udp/tftp.c b/debian/grub-extras/disabled/gpxe/src/net/udp/tftp.c
new file mode 100644
index 0000000..bb031ec
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/src/net/udp/tftp.c
@@ -0,0 +1,1205 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <byteswap.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+#include <gpxe/uri.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/retry.h>
+#include <gpxe/features.h>
+#include <gpxe/bitmap.h>
+#include <gpxe/settings.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/uri.h>
+#include <gpxe/tftp.h>
+
+/** @file
+ *
+ * TFTP protocol
+ *
+ */
+
+FEATURE ( FEATURE_PROTOCOL, "TFTP", DHCP_EB_FEATURE_TFTP, 1 );
+
+/* TFTP-specific error codes */
+#define ETFTP_INVALID_BLKSIZE EUNIQ_01
+#define ETFTP_INVALID_TSIZE EUNIQ_02
+#define ETFTP_MC_NO_PORT EUNIQ_03
+#define ETFTP_MC_NO_MC EUNIQ_04
+#define ETFTP_MC_INVALID_MC EUNIQ_05
+#define ETFTP_MC_INVALID_IP EUNIQ_06
+#define ETFTP_MC_INVALID_PORT EUNIQ_07
+
+/**
+ * A TFTP request
+ *
+ * This data structure holds the state for an ongoing TFTP transfer.
+ */
+struct tftp_request {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Data transfer interface */
+ struct xfer_interface xfer;
+
+ /** URI being fetched */
+ struct uri *uri;
+ /** Transport layer interface */
+ struct xfer_interface socket;
+ /** Multicast transport layer interface */
+ struct xfer_interface mc_socket;
+
+ /** Data block size
+ *
+ * This is the "blksize" option negotiated with the TFTP
+ * server. (If the TFTP server does not support TFTP options,
+ * this will default to 512).
+ */
+ unsigned int blksize;
+ /** File size
+ *
+ * This is the value returned in the "tsize" option from the
+ * TFTP server. If the TFTP server does not support the
+ * "tsize" option, this value will be zero.
+ */
+ unsigned long tsize;
+
+ /** Server port
+ *
+ * This is the port to which RRQ packets are sent.
+ */
+ unsigned int port;
+ /** Peer address
+ *
+ * The peer address is determined by the first response
+ * received to the TFTP RRQ.
+ */
+ struct sockaddr_tcpip peer;
+ /** Request flags */
+ unsigned int flags;
+ /** MTFTP timeout count */
+ unsigned int mtftp_timeouts;
+
+ /** Block bitmap */
+ struct bitmap bitmap;
+ /** Maximum known length
+ *
+ * We don't always know the file length in advance. In
+ * particular, if the TFTP server doesn't support the tsize
+ * option, or we are using MTFTP, then we don't know the file
+ * length until we see the end-of-file block (which, in the
+ * case of MTFTP, may not be the last block we see).
+ *
+ * This value is updated whenever we obtain information about
+ * the file length.
+ */
+ size_t filesize;
+ /** Retransmission timer */
+ struct retry_timer timer;
+};
+
+/** TFTP request flags */
+enum {
+ /** Send ACK packets */
+ TFTP_FL_SEND_ACK = 0x0001,
+ /** Request blksize and tsize options */
+ TFTP_FL_RRQ_SIZES = 0x0002,
+ /** Request multicast option */
+ TFTP_FL_RRQ_MULTICAST = 0x0004,
+ /** Perform MTFTP recovery on timeout */
+ TFTP_FL_MTFTP_RECOVERY = 0x0008,
+};
+
+/** Maximum number of MTFTP open requests before falling back to TFTP */
+#define MTFTP_MAX_TIMEOUTS 3
+
+/**
+ * Free TFTP request
+ *
+ * @v refcnt Reference counter
+ */
+static void tftp_free ( struct refcnt *refcnt ) {
+ struct tftp_request *tftp =
+ container_of ( refcnt, struct tftp_request, refcnt );
+
+ uri_put ( tftp->uri );
+ bitmap_free ( &tftp->bitmap );
+ free ( tftp );
+}
+
+/**
+ * Mark TFTP request as complete
+ *
+ * @v tftp TFTP connection
+ * @v rc Return status code
+ */
+static void tftp_done ( struct tftp_request *tftp, int rc ) {
+
+ DBGC ( tftp, "TFTP %p finished with status %d (%s)\n",
+ tftp, rc, strerror ( rc ) );
+
+ /* Stop the retry timer */
+ stop_timer ( &tftp->timer );
+
+ /* Close all data transfer interfaces */
+ xfer_nullify ( &tftp->socket );
+ xfer_close ( &tftp->socket, rc );
+ xfer_nullify ( &tftp->mc_socket );
+ xfer_close ( &tftp->mc_socket, rc );
+ xfer_nullify ( &tftp->xfer );
+ xfer_close ( &tftp->xfer, rc );
+}
+
+/**
+ * Reopen TFTP socket
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_reopen ( struct tftp_request *tftp ) {
+ struct sockaddr_tcpip server;
+ int rc;
+
+ /* Close socket */
+ xfer_close ( &tftp->socket, 0 );
+
+ /* Disable ACK sending. */
+ tftp->flags &= ~TFTP_FL_SEND_ACK;
+
+ /* Reset peer address */
+ memset ( &tftp->peer, 0, sizeof ( tftp->peer ) );
+
+ /* Open socket */
+ memset ( &server, 0, sizeof ( server ) );
+ server.st_port = htons ( tftp->port );
+ if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &server,
+ tftp->uri->host, NULL ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not open socket: %s\n",
+ tftp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Reopen TFTP multicast socket
+ *
+ * @v tftp TFTP connection
+ * @v local Local socket address
+ * @ret rc Return status code
+ */
+static int tftp_reopen_mc ( struct tftp_request *tftp,
+ struct sockaddr *local ) {
+ int rc;
+
+ /* Close multicast socket */
+ xfer_close ( &tftp->mc_socket, 0 );
+
+ /* Open multicast socket. We never send via this socket, so
+ * use the local address as the peer address (since the peer
+ * address cannot be NULL).
+ */
+ if ( ( rc = xfer_open_socket ( &tftp->mc_socket, SOCK_DGRAM,
+ local, local ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not open multicast "
+ "socket: %s\n", tftp, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Presize TFTP receive buffers and block bitmap
+ *
+ * @v tftp TFTP connection
+ * @v filesize Known minimum file size
+ * @ret rc Return status code
+ */
+static int tftp_presize ( struct tftp_request *tftp, size_t filesize ) {
+ unsigned int num_blocks;
+ int rc;
+
+ /* Do nothing if we are already large enough */
+ if ( filesize <= tftp->filesize )
+ return 0;
+
+ /* Record filesize */
+ tftp->filesize = filesize;
+
+ /* Notify recipient of file size */
+ xfer_seek ( &tftp->xfer, filesize, SEEK_SET );
+ xfer_seek ( &tftp->xfer, 0, SEEK_SET );
+
+ /* Calculate expected number of blocks. Note that files whose
+ * length is an exact multiple of the blocksize will have a
+ * trailing zero-length block, which must be included.
+ */
+ num_blocks = ( ( filesize / tftp->blksize ) + 1 );
+ if ( ( rc = bitmap_resize ( &tftp->bitmap, num_blocks ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not resize bitmap to %d blocks: "
+ "%s\n", tftp, num_blocks, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * TFTP requested blocksize
+ *
+ * This is treated as a global configuration parameter.
+ */
+static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE;
+
+/**
+ * Set TFTP request blocksize
+ *
+ * @v blksize Requested block size
+ */
+void tftp_set_request_blksize ( unsigned int blksize ) {
+ if ( blksize < TFTP_DEFAULT_BLKSIZE )
+ blksize = TFTP_DEFAULT_BLKSIZE;
+ tftp_request_blksize = blksize;
+}
+
+/**
+ * MTFTP multicast receive address
+ *
+ * This is treated as a global configuration parameter.
+ */
+static struct sockaddr_in tftp_mtftp_socket = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl ( 0xefff0101 ),
+ .sin_port = htons ( 3001 ),
+};
+
+/**
+ * Set MTFTP multicast address
+ *
+ * @v address Multicast IPv4 address
+ */
+void tftp_set_mtftp_address ( struct in_addr address ) {
+ tftp_mtftp_socket.sin_addr = address;
+}
+
+/**
+ * Set MTFTP multicast port
+ *
+ * @v port Multicast port
+ */
+void tftp_set_mtftp_port ( unsigned int port ) {
+ tftp_mtftp_socket.sin_port = htons ( port );
+}
+
+/**
+ * Transmit RRQ
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_send_rrq ( struct tftp_request *tftp ) {
+ struct tftp_rrq *rrq;
+ const char *path;
+ size_t len;
+ struct io_buffer *iobuf;
+
+ /* Strip initial '/' if present. If we were opened via the
+ * URI interface, then there will be an initial '/', since a
+ * full tftp:// URI provides no way to specify a non-absolute
+ * path. However, many TFTP servers (particularly Windows
+ * TFTP servers) complain about having an initial '/', and it
+ * violates user expectations to have a '/' silently added to
+ * the DHCP-specified filename.
+ */
+ path = tftp->uri->path;
+ if ( *path == '/' )
+ path++;
+
+ DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
+
+ /* Allocate buffer */
+ len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
+ + 5 + 1 /* "octet" + NUL */
+ + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
+ + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */
+ + 9 + 1 + 1 /* "multicast" + NUL + NUL */ );
+ iobuf = xfer_alloc_iob ( &tftp->socket, len );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Build request */
+ rrq = iob_put ( iobuf, sizeof ( *rrq ) );
+ rrq->opcode = htons ( TFTP_RRQ );
+ iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ),
+ "%s%coctet", path, 0 ) + 1 );
+ if ( tftp->flags & TFTP_FL_RRQ_SIZES ) {
+ iob_put ( iobuf, snprintf ( iobuf->tail,
+ iob_tailroom ( iobuf ),
+ "blksize%c%d%ctsize%c0", 0,
+ tftp_request_blksize, 0, 0 ) + 1 );
+ }
+ if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) {
+ iob_put ( iobuf, snprintf ( iobuf->tail,
+ iob_tailroom ( iobuf ),
+ "multicast%c", 0 ) + 1 );
+ }
+
+ /* RRQ always goes to the address specified in the initial
+ * xfer_open() call
+ */
+ return xfer_deliver_iob ( &tftp->socket, iobuf );
+}
+
+/**
+ * Transmit ACK
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_send_ack ( struct tftp_request *tftp ) {
+ struct tftp_ack *ack;
+ struct io_buffer *iobuf;
+ struct xfer_metadata meta = {
+ .dest = ( struct sockaddr * ) &tftp->peer,
+ };
+ unsigned int block;
+
+ /* Determine next required block number */
+ block = bitmap_first_gap ( &tftp->bitmap );
+ DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n", tftp, block );
+
+ /* Allocate buffer */
+ iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
+ if ( ! iobuf )
+ return -ENOMEM;
+
+ /* Build ACK */
+ ack = iob_put ( iobuf, sizeof ( *ack ) );
+ ack->opcode = htons ( TFTP_ACK );
+ ack->block = htons ( block );
+
+ /* ACK always goes to the peer recorded from the RRQ response */
+ return xfer_deliver_iob_meta ( &tftp->socket, iobuf, &meta );
+}
+
+/**
+ * Transmit next relevant packet
+ *
+ * @v tftp TFTP connection
+ * @ret rc Return status code
+ */
+static int tftp_send_packet ( struct tftp_request *tftp ) {
+
+ /* Update retransmission timer */
+ stop_timer ( &tftp->timer );
+ start_timer ( &tftp->timer );
+
+ /* Send RRQ or ACK as appropriate */
+ if ( ! tftp->peer.st_family ) {
+ return tftp_send_rrq ( tftp );
+ } else {
+ if ( tftp->flags & TFTP_FL_SEND_ACK ) {
+ return tftp_send_ack ( tftp );
+ } else {
+ return 0;
+ }
+ }
+}
+
+/**
+ * Handle TFTP retransmission timer expiry
+ *
+ * @v timer Retry timer
+ * @v fail Failure indicator
+ */
+static void tftp_timer_expired ( struct retry_timer *timer, int fail ) {
+ struct tftp_request *tftp =
+ container_of ( timer, struct tftp_request, timer );
+ int rc;
+
+ /* If we are doing MTFTP, attempt the various recovery strategies */
+ if ( tftp->flags & TFTP_FL_MTFTP_RECOVERY ) {
+ if ( tftp->peer.st_family ) {
+ /* If we have received any response from the server,
+ * try resending the RRQ to restart the download.
+ */
+ DBGC ( tftp, "TFTP %p attempting reopen\n", tftp );
+ if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
+ goto err;
+ } else {
+ /* Fall back to plain TFTP after several attempts */
+ tftp->mtftp_timeouts++;
+ DBGC ( tftp, "TFTP %p timeout %d waiting for MTFTP "
+ "open\n", tftp, tftp->mtftp_timeouts );
+
+ if ( tftp->mtftp_timeouts > MTFTP_MAX_TIMEOUTS ) {
+ DBGC ( tftp, "TFTP %p falling back to plain "
+ "TFTP\n", tftp );
+ tftp->flags = TFTP_FL_RRQ_SIZES;
+
+ /* Close multicast socket */
+ xfer_close ( &tftp->mc_socket, 0 );
+
+ /* Reset retry timer */
+ start_timer_nodelay ( &tftp->timer );
+
+ /* The blocksize may change: discard
+ * the block bitmap
+ */
+ bitmap_free ( &tftp->bitmap );
+ memset ( &tftp->bitmap, 0,
+ sizeof ( tftp->bitmap ) );
+
+ /* Reopen on standard TFTP port */
+ tftp->port = TFTP_PORT;
+ if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
+ goto err;
+ }
+ }
+ } else {
+ /* Not doing MTFTP (or have fallen back to plain
+ * TFTP); fail as per normal.
+ */
+ if ( fail ) {
+ rc = -ETIMEDOUT;
+ goto err;
+ }
+ }
+ tftp_send_packet ( tftp );
+ return;
+
+ err:
+ tftp_done ( tftp, rc );
+}
+
+/**
+ * Process TFTP "blksize" option
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_blksize ( struct tftp_request *tftp,
+ const char *value ) {
+ char *end;
+
+ tftp->blksize = strtoul ( value, &end, 10 );
+ if ( *end ) {
+ DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
+ tftp, value );
+ return -( EINVAL | ETFTP_INVALID_BLKSIZE );
+ }
+ DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
+
+ return 0;
+}
+
+/**
+ * Process TFTP "tsize" option
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_tsize ( struct tftp_request *tftp,
+ const char *value ) {
+ char *end;
+
+ tftp->tsize = strtoul ( value, &end, 10 );
+ if ( *end ) {
+ DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
+ tftp, value );
+ return -( EINVAL | ETFTP_INVALID_TSIZE );
+ }
+ DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
+
+ return 0;
+}
+
+/**
+ * Process TFTP "multicast" option
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_multicast ( struct tftp_request *tftp,
+ const char *value ) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ } socket;
+ char buf[ strlen ( value ) + 1 ];
+ char *addr;
+ char *port;
+ char *port_end;
+ char *mc;
+ char *mc_end;
+ int rc;
+
+ /* Split value into "addr,port,mc" fields */
+ memcpy ( buf, value, sizeof ( buf ) );
+ addr = buf;
+ port = strchr ( addr, ',' );
+ if ( ! port ) {
+ DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
+ return -( EINVAL | ETFTP_MC_NO_PORT );
+ }
+ *(port++) = '\0';
+ mc = strchr ( port, ',' );
+ if ( ! mc ) {
+ DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
+ return -( EINVAL | ETFTP_MC_NO_MC );
+ }
+ *(mc++) = '\0';
+
+ /* Parse parameters */
+ if ( strtoul ( mc, &mc_end, 0 ) == 0 )
+ tftp->flags &= ~TFTP_FL_SEND_ACK;
+ if ( *mc_end ) {
+ DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
+ return -( EINVAL | ETFTP_MC_INVALID_MC );
+ }
+ DBGC ( tftp, "TFTP %p is%s the master client\n",
+ tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
+ if ( *addr && *port ) {
+ socket.sin.sin_family = AF_INET;
+ if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
+ DBGC ( tftp, "TFTP %p multicast invalid IP address "
+ "%s\n", tftp, addr );
+ return -( EINVAL | ETFTP_MC_INVALID_IP );
+ }
+ DBGC ( tftp, "TFTP %p multicast IP address %s\n",
+ tftp, inet_ntoa ( socket.sin.sin_addr ) );
+ socket.sin.sin_port = htons ( strtoul ( port, &port_end, 0 ) );
+ if ( *port_end ) {
+ DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
+ tftp, port );
+ return -( EINVAL | ETFTP_MC_INVALID_PORT );
+ }
+ DBGC ( tftp, "TFTP %p multicast port %d\n",
+ tftp, ntohs ( socket.sin.sin_port ) );
+ if ( ( rc = tftp_reopen_mc ( tftp, &socket.sa ) ) != 0 )
+ return rc;
+ }
+
+ return 0;
+}
+
+/** A TFTP option */
+struct tftp_option {
+ /** Option name */
+ const char *name;
+ /** Option processor
+ *
+ * @v tftp TFTP connection
+ * @v value Option value
+ * @ret rc Return status code
+ */
+ int ( * process ) ( struct tftp_request *tftp, const char *value );
+};
+
+/** Recognised TFTP options */
+static struct tftp_option tftp_options[] = {
+ { "blksize", tftp_process_blksize },
+ { "tsize", tftp_process_tsize },
+ { "multicast", tftp_process_multicast },
+ { NULL, NULL }
+};
+
+/**
+ * Process TFTP option
+ *
+ * @v tftp TFTP connection
+ * @v name Option name
+ * @v value Option value
+ * @ret rc Return status code
+ */
+static int tftp_process_option ( struct tftp_request *tftp,
+ const char *name, const char *value ) {
+ struct tftp_option *option;
+
+ for ( option = tftp_options ; option->name ; option++ ) {
+ if ( strcasecmp ( name, option->name ) == 0 )
+ return option->process ( tftp, value );
+ }
+
+ DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
+ tftp, name, value );
+
+ /* Unknown options should be silently ignored */
+ return 0;
+}
+
+/**
+ * Receive OACK
+ *
+ * @v tftp TFTP connection
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
+ * @ret rc Return status code
+ */
+static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
+ struct tftp_oack *oack = buf;
+ char *end = buf + len;
+ char *name;
+ char *value;
+ char *next;
+ int rc = 0;
+
+ /* Sanity check */
+ if ( len < sizeof ( *oack ) ) {
+ DBGC ( tftp, "TFTP %p received underlength OACK packet "
+ "length %zd\n", tftp, len );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Process each option in turn */
+ for ( name = oack->data ; name < end ; name = next ) {
+
+ /* Parse option name and value
+ *
+ * We treat parsing errors as non-fatal, because there
+ * exists at least one TFTP server (IBM Tivoli PXE
+ * Server 5.1.0.3) that has been observed to send
+ * malformed OACKs containing trailing garbage bytes.
+ */
+ value = ( name + strnlen ( name, ( end - name ) ) + 1 );
+ if ( value > end ) {
+ DBGC ( tftp, "TFTP %p received OACK with malformed "
+ "option name:\n", tftp );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+ if ( value == end ) {
+ DBGC ( tftp, "TFTP %p received OACK missing value "
+ "for option \"%s\"\n", tftp, name );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+ next = ( value + strnlen ( value, ( end - value ) ) + 1 );
+ if ( next > end ) {
+ DBGC ( tftp, "TFTP %p received OACK with malformed "
+ "value for option \"%s\":\n", tftp, name );
+ DBGC_HD ( tftp, oack, len );
+ break;
+ }
+
+ /* Process option */
+ if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
+ goto done;
+ }
+
+ /* Process tsize information, if available */
+ if ( tftp->tsize ) {
+ if ( ( rc = tftp_presize ( tftp, tftp->tsize ) ) != 0 )
+ goto done;
+ }
+
+ /* Request next data block */
+ tftp_send_packet ( tftp );
+
+ done:
+ if ( rc )
+ tftp_done ( tftp, rc );
+ return rc;
+}
+
+/**
+ * Receive DATA
+ *
+ * @v tftp TFTP connection
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * Takes ownership of I/O buffer.
+ */
+static int tftp_rx_data ( struct tftp_request *tftp,
+ struct io_buffer *iobuf ) {
+ struct tftp_data *data = iobuf->data;
+ struct xfer_metadata meta;
+ int block;
+ off_t offset;
+ size_t data_len;
+ int rc;
+
+ /* Sanity check */
+ if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
+ DBGC ( tftp, "TFTP %p received underlength DATA packet "
+ "length %zd\n", tftp, iob_len ( iobuf ) );
+ rc = -EINVAL;
+ goto done;
+ }
+ if ( data->block == 0 ) {
+ DBGC ( tftp, "TFTP %p received data block 0\n", tftp );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Extract data */
+ block = ( ntohs ( data->block ) - 1 );
+ offset = ( block * tftp->blksize );
+ iob_pull ( iobuf, sizeof ( *data ) );
+ data_len = iob_len ( iobuf );
+ if ( data_len > tftp->blksize ) {
+ DBGC ( tftp, "TFTP %p received overlength DATA packet "
+ "length %zd\n", tftp, data_len );
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Deliver data */
+ memset ( &meta, 0, sizeof ( meta ) );
+ meta.whence = SEEK_SET;
+ meta.offset = offset;
+ if ( ( rc = xfer_deliver_iob_meta ( &tftp->xfer, iob_disown ( iobuf ),
+ &meta ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
+ tftp, strerror ( rc ) );
+ goto done;
+ }
+
+ /* Ensure block bitmap is ready */
+ if ( ( rc = tftp_presize ( tftp, ( offset + data_len ) ) ) != 0 )
+ goto done;
+
+ /* Mark block as received */
+ bitmap_set ( &tftp->bitmap, block );
+
+ /* Acknowledge block */
+ tftp_send_packet ( tftp );
+
+ /* If all blocks have been received, finish. */
+ if ( bitmap_full ( &tftp->bitmap ) )
+ tftp_done ( tftp, 0 );
+
+ done:
+ free_iob ( iobuf );
+ if ( rc )
+ tftp_done ( tftp, rc );
+ return rc;
+}
+
+/** Translation between TFTP errors and internal error numbers */
+static const int tftp_errors[] = {
+ [TFTP_ERR_FILE_NOT_FOUND] = ENOENT,
+ [TFTP_ERR_ACCESS_DENIED] = EACCES,
+ [TFTP_ERR_ILLEGAL_OP] = ENOTSUP,
+};
+
+/**
+ * Receive ERROR
+ *
+ * @v tftp TFTP connection
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
+ * @ret rc Return status code
+ */
+static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
+ struct tftp_error *error = buf;
+ unsigned int err;
+ int rc = 0;
+
+ /* Sanity check */
+ if ( len < sizeof ( *error ) ) {
+ DBGC ( tftp, "TFTP %p received underlength ERROR packet "
+ "length %zd\n", tftp, len );
+ return -EINVAL;
+ }
+
+ DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
+ "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
+
+ /* Determine final operation result */
+ err = ntohs ( error->errcode );
+ if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
+ rc = -tftp_errors[err];
+ if ( ! rc )
+ rc = -ENOTSUP;
+
+ /* Close TFTP request */
+ tftp_done ( tftp, rc );
+
+ return 0;
+}
+
+/**
+ * Receive new data
+ *
+ * @v tftp TFTP connection
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int tftp_rx ( struct tftp_request *tftp,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct sockaddr_tcpip *st_src;
+ struct tftp_common *common = iobuf->data;
+ size_t len = iob_len ( iobuf );
+ int rc = -EINVAL;
+
+ /* Sanity checks */
+ if ( len < sizeof ( *common ) ) {
+ DBGC ( tftp, "TFTP %p received underlength packet length "
+ "%zd\n", tftp, len );
+ goto done;
+ }
+ if ( ! meta->src ) {
+ DBGC ( tftp, "TFTP %p received packet without source port\n",
+ tftp );
+ goto done;
+ }
+
+ /* Filter by TID. Set TID on first response received */
+ st_src = ( struct sockaddr_tcpip * ) meta->src;
+ if ( ! tftp->peer.st_family ) {
+ memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
+ DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
+ ntohs ( tftp->peer.st_port ) );
+ } else if ( memcmp ( &tftp->peer, st_src,
+ sizeof ( tftp->peer ) ) != 0 ) {
+ DBGC ( tftp, "TFTP %p received packet from wrong source (got "
+ "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
+ ntohs ( tftp->peer.st_port ) );
+ goto done;
+ }
+
+ switch ( common->opcode ) {
+ case htons ( TFTP_OACK ):
+ rc = tftp_rx_oack ( tftp, iobuf->data, len );
+ break;
+ case htons ( TFTP_DATA ):
+ rc = tftp_rx_data ( tftp, iob_disown ( iobuf ) );
+ break;
+ case htons ( TFTP_ERROR ):
+ rc = tftp_rx_error ( tftp, iobuf->data, len );
+ break;
+ default:
+ DBGC ( tftp, "TFTP %p received strange packet type %d\n",
+ tftp, ntohs ( common->opcode ) );
+ break;
+ };
+
+ done:
+ free_iob ( iobuf );
+ return rc;
+}
+
+/**
+ * Receive new data via socket
+ *
+ * @v socket Transport layer interface
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int tftp_socket_deliver_iob ( struct xfer_interface *socket,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct tftp_request *tftp =
+ container_of ( socket, struct tftp_request, socket );
+
+ /* Enable sending ACKs when we receive a unicast packet. This
+ * covers three cases:
+ *
+ * 1. Standard TFTP; we should always send ACKs, and will
+ * always receive a unicast packet before we need to send the
+ * first ACK.
+ *
+ * 2. RFC2090 multicast TFTP; the only unicast packets we will
+ * receive are the OACKs; enable sending ACKs here (before
+ * processing the OACK) and disable it when processing the
+ * multicast option if we are not the master client.
+ *
+ * 3. MTFTP; receiving a unicast datagram indicates that we
+ * are the "master client" and should send ACKs.
+ */
+ tftp->flags |= TFTP_FL_SEND_ACK;
+
+ return tftp_rx ( tftp, iobuf, meta );
+}
+
+/** TFTP socket operations */
+static struct xfer_interface_operations tftp_socket_operations = {
+ .close = ignore_xfer_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = tftp_socket_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/**
+ * Receive new data via multicast socket
+ *
+ * @v mc_socket Multicast transport layer interface
+ * @v iobuf I/O buffer
+ * @v meta Transfer metadata
+ * @ret rc Return status code
+ */
+static int tftp_mc_socket_deliver_iob ( struct xfer_interface *mc_socket,
+ struct io_buffer *iobuf,
+ struct xfer_metadata *meta ) {
+ struct tftp_request *tftp =
+ container_of ( mc_socket, struct tftp_request, mc_socket );
+
+ return tftp_rx ( tftp, iobuf, meta );
+}
+
+/** TFTP multicast socket operations */
+static struct xfer_interface_operations tftp_mc_socket_operations = {
+ .close = ignore_xfer_close,
+ .vredirect = xfer_vreopen,
+ .window = unlimited_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = tftp_mc_socket_deliver_iob,
+ .deliver_raw = xfer_deliver_as_iob,
+};
+
+/**
+ * Close TFTP data transfer interface
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct tftp_request *tftp =
+ container_of ( xfer, struct tftp_request, xfer );
+
+ DBGC ( tftp, "TFTP %p interface closed: %s\n",
+ tftp, strerror ( rc ) );
+
+ tftp_done ( tftp, rc );
+}
+
+/**
+ * Check flow control window
+ *
+ * @v xfer Data transfer interface
+ * @ret len Length of window
+ */
+static size_t tftp_xfer_window ( struct xfer_interface *xfer ) {
+ struct tftp_request *tftp =
+ container_of ( xfer, struct tftp_request, xfer );
+
+ /* We abuse this data-xfer method to convey the blocksize to
+ * the caller. This really should be done using some kind of
+ * stat() method, but we don't yet have the facility to do
+ * that.
+ */
+ return tftp->blksize;
+}
+
+/** TFTP data transfer interface operations */
+static struct xfer_interface_operations tftp_xfer_operations = {
+ .close = tftp_xfer_close,
+ .vredirect = ignore_xfer_vredirect,
+ .window = tftp_xfer_window,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = ignore_xfer_deliver_raw,
+};
+
+/**
+ * Initiate TFTP/TFTM/MTFTP download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftp_core_open ( struct xfer_interface *xfer, struct uri *uri,
+ unsigned int default_port,
+ struct sockaddr *multicast,
+ unsigned int flags ) {
+ struct tftp_request *tftp;
+ int rc;
+
+ /* Sanity checks */
+ if ( ! uri->host )
+ return -EINVAL;
+ if ( ! uri->path )
+ return -EINVAL;
+
+ /* Allocate and populate TFTP structure */
+ tftp = zalloc ( sizeof ( *tftp ) );
+ if ( ! tftp )
+ return -ENOMEM;
+ tftp->refcnt.free = tftp_free;
+ xfer_init ( &tftp->xfer, &tftp_xfer_operations, &tftp->refcnt );
+ tftp->uri = uri_get ( uri );
+ xfer_init ( &tftp->socket, &tftp_socket_operations, &tftp->refcnt );
+ xfer_init ( &tftp->mc_socket, &tftp_mc_socket_operations,
+ &tftp->refcnt );
+ tftp->blksize = TFTP_DEFAULT_BLKSIZE;
+ tftp->flags = flags;
+ tftp->timer.expired = tftp_timer_expired;
+
+ /* Open socket */
+ tftp->port = uri_port ( tftp->uri, default_port );
+ if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
+ goto err;
+
+ /* Open multicast socket */
+ if ( multicast ) {
+ if ( ( rc = tftp_reopen_mc ( tftp, multicast ) ) != 0 )
+ goto err;
+ }
+
+ /* Start timer to initiate RRQ */
+ start_timer_nodelay ( &tftp->timer );
+
+ /* Attach to parent interface, mortalise self, and return */
+ xfer_plug_plug ( &tftp->xfer, xfer );
+ ref_put ( &tftp->refcnt );
+ return 0;
+
+ err:
+ DBGC ( tftp, "TFTP %p could not create request: %s\n",
+ tftp, strerror ( rc ) );
+ tftp_done ( tftp, rc );
+ ref_put ( &tftp->refcnt );
+ return rc;
+}
+
+/**
+ * Initiate TFTP download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
+ TFTP_FL_RRQ_SIZES );
+
+}
+
+/** TFTP URI opener */
+struct uri_opener tftp_uri_opener __uri_opener = {
+ .scheme = "tftp",
+ .open = tftp_open,
+};
+
+/**
+ * Initiate TFTM download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int tftm_open ( struct xfer_interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
+ ( TFTP_FL_RRQ_SIZES |
+ TFTP_FL_RRQ_MULTICAST ) );
+
+}
+
+/** TFTM URI opener */
+struct uri_opener tftm_uri_opener __uri_opener = {
+ .scheme = "tftm",
+ .open = tftm_open,
+};
+
+/**
+ * Initiate MTFTP download
+ *
+ * @v xfer Data transfer interface
+ * @v uri Uniform Resource Identifier
+ * @ret rc Return status code
+ */
+static int mtftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
+ return tftp_core_open ( xfer, uri, MTFTP_PORT,
+ ( struct sockaddr * ) &tftp_mtftp_socket,
+ TFTP_FL_MTFTP_RECOVERY );
+}
+
+/** MTFTP URI opener */
+struct uri_opener mtftp_uri_opener __uri_opener = {
+ .scheme = "mtftp",
+ .open = mtftp_open,
+};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** TFTP server setting */
+struct setting next_server_setting __setting = {
+ .name = "next-server",
+ .description = "TFTP server",
+ .tag = DHCP_EB_SIADDR,
+ .type = &setting_type_ipv4,
+};
+
+/**
+ * Apply TFTP configuration settings
+ *
+ * @ret rc Return status code
+ */
+static int tftp_apply_settings ( void ) {
+ static struct in_addr tftp_server = { 0 };
+ struct in_addr last_tftp_server;
+ char uri_string[32];
+ struct uri *uri;
+
+ /* Retrieve TFTP server setting */
+ last_tftp_server = tftp_server;
+ fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
+
+ /* If TFTP server setting has changed, set the current working
+ * URI to match. Do it only when the TFTP server has changed
+ * to try to minimise surprises to the user, who probably
+ * won't expect the CWURI to change just because they updated
+ * an unrelated setting and triggered all the settings
+ * applicators.
+ */
+ if ( tftp_server.s_addr != last_tftp_server.s_addr ) {
+ snprintf ( uri_string, sizeof ( uri_string ),
+ "tftp://%s/", inet_ntoa ( tftp_server ) );
+ uri = parse_uri ( uri_string );
+ if ( ! uri )
+ return -ENOMEM;
+ churi ( uri );
+ uri_put ( uri );
+ }
+
+ return 0;
+}
+
+/** TFTP settings applicator */
+struct settings_applicator tftp_settings_applicator __settings_applicator = {
+ .apply = tftp_apply_settings,
+};
diff --git a/debian/grub-extras/disabled/gpxe/wrap/nic.c b/debian/grub-extras/disabled/gpxe/wrap/nic.c
new file mode 100644
index 0000000..05a3b89
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/wrap/nic.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <gpxe/pci.h>
+#include <grub/misc.h>
+
+/* Helper for grub_gpxe_register_pci_nic. */
+static int
+grub_gpxe_pci_nic_init (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+{
+ struct pci_driver *nic = data;
+ unsigned i;
+
+ for (i = 0; i < nic->id_count; i++)
+ {
+ int err;
+ if (nic->ids[i].devid == pciid)
+ {
+ struct pci_device *pci;
+ struct pci_device_id *id;
+ int reg;
+
+ grub_dprintf ("gpxe", "Attaching NIC %d:%d.%d\n",
+ grub_pci_get_bus (dev),
+ grub_pci_get_device (dev),
+ grub_pci_get_function (dev));
+ pci = grub_malloc (sizeof (*pci));
+ if (!pci)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ id = grub_malloc (sizeof (*id));
+ if (!id)
+ {
+ grub_free (pci);
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ id->devid = pciid;
+ pci->dev.desc.bus_type = BUS_TYPE_PCI;
+ pci->dev.desc.bus = grub_pci_get_bus (dev);
+ pci->dev.desc.location = (grub_pci_get_device (dev) << 3)
+ | grub_pci_get_function (dev);
+ pci->dev.desc.vendor = pciid & 0xffff;
+ pci->dev.desc.device = pciid >> 16;
+ pci->vendor = pciid & 0xffff;
+ pci->device = pciid >> 16;
+ pci->dev.name = grub_xasprintf ("PCI:%02x:%02x.%x",
+ grub_pci_get_bus (dev),
+ grub_pci_get_device (dev),
+ grub_pci_get_function (dev));
+ pci->dev.pci_dev = dev;
+ pci->priv = 0;
+ pci->drvdata = 0;
+
+ reg = GRUB_PCI_REG_ADDRESSES;
+ while (reg < GRUB_PCI_REG_CIS_POINTER)
+ {
+ grub_uint64_t space;
+ grub_pci_address_t addr;
+
+ addr = grub_pci_make_address (dev, reg);
+ space = grub_pci_read (addr);
+
+ reg += sizeof (grub_uint32_t);
+
+ if (space == 0)
+ continue;
+
+ if ((space & GRUB_PCI_ADDR_SPACE_MASK)
+ == GRUB_PCI_ADDR_SPACE_IO)
+ {
+ pci->ioaddr = space & GRUB_PCI_ADDR_IO_MASK;
+ break;
+ }
+
+ if ((space & GRUB_PCI_ADDR_MEM_TYPE_MASK)
+ == GRUB_PCI_ADDR_MEM_TYPE_64)
+ reg += sizeof (grub_uint32_t);
+ }
+
+ /* No IRQ support yet. */
+ pci->irq = 0;
+ grub_dprintf ("gpxe", "Probing NIC %d:%d.%d\n",
+ grub_pci_get_bus (dev),
+ grub_pci_get_device (dev),
+ grub_pci_get_function (dev));
+ err = nic->probe (pci, id);
+ grub_dprintf ("gpxe", "Nic probe finished with status %d\n", err);
+ }
+ }
+ return 0;
+}
+
+void
+grub_gpxe_register_pci_nic (struct pci_driver *nic)
+{
+ grub_dprintf ("gpxe", "Registering nic\n");
+ grub_pci_iterate (grub_gpxe_pci_nic_init, nic);
+}
+
+/* FIXME: free all resources associated with driver and detach devices. */
+void
+grub_gpxe_unregister_pci_nic (struct pci_driver *nic __attribute__ ((unused)))
+{
+}
diff --git a/debian/grub-extras/disabled/gpxe/wrap/pci.c b/debian/grub-extras/disabled/gpxe/wrap/pci.c
new file mode 100644
index 0000000..90b26c5
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/wrap/pci.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * Based in part on pci.c from Etherboot 5.4, by Ken Yap and David
+ * Munro, in turn based on the Linux kernel's PCI implementation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/tables.h>
+#include <gpxe/device.h>
+#include <gpxe/pci.h>
+
+/**
+ * Enable PCI device
+ *
+ * @v pci PCI device
+ *
+ * Set device to be a busmaster in case BIOS neglected to do so. Also
+ * adjust PCI latency timer to a reasonable value, 32.
+ */
+void adjust_pci_device ( struct pci_device *pci ) {
+ unsigned short new_command, pci_command;
+ unsigned char pci_latency;
+
+ pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
+ new_command = ( pci_command | PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEM | PCI_COMMAND_IO );
+ if ( pci_command != new_command ) {
+ pci_write_config_word ( pci, PCI_COMMAND, new_command );
+ }
+
+ pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
+ if ( pci_latency < 32 ) {
+ pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
+ }
+}
diff --git a/debian/grub-extras/disabled/gpxe/wrap/wrap.c b/debian/grub-extras/disabled/gpxe/wrap/wrap.c
new file mode 100644
index 0000000..691e552
--- /dev/null
+++ b/debian/grub-extras/disabled/gpxe/wrap/wrap.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2009 Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+#include <gpxe/wrap.h>
+#include <gpxe/uaccess.h>
+
+void
+memcpy_user (userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off, size_t len )
+{
+ grub_memcpy ((void *) dest+dest_off, (void *) src+src_off, len);
+}
+
+userptr_t
+virt_to_user (volatile const void *in)
+{
+ return in;
+}
+
+void
+free_memblock (void *ptr, size_t size __attribute__ ((unused)))
+{
+ grub_free (ptr);
+}
+
+void *
+memchr (void *s, grub_uint8_t c, grub_size_t size)
+{
+ for (;size && *(grub_uint8_t *)s != c; size--, s = (grub_uint8_t *)s + 1);
+ if (size)
+ return s;
+ return NULL;
+}
+
+grub_size_t
+strnlen (char *str, grub_size_t n)
+{
+ grub_size_t r = 0;
+ while (*str && n)
+ {
+ str++;
+ n--;
+ r++;
+ }
+ return r;
+}
diff --git a/debian/grub-extras/disabled/zfs/COPYING b/debian/grub-extras/disabled/zfs/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/debian/grub-extras/disabled/zfs/Makefile.common b/debian/grub-extras/disabled/zfs/Makefile.common
new file mode 100644
index 0000000..8c8f801
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/Makefile.common
@@ -0,0 +1 @@
+ZFS_CPPFLAGS = -I$(top_srcdir)/contrib/zfs/include
diff --git a/debian/grub-extras/disabled/zfs/Makefile.core.def b/debian/grub-extras/disabled/zfs/Makefile.core.def
new file mode 100644
index 0000000..5c63114
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/Makefile.core.def
@@ -0,0 +1,16 @@
+AutoGen definitions Makefile.tpl;
+
+module = {
+ name = zfs;
+ common = contrib/zfs/zfs.c;
+ common = contrib/zfs/zfs_lzjb.c;
+ common = contrib/zfs/zfs_sha256.c;
+ common = contrib/zfs/zfs_fletcher.c;
+ cppflags = '$(ZFS_CPPFLAGS)';
+};
+
+module = {
+ name = zfsinfo;
+ common = contrib/zfs/zfsinfo.c;
+ cppflags = '$(ZFS_CPPFLAGS)';
+};
diff --git a/debian/grub-extras/disabled/zfs/Makefile.util.def b/debian/grub-extras/disabled/zfs/Makefile.util.def
new file mode 100644
index 0000000..f3215f2
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/Makefile.util.def
@@ -0,0 +1,10 @@
+AutoGen definitions Makefile.tpl;
+
+library = {
+ name = libgrubmods.a;
+ common = contrib/zfs/zfs.c;
+ common = contrib/zfs/zfs_lzjb.c;
+ common = contrib/zfs/zfs_sha256.c;
+ common = contrib/zfs/zfs_fletcher.c;
+ cppflags = '$(ZFS_CPPFLAGS)';
+};
diff --git a/debian/grub-extras/disabled/zfs/README b/debian/grub-extras/disabled/zfs/README
new file mode 100644
index 0000000..874bd08
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/README
@@ -0,0 +1,11 @@
+
+grub-extras is meant to be used as an overlay on grub2 source tree.
+
+Build instructions:
+
+ - Copy grub-extras in a subdirectory of your grub2 checkout.
+ For example, "grub-extras".
+
+ - Export GRUB_CONTRIB environment variable to point to this directory.
+
+ - Build GRUB as usual.
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/dmu.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/dmu.h
new file mode 100644
index 0000000..7faa708
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/dmu.h
@@ -0,0 +1,120 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DMU_H
+#define _SYS_DMU_H
+
+/*
+ * This file describes the interface that the DMU provides for its
+ * consumers.
+ *
+ * The DMU also interacts with the SPA. That interface is described in
+ * dmu_spa.h.
+ */
+typedef enum dmu_object_type {
+ DMU_OT_NONE,
+ /* general: */
+ DMU_OT_OBJECT_DIRECTORY, /* ZAP */
+ DMU_OT_OBJECT_ARRAY, /* UINT64 */
+ DMU_OT_PACKED_NVLIST, /* UINT8 (XDR by nvlist_pack/unpack) */
+ DMU_OT_PACKED_NVLIST_SIZE, /* UINT64 */
+ DMU_OT_BPLIST, /* UINT64 */
+ DMU_OT_BPLIST_HDR, /* UINT64 */
+ /* spa: */
+ DMU_OT_SPACE_MAP_HEADER, /* UINT64 */
+ DMU_OT_SPACE_MAP, /* UINT64 */
+ /* zil: */
+ DMU_OT_INTENT_LOG, /* UINT64 */
+ /* dmu: */
+ DMU_OT_DNODE, /* DNODE */
+ DMU_OT_OBJSET, /* OBJSET */
+ /* dsl: */
+ DMU_OT_DSL_DIR, /* UINT64 */
+ DMU_OT_DSL_DIR_CHILD_MAP, /* ZAP */
+ DMU_OT_DSL_DS_SNAP_MAP, /* ZAP */
+ DMU_OT_DSL_PROPS, /* ZAP */
+ DMU_OT_DSL_DATASET, /* UINT64 */
+ /* zpl: */
+ DMU_OT_ZNODE, /* ZNODE */
+ DMU_OT_OLDACL, /* OLD ACL */
+ DMU_OT_PLAIN_FILE_CONTENTS, /* UINT8 */
+ DMU_OT_DIRECTORY_CONTENTS, /* ZAP */
+ DMU_OT_MASTER_NODE, /* ZAP */
+ DMU_OT_UNLINKED_SET, /* ZAP */
+ /* zvol: */
+ DMU_OT_ZVOL, /* UINT8 */
+ DMU_OT_ZVOL_PROP, /* ZAP */
+ /* other; for testing only! */
+ DMU_OT_PLAIN_OTHER, /* UINT8 */
+ DMU_OT_UINT64_OTHER, /* UINT64 */
+ DMU_OT_ZAP_OTHER, /* ZAP */
+ /* new object types: */
+ DMU_OT_ERROR_LOG, /* ZAP */
+ DMU_OT_SPA_HISTORY, /* UINT8 */
+ DMU_OT_SPA_HISTORY_OFFSETS, /* spa_his_phys_t */
+ DMU_OT_POOL_PROPS, /* ZAP */
+ DMU_OT_DSL_PERMS, /* ZAP */
+ DMU_OT_ACL, /* ACL */
+ DMU_OT_SYSACL, /* SYSACL */
+ DMU_OT_FUID, /* FUID table (Packed NVLIST UINT8) */
+ DMU_OT_FUID_SIZE, /* FUID table size UINT64 */
+ DMU_OT_NEXT_CLONES, /* ZAP */
+ DMU_OT_SCRUB_QUEUE, /* ZAP */
+ DMU_OT_USERGROUP_USED, /* ZAP */
+ DMU_OT_USERGROUP_QUOTA, /* ZAP */
+ DMU_OT_USERREFS, /* ZAP */
+ DMU_OT_DDT_ZAP, /* ZAP */
+ DMU_OT_DDT_STATS, /* ZAP */
+ DMU_OT_SA, /* System attr */
+ DMU_OT_SA_MASTER_NODE, /* ZAP */
+ DMU_OT_SA_ATTR_REGISTRATION, /* ZAP */
+ DMU_OT_SA_ATTR_LAYOUTS, /* ZAP */
+ DMU_OT_NUMTYPES
+} dmu_object_type_t;
+
+typedef enum dmu_objset_type {
+ DMU_OST_NONE,
+ DMU_OST_META,
+ DMU_OST_ZFS,
+ DMU_OST_ZVOL,
+ DMU_OST_OTHER, /* For testing only! */
+ DMU_OST_ANY, /* Be careful! */
+ DMU_OST_NUMTYPES
+} dmu_objset_type_t;
+
+/*
+ * The names of zap entries in the DIRECTORY_OBJECT of the MOS.
+ */
+#define DMU_POOL_DIRECTORY_OBJECT 1
+#define DMU_POOL_CONFIG "config"
+#define DMU_POOL_ROOT_DATASET "root_dataset"
+#define DMU_POOL_SYNC_BPLIST "sync_bplist"
+#define DMU_POOL_ERRLOG_SCRUB "errlog_scrub"
+#define DMU_POOL_ERRLOG_LAST "errlog_last"
+#define DMU_POOL_SPARES "spares"
+#define DMU_POOL_DEFLATE "deflate"
+#define DMU_POOL_HISTORY "history"
+#define DMU_POOL_PROPS "pool_props"
+#define DMU_POOL_L2CACHE "l2cache"
+
+#endif /* _SYS_DMU_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/dmu_objset.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/dmu_objset.h
new file mode 100644
index 0000000..aa1f4ab
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/dmu_objset.h
@@ -0,0 +1,44 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright (C) 2010 Robert Millan <rmh@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DMU_OBJSET_H
+#define _SYS_DMU_OBJSET_H
+
+#include <grub/zfs/zil.h>
+
+#define OBJSET_PHYS_SIZE 2048
+#define OBJSET_PHYS_SIZE_V14 1024
+
+typedef struct objset_phys {
+ dnode_phys_t os_meta_dnode;
+ zil_header_t os_zil_header;
+ grub_uint64_t os_type;
+ grub_uint64_t os_flags;
+ char os_pad[OBJSET_PHYS_SIZE - sizeof (dnode_phys_t)*3 -
+ sizeof (zil_header_t) - sizeof (grub_uint64_t)*2];
+ dnode_phys_t os_userused_dnode;
+ dnode_phys_t os_groupused_dnode;
+} objset_phys_t;
+
+#endif /* _SYS_DMU_OBJSET_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/dnode.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/dnode.h
new file mode 100644
index 0000000..6b0e184
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/dnode.h
@@ -0,0 +1,81 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DNODE_H
+#define _SYS_DNODE_H
+
+#include <grub/zfs/spa.h>
+
+/*
+ * Fixed constants.
+ */
+#define DNODE_SHIFT 9 /* 512 bytes */
+#define DN_MIN_INDBLKSHIFT 10 /* 1k */
+#define DN_MAX_INDBLKSHIFT 14 /* 16k */
+#define DNODE_BLOCK_SHIFT 14 /* 16k */
+#define DNODE_CORE_SIZE 64 /* 64 bytes for dnode sans blkptrs */
+#define DN_MAX_OBJECT_SHIFT 48 /* 256 trillion (zfs_fid_t limit) */
+#define DN_MAX_OFFSET_SHIFT 64 /* 2^64 bytes in a dnode */
+
+/*
+ * Derived constants.
+ */
+#define DNODE_SIZE (1 << DNODE_SHIFT)
+#define DN_MAX_NBLKPTR ((DNODE_SIZE - DNODE_CORE_SIZE) >> SPA_BLKPTRSHIFT)
+#define DN_MAX_BONUSLEN (DNODE_SIZE - DNODE_CORE_SIZE - (1 << SPA_BLKPTRSHIFT))
+#define DN_MAX_OBJECT (1ULL << DN_MAX_OBJECT_SHIFT)
+
+#define DNODES_PER_BLOCK_SHIFT (DNODE_BLOCK_SHIFT - DNODE_SHIFT)
+#define DNODES_PER_BLOCK (1ULL << DNODES_PER_BLOCK_SHIFT)
+#define DNODES_PER_LEVEL_SHIFT (DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT)
+
+#define DNODE_FLAG_SPILL_BLKPTR (1<<2)
+
+#define DN_BONUS(dnp) ((void*)((dnp)->dn_bonus + \
+ (((dnp)->dn_nblkptr - 1) * sizeof (blkptr_t))))
+
+typedef struct dnode_phys {
+ grub_uint8_t dn_type; /* dmu_object_type_t */
+ grub_uint8_t dn_indblkshift; /* ln2(indirect block size) */
+ grub_uint8_t dn_nlevels; /* 1=dn_blkptr->data blocks */
+ grub_uint8_t dn_nblkptr; /* length of dn_blkptr */
+ grub_uint8_t dn_bonustype; /* type of data in bonus buffer */
+ grub_uint8_t dn_checksum; /* ZIO_CHECKSUM type */
+ grub_uint8_t dn_compress; /* ZIO_COMPRESS type */
+ grub_uint8_t dn_flags; /* DNODE_FLAG_* */
+ grub_uint16_t dn_datablkszsec; /* data block size in 512b sectors */
+ grub_uint16_t dn_bonuslen; /* length of dn_bonus */
+ grub_uint8_t dn_pad2[4];
+
+ /* accounting is protected by dn_dirty_mtx */
+ grub_uint64_t dn_maxblkid; /* largest allocated block ID */
+ grub_uint64_t dn_used; /* bytes (or sectors) of disk space */
+
+ grub_uint64_t dn_pad3[4];
+
+ blkptr_t dn_blkptr[1];
+ grub_uint8_t dn_bonus[DN_MAX_BONUSLEN - sizeof (blkptr_t)];
+ blkptr_t dn_spill;
+} dnode_phys_t;
+
+#endif /* _SYS_DNODE_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dataset.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dataset.h
new file mode 100644
index 0000000..de0dc54
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dataset.h
@@ -0,0 +1,53 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DSL_DATASET_H
+#define _SYS_DSL_DATASET_H
+
+typedef struct dsl_dataset_phys {
+ grub_uint64_t ds_dir_obj;
+ grub_uint64_t ds_prev_snap_obj;
+ grub_uint64_t ds_prev_snap_txg;
+ grub_uint64_t ds_next_snap_obj;
+ grub_uint64_t ds_snapnames_zapobj; /* zap obj of snaps; ==0 for snaps */
+ grub_uint64_t ds_num_children; /* clone/snap children; ==0 for head */
+ grub_uint64_t ds_creation_time; /* seconds since 1970 */
+ grub_uint64_t ds_creation_txg;
+ grub_uint64_t ds_deadlist_obj;
+ grub_uint64_t ds_used_bytes;
+ grub_uint64_t ds_compressed_bytes;
+ grub_uint64_t ds_uncompressed_bytes;
+ grub_uint64_t ds_unique_bytes; /* only relevant to snapshots */
+ /*
+ * The ds_fsid_guid is a 56-bit ID that can change to avoid
+ * collisions. The ds_guid is a 64-bit ID that will never
+ * change, so there is a small probability that it will collide.
+ */
+ grub_uint64_t ds_fsid_guid;
+ grub_uint64_t ds_guid;
+ grub_uint64_t ds_flags;
+ blkptr_t ds_bp;
+ grub_uint64_t ds_pad[8]; /* pad out to 320 bytes for good measure */
+} dsl_dataset_phys_t;
+
+#endif /* _SYS_DSL_DATASET_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dir.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dir.h
new file mode 100644
index 0000000..717f359
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/dsl_dir.h
@@ -0,0 +1,49 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DSL_DIR_H
+#define _SYS_DSL_DIR_H
+
+typedef struct dsl_dir_phys {
+ grub_uint64_t dd_creation_time; /* not actually used */
+ grub_uint64_t dd_head_dataset_obj;
+ grub_uint64_t dd_parent_obj;
+ grub_uint64_t dd_clone_parent_obj;
+ grub_uint64_t dd_child_dir_zapobj;
+ /*
+ * how much space our children are accounting for; for leaf
+ * datasets, == physical space used by fs + snaps
+ */
+ grub_uint64_t dd_used_bytes;
+ grub_uint64_t dd_compressed_bytes;
+ grub_uint64_t dd_uncompressed_bytes;
+ /* Administrative quota setting */
+ grub_uint64_t dd_quota;
+ /* Administrative reservation setting */
+ grub_uint64_t dd_reserved;
+ grub_uint64_t dd_props_zapobj;
+ grub_uint64_t dd_deleg_zapobj; /* dataset permissions */
+ grub_uint64_t dd_pad[20]; /* pad out to 256 bytes for good measure */
+} dsl_dir_phys_t;
+
+#endif /* _SYS_DSL_DIR_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/sa_impl.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/sa_impl.h
new file mode 100644
index 0000000..8aa6e2e
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/sa_impl.h
@@ -0,0 +1,35 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _SYS_SA_IMPL_H
+#define _SYS_SA_IMPL_H
+
+typedef struct sa_hdr_phys {
+ grub_uint32_t sa_magic;
+ grub_uint16_t sa_layout_info;
+ grub_uint16_t sa_lengths[1];
+} sa_hdr_phys_t;
+
+#define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0)
+#define SA_SIZE_OFFSET 0x8
+
+#endif /* _SYS_SA_IMPL_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/spa.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/spa.h
new file mode 100644
index 0000000..36b8e67
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/spa.h
@@ -0,0 +1,312 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright 2010 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_ZFS_SPA_HEADER
+#define GRUB_ZFS_SPA_HEADER 1
+
+typedef enum grub_zfs_endian
+ {
+ UNKNOWN_ENDIAN = -2,
+ LITTLE_ENDIAN = -1,
+ BIG_ENDIAN = 0
+ } grub_zfs_endian_t;
+
+#define grub_zfs_to_cpu16(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu16(x) \
+ : grub_le_to_cpu16(x))
+#define grub_cpu_to_zfs16(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be16(x) \
+ : grub_cpu_to_le16(x))
+
+#define grub_zfs_to_cpu32(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu32(x) \
+ : grub_le_to_cpu32(x))
+#define grub_cpu_to_zfs32(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be32(x) \
+ : grub_cpu_to_le32(x))
+
+#define grub_zfs_to_cpu64(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu64(x) \
+ : grub_le_to_cpu64(x))
+#define grub_cpu_to_zfs64(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be64(x) \
+ : grub_cpu_to_le64(x))
+
+/*
+ * General-purpose 32-bit and 64-bit bitfield encodings.
+ */
+#define BF32_DECODE(x, low, len) P2PHASE((x) >> (low), 1U << (len))
+#define BF64_DECODE(x, low, len) P2PHASE((x) >> (low), 1ULL << (len))
+#define BF32_ENCODE(x, low, len) (P2PHASE((x), 1U << (len)) << (low))
+#define BF64_ENCODE(x, low, len) (P2PHASE((x), 1ULL << (len)) << (low))
+
+#define BF32_GET(x, low, len) BF32_DECODE(x, low, len)
+#define BF64_GET(x, low, len) BF64_DECODE(x, low, len)
+
+#define BF32_SET(x, low, len, val) \
+ ((x) ^= BF32_ENCODE((x >> low) ^ (val), low, len))
+#define BF64_SET(x, low, len, val) \
+ ((x) ^= BF64_ENCODE((x >> low) ^ (val), low, len))
+
+#define BF32_GET_SB(x, low, len, shift, bias) \
+ ((BF32_GET(x, low, len) + (bias)) << (shift))
+#define BF64_GET_SB(x, low, len, shift, bias) \
+ ((BF64_GET(x, low, len) + (bias)) << (shift))
+
+#define BF32_SET_SB(x, low, len, shift, bias, val) \
+ BF32_SET(x, low, len, ((val) >> (shift)) - (bias))
+#define BF64_SET_SB(x, low, len, shift, bias, val) \
+ BF64_SET(x, low, len, ((val) >> (shift)) - (bias))
+
+/*
+ * We currently support nine block sizes, from 512 bytes to 128K.
+ * We could go higher, but the benefits are near-zero and the cost
+ * of COWing a giant block to modify one byte would become excessive.
+ */
+#define SPA_MINBLOCKSHIFT 9
+#define SPA_MAXBLOCKSHIFT 17
+#define SPA_MINBLOCKSIZE (1ULL << SPA_MINBLOCKSHIFT)
+#define SPA_MAXBLOCKSIZE (1ULL << SPA_MAXBLOCKSHIFT)
+
+#define SPA_BLOCKSIZES (SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT + 1)
+
+/*
+ * Size of block to hold the configuration data (a packed nvlist)
+ */
+#define SPA_CONFIG_BLOCKSIZE (1 << 14)
+
+/*
+ * The DVA size encodings for LSIZE and PSIZE support blocks up to 32MB.
+ * The ASIZE encoding should be at least 64 times larger (6 more bits)
+ * to support up to 4-way RAID-Z mirror mode with worst-case gang block
+ * overhead, three DVAs per bp, plus one more bit in case we do anything
+ * else that expands the ASIZE.
+ */
+#define SPA_LSIZEBITS 16 /* LSIZE up to 32M (2^16 * 512) */
+#define SPA_PSIZEBITS 16 /* PSIZE up to 32M (2^16 * 512) */
+#define SPA_ASIZEBITS 24 /* ASIZE up to 64 times larger */
+
+/*
+ * All SPA data is represented by 128-bit data virtual addresses (DVAs).
+ * The members of the dva_t should be considered opaque outside the SPA.
+ */
+typedef struct dva {
+ grub_uint64_t dva_word[2];
+} dva_t;
+
+/*
+ * Each block has a 256-bit checksum -- strong enough for cryptographic hashes.
+ */
+typedef struct zio_cksum {
+ grub_uint64_t zc_word[4];
+} zio_cksum_t;
+
+/*
+ * Each block is described by its DVAs, time of birth, checksum, etc.
+ * The word-by-word, bit-by-bit layout of the blkptr is as follows:
+ *
+ * 64 56 48 40 32 24 16 8 0
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 0 | vdev1 | GRID | ASIZE |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 1 |G| offset1 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 2 | vdev2 | GRID | ASIZE |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 3 |G| offset2 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 4 | vdev3 | GRID | ASIZE |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 5 |G| offset3 |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 6 |BDX|lvl| type | cksum | comp | PSIZE | LSIZE |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 7 | padding |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 8 | padding |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * 9 | physical birth txg |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * a | logical birth txg |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * b | fill count |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * c | checksum[0] |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * d | checksum[1] |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * e | checksum[2] |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * f | checksum[3] |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * Legend:
+ *
+ * vdev virtual device ID
+ * offset offset into virtual device
+ * LSIZE logical size
+ * PSIZE physical size (after compression)
+ * ASIZE allocated size (including RAID-Z parity and gang block headers)
+ * GRID RAID-Z layout information (reserved for future use)
+ * cksum checksum function
+ * comp compression function
+ * G gang block indicator
+ * B byteorder (endianness)
+ * D dedup
+ * X unused
+ * lvl level of indirection
+ * type DMU object type
+ * phys birth txg of block allocation; zero if same as logical birth txg
+ * log. birth transaction group in which the block was logically born
+ * fill count number of non-zero blocks under this bp
+ * checksum[4] 256-bit checksum of the data this bp describes
+ */
+#define SPA_BLKPTRSHIFT 7 /* blkptr_t is 128 bytes */
+#define SPA_DVAS_PER_BP 3 /* Number of DVAs in a bp */
+
+typedef struct blkptr {
+ dva_t blk_dva[SPA_DVAS_PER_BP]; /* Data Virtual Addresses */
+ grub_uint64_t blk_prop; /* size, compression, type, etc */
+ grub_uint64_t blk_pad[2]; /* Extra space for the future */
+ grub_uint64_t blk_phys_birth; /* txg when block was allocated */
+ grub_uint64_t blk_birth; /* transaction group at birth */
+ grub_uint64_t blk_fill; /* fill count */
+ zio_cksum_t blk_cksum; /* 256-bit checksum */
+} blkptr_t;
+
+/*
+ * Macros to get and set fields in a bp or DVA.
+ */
+#define DVA_GET_ASIZE(dva) \
+ BF64_GET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0)
+#define DVA_SET_ASIZE(dva, x) \
+ BF64_SET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0, x)
+
+#define DVA_GET_GRID(dva) BF64_GET((dva)->dva_word[0], 24, 8)
+#define DVA_SET_GRID(dva, x) BF64_SET((dva)->dva_word[0], 24, 8, x)
+
+#define DVA_GET_VDEV(dva) BF64_GET((dva)->dva_word[0], 32, 32)
+#define DVA_SET_VDEV(dva, x) BF64_SET((dva)->dva_word[0], 32, 32, x)
+
+#define DVA_GET_GANG(dva) BF64_GET((dva)->dva_word[1], 63, 1)
+#define DVA_SET_GANG(dva, x) BF64_SET((dva)->dva_word[1], 63, 1, x)
+
+#define BP_GET_LSIZE(bp) \
+ BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
+#define BP_SET_LSIZE(bp, x) \
+ BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
+
+#define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 8)
+#define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 8, x)
+
+#define BP_GET_CHECKSUM(bp) BF64_GET((bp)->blk_prop, 40, 8)
+#define BP_SET_CHECKSUM(bp, x) BF64_SET((bp)->blk_prop, 40, 8, x)
+
+#define BP_GET_TYPE(bp) BF64_GET((bp)->blk_prop, 48, 8)
+#define BP_SET_TYPE(bp, x) BF64_SET((bp)->blk_prop, 48, 8, x)
+
+#define BP_GET_LEVEL(bp) BF64_GET((bp)->blk_prop, 56, 5)
+#define BP_SET_LEVEL(bp, x) BF64_SET((bp)->blk_prop, 56, 5, x)
+
+#define BP_GET_PROP_BIT_61(bp) BF64_GET((bp)->blk_prop, 61, 1)
+#define BP_SET_PROP_BIT_61(bp, x) BF64_SET((bp)->blk_prop, 61, 1, x)
+
+#define BP_GET_DEDUP(bp) BF64_GET((bp)->blk_prop, 62, 1)
+#define BP_SET_DEDUP(bp, x) BF64_SET((bp)->blk_prop, 62, 1, x)
+
+#define BP_GET_BYTEORDER(bp) (0 - BF64_GET((bp)->blk_prop, 63, 1))
+#define BP_SET_BYTEORDER(bp, x) BF64_SET((bp)->blk_prop, 63, 1, x)
+
+#define BP_PHYSICAL_BIRTH(bp) \
+ ((bp)->blk_phys_birth ? (bp)->blk_phys_birth : (bp)->blk_birth)
+
+#define BP_SET_BIRTH(bp, logical, physical) \
+{ \
+ (bp)->blk_birth = (logical); \
+ (bp)->blk_phys_birth = ((logical) == (physical) ? 0 : (physical)); \
+}
+
+#define BP_GET_ASIZE(bp) \
+ (DVA_GET_ASIZE(&(bp)->blk_dva[0]) + DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \
+ DVA_GET_ASIZE(&(bp)->blk_dva[2]))
+
+#define BP_GET_UCSIZE(bp) \
+ ((BP_GET_LEVEL(bp) > 0 || dmu_ot[BP_GET_TYPE(bp)].ot_metadata) ? \
+ BP_GET_PSIZE(bp) : BP_GET_LSIZE(bp));
+
+#define BP_GET_NDVAS(bp) \
+ (!!DVA_GET_ASIZE(&(bp)->blk_dva[0]) + \
+ !!DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \
+ !!DVA_GET_ASIZE(&(bp)->blk_dva[2]))
+
+#define BP_COUNT_GANG(bp) \
+ (DVA_GET_GANG(&(bp)->blk_dva[0]) + \
+ DVA_GET_GANG(&(bp)->blk_dva[1]) + \
+ DVA_GET_GANG(&(bp)->blk_dva[2]))
+
+#define DVA_EQUAL(dva1, dva2) \
+ ((dva1)->dva_word[1] == (dva2)->dva_word[1] && \
+ (dva1)->dva_word[0] == (dva2)->dva_word[0])
+
+#define BP_EQUAL(bp1, bp2) \
+ (BP_PHYSICAL_BIRTH(bp1) == BP_PHYSICAL_BIRTH(bp2) && \
+ DVA_EQUAL(&(bp1)->blk_dva[0], &(bp2)->blk_dva[0]) && \
+ DVA_EQUAL(&(bp1)->blk_dva[1], &(bp2)->blk_dva[1]) && \
+ DVA_EQUAL(&(bp1)->blk_dva[2], &(bp2)->blk_dva[2]))
+
+#define ZIO_CHECKSUM_EQUAL(zc1, zc2) \
+ (0 == (((zc1).zc_word[0] - (zc2).zc_word[0]) | \
+ ((zc1).zc_word[1] - (zc2).zc_word[1]) | \
+ ((zc1).zc_word[2] - (zc2).zc_word[2]) | \
+ ((zc1).zc_word[3] - (zc2).zc_word[3])))
+
+#define DVA_IS_VALID(dva) (DVA_GET_ASIZE(dva) != 0)
+
+#define ZIO_SET_CHECKSUM(zcp, w0, w1, w2, w3) \
+{ \
+ (zcp)->zc_word[0] = w0; \
+ (zcp)->zc_word[1] = w1; \
+ (zcp)->zc_word[2] = w2; \
+ (zcp)->zc_word[3] = w3; \
+}
+
+#define BP_IDENTITY(bp) (&(bp)->blk_dva[0])
+#define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp))
+#define BP_IS_HOLE(bp) ((bp)->blk_birth == 0)
+
+/* BP_IS_RAIDZ(bp) assumes no block compression */
+#define BP_IS_RAIDZ(bp) (DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \
+ BP_GET_PSIZE(bp))
+
+#define BP_ZERO(bp) \
+{ \
+ (bp)->blk_dva[0].dva_word[0] = 0; \
+ (bp)->blk_dva[0].dva_word[1] = 0; \
+ (bp)->blk_dva[1].dva_word[0] = 0; \
+ (bp)->blk_dva[1].dva_word[1] = 0; \
+ (bp)->blk_dva[2].dva_word[0] = 0; \
+ (bp)->blk_dva[2].dva_word[1] = 0; \
+ (bp)->blk_prop = 0; \
+ (bp)->blk_pad[0] = 0; \
+ (bp)->blk_pad[1] = 0; \
+ (bp)->blk_phys_birth = 0; \
+ (bp)->blk_birth = 0; \
+ (bp)->blk_fill = 0; \
+ ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0); \
+}
+
+#define BP_SPRINTF_LEN 320
+
+#endif /* ! GRUB_ZFS_SPA_HEADER */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/uberblock_impl.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/uberblock_impl.h
new file mode 100644
index 0000000..9afc565
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/uberblock_impl.h
@@ -0,0 +1,61 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_UBERBLOCK_IMPL_H
+#define _SYS_UBERBLOCK_IMPL_H
+
+/*
+ * The uberblock version is incremented whenever an incompatible on-disk
+ * format change is made to the SPA, DMU, or ZAP.
+ *
+ * Note: the first two fields should never be moved. When a storage pool
+ * is opened, the uberblock must be read off the disk before the version
+ * can be checked. If the ub_version field is moved, we may not detect
+ * version mismatch. If the ub_magic field is moved, applications that
+ * expect the magic number in the first word won't work.
+ */
+#define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */
+#define UBERBLOCK_SHIFT 10 /* up to 1K */
+
+typedef struct uberblock {
+ grub_uint64_t ub_magic; /* UBERBLOCK_MAGIC */
+ grub_uint64_t ub_version; /* ZFS_VERSION */
+ grub_uint64_t ub_txg; /* txg of last sync */
+ grub_uint64_t ub_guid_sum; /* sum of all vdev guids */
+ grub_uint64_t ub_timestamp; /* UTC time of last sync */
+ blkptr_t ub_rootbp; /* MOS objset_phys_t */
+} uberblock_t;
+
+#define UBERBLOCK_SIZE (1ULL << UBERBLOCK_SHIFT)
+#define VDEV_UBERBLOCK_SHIFT UBERBLOCK_SHIFT
+
+/* XXX Uberblock_phys_t is no longer in the kernel zfs */
+typedef struct uberblock_phys {
+ uberblock_t ubp_uberblock;
+ char ubp_pad[UBERBLOCK_SIZE - sizeof (uberblock_t) -
+ sizeof (zio_eck_t)];
+ zio_eck_t ubp_zec;
+} uberblock_phys_t;
+
+
+#endif /* _SYS_UBERBLOCK_IMPL_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/vdev_impl.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/vdev_impl.h
new file mode 100644
index 0000000..6e9002f
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/vdev_impl.h
@@ -0,0 +1,70 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_VDEV_IMPL_H
+#define _SYS_VDEV_IMPL_H
+
+#define VDEV_SKIP_SIZE (8 << 10)
+#define VDEV_BOOT_HEADER_SIZE (8 << 10)
+#define VDEV_PHYS_SIZE (112 << 10)
+#define VDEV_UBERBLOCK_RING (128 << 10)
+
+/* ZFS boot block */
+#define VDEV_BOOT_MAGIC 0x2f5b007b10cULL
+#define VDEV_BOOT_VERSION 1 /* version number */
+
+typedef struct vdev_boot_header {
+ grub_uint64_t vb_magic; /* VDEV_BOOT_MAGIC */
+ grub_uint64_t vb_version; /* VDEV_BOOT_VERSION */
+ grub_uint64_t vb_offset; /* start offset (bytes) */
+ grub_uint64_t vb_size; /* size (bytes) */
+ char vb_pad[VDEV_BOOT_HEADER_SIZE - 4 * sizeof (grub_uint64_t)];
+} vdev_boot_header_t;
+
+typedef struct vdev_phys {
+ char vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_eck_t)];
+ zio_eck_t vp_zbt;
+} vdev_phys_t;
+
+typedef struct vdev_label {
+ char vl_pad[VDEV_SKIP_SIZE]; /* 8K */
+ vdev_boot_header_t vl_boot_header; /* 8K */
+ vdev_phys_t vl_vdev_phys; /* 112K */
+ char vl_uberblock[VDEV_UBERBLOCK_RING]; /* 128K */
+} vdev_label_t; /* 256K total */
+
+/*
+ * Size and offset of embedded boot loader region on each label.
+ * The total size of the first two labels plus the boot area is 4MB.
+ */
+#define VDEV_BOOT_OFFSET (2 * sizeof (vdev_label_t))
+#define VDEV_BOOT_SIZE (7ULL << 19) /* 3.5M */
+
+/*
+ * Size of label regions at the start and end of each leaf device.
+ */
+#define VDEV_LABEL_START_SIZE (2 * sizeof (vdev_label_t) + VDEV_BOOT_SIZE)
+#define VDEV_LABEL_END_SIZE (2 * sizeof (vdev_label_t))
+#define VDEV_LABELS 4
+
+#endif /* _SYS_VDEV_IMPL_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zap_impl.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zap_impl.h
new file mode 100644
index 0000000..b229a06
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zap_impl.h
@@ -0,0 +1,112 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ZAP_IMPL_H
+#define _SYS_ZAP_IMPL_H
+
+#define ZAP_MAGIC 0x2F52AB2ABULL
+
+#define ZAP_HASHBITS 28
+#define MZAP_ENT_LEN 64
+#define MZAP_NAME_LEN (MZAP_ENT_LEN - 8 - 4 - 2)
+#define MZAP_MAX_BLKSHIFT SPA_MAXBLOCKSHIFT
+#define MZAP_MAX_BLKSZ (1 << MZAP_MAX_BLKSHIFT)
+
+typedef struct mzap_ent_phys {
+ grub_uint64_t mze_value;
+ grub_uint32_t mze_cd;
+ grub_uint16_t mze_pad; /* in case we want to chain them someday */
+ char mze_name[MZAP_NAME_LEN];
+} mzap_ent_phys_t;
+
+typedef struct mzap_phys {
+ grub_uint64_t mz_block_type; /* ZBT_MICRO */
+ grub_uint64_t mz_salt;
+ grub_uint64_t mz_pad[6];
+ mzap_ent_phys_t mz_chunk[1];
+ /* actually variable size depending on block size */
+} mzap_phys_t;
+
+/*
+ * The (fat) zap is stored in one object. It is an array of
+ * 1<<FZAP_BLOCK_SHIFT byte blocks. The layout looks like one of:
+ *
+ * ptrtbl fits in first block:
+ * [zap_phys_t zap_ptrtbl_shift < 6] [zap_leaf_t] ...
+ *
+ * ptrtbl too big for first block:
+ * [zap_phys_t zap_ptrtbl_shift >= 6] [zap_leaf_t] [ptrtbl] ...
+ *
+ */
+
+#define ZBT_LEAF ((1ULL << 63) + 0)
+#define ZBT_HEADER ((1ULL << 63) + 1)
+#define ZBT_MICRO ((1ULL << 63) + 3)
+/* any other values are ptrtbl blocks */
+
+/*
+ * the embedded pointer table takes up half a block:
+ * block size / entry size (2^3) / 2
+ */
+#define ZAP_EMBEDDED_PTRTBL_SHIFT(zap) (FZAP_BLOCK_SHIFT(zap) - 3 - 1)
+
+/*
+ * The embedded pointer table starts half-way through the block. Since
+ * the pointer table itself is half the block, it starts at (64-bit)
+ * word number (1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap)).
+ */
+#define ZAP_EMBEDDED_PTRTBL_ENT(zap, idx) \
+ ((grub_uint64_t *)(zap)->zap_f.zap_phys) \
+ [(idx) + (1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap))]
+
+/*
+ * TAKE NOTE:
+ * If zap_phys_t is modified, zap_byteswap() must be modified.
+ */
+typedef struct zap_phys {
+ grub_uint64_t zap_block_type; /* ZBT_HEADER */
+ grub_uint64_t zap_magic; /* ZAP_MAGIC */
+
+ struct zap_table_phys {
+ grub_uint64_t zt_blk; /* starting block number */
+ grub_uint64_t zt_numblks; /* number of blocks */
+ grub_uint64_t zt_shift; /* bits to index it */
+ grub_uint64_t zt_nextblk; /* next (larger) copy start block */
+ grub_uint64_t zt_blks_copied; /* number source blocks copied */
+ } zap_ptrtbl;
+
+ grub_uint64_t zap_freeblk; /* the next free block */
+ grub_uint64_t zap_num_leafs; /* number of leafs */
+ grub_uint64_t zap_num_entries; /* number of entries */
+ grub_uint64_t zap_salt; /* salt to stir into hash function */
+ grub_uint64_t zap_normflags; /* flags for u8_textprep_str() */
+ grub_uint64_t zap_flags; /* zap_flag_t */
+ /*
+ * This structure is followed by padding, and then the embedded
+ * pointer table. The embedded pointer table takes up second
+ * half of the block. It is accessed using the
+ * ZAP_EMBEDDED_PTRTBL_ENT() macro.
+ */
+} zap_phys_t;
+
+#endif /* _SYS_ZAP_IMPL_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zap_leaf.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zap_leaf.h
new file mode 100644
index 0000000..9734456
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zap_leaf.h
@@ -0,0 +1,104 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ZAP_LEAF_H
+#define _SYS_ZAP_LEAF_H
+
+#define ZAP_LEAF_MAGIC 0x2AB1EAF
+
+/* chunk size = 24 bytes */
+#define ZAP_LEAF_CHUNKSIZE 24
+
+/*
+ * The amount of space within the chunk available for the array is:
+ * chunk size - space for type (1) - space for next pointer (2)
+ */
+#define ZAP_LEAF_ARRAY_BYTES (ZAP_LEAF_CHUNKSIZE - 3)
+
+typedef enum zap_chunk_type {
+ ZAP_CHUNK_FREE = 253,
+ ZAP_CHUNK_ENTRY = 252,
+ ZAP_CHUNK_ARRAY = 251,
+ ZAP_CHUNK_TYPE_MAX = 250
+} zap_chunk_type_t;
+
+/*
+ * TAKE NOTE:
+ * If zap_leaf_phys_t is modified, zap_leaf_byteswap() must be modified.
+ */
+typedef struct zap_leaf_phys {
+ struct zap_leaf_header {
+ grub_uint64_t lh_block_type; /* ZBT_LEAF */
+ grub_uint64_t lh_pad1;
+ grub_uint64_t lh_prefix; /* hash prefix of this leaf */
+ grub_uint32_t lh_magic; /* ZAP_LEAF_MAGIC */
+ grub_uint16_t lh_nfree; /* number free chunks */
+ grub_uint16_t lh_nentries; /* number of entries */
+ grub_uint16_t lh_prefix_len; /* num bits used to id this */
+
+/* above is accessable to zap, below is zap_leaf private */
+
+ grub_uint16_t lh_freelist; /* chunk head of free list */
+ grub_uint8_t lh_pad2[12];
+ } l_hdr; /* 2 24-byte chunks */
+
+ /*
+ * The header is followed by a hash table with
+ * ZAP_LEAF_HASH_NUMENTRIES(zap) entries. The hash table is
+ * followed by an array of ZAP_LEAF_NUMCHUNKS(zap)
+ * zap_leaf_chunk structures. These structures are accessed
+ * with the ZAP_LEAF_CHUNK() macro.
+ */
+
+ grub_uint16_t l_hash[1];
+} zap_leaf_phys_t;
+
+typedef union zap_leaf_chunk {
+ struct zap_leaf_entry {
+ grub_uint8_t le_type; /* always ZAP_CHUNK_ENTRY */
+ grub_uint8_t le_int_size; /* size of ints */
+ grub_uint16_t le_next; /* next entry in hash chain */
+ grub_uint16_t le_name_chunk; /* first chunk of the name */
+ grub_uint16_t le_name_length; /* bytes in name, incl null */
+ grub_uint16_t le_value_chunk; /* first chunk of the value */
+ grub_uint16_t le_value_length; /* value length in ints */
+ grub_uint32_t le_cd; /* collision differentiator */
+ grub_uint64_t le_hash; /* hash value of the name */
+ } l_entry;
+ struct zap_leaf_array {
+ grub_uint8_t la_type; /* always ZAP_CHUNK_ARRAY */
+ union
+ {
+ grub_uint8_t la_array[ZAP_LEAF_ARRAY_BYTES];
+ grub_uint64_t la_array64;
+ };
+ grub_uint16_t la_next; /* next blk or CHAIN_END */
+ } l_array;
+ struct zap_leaf_free {
+ grub_uint8_t lf_type; /* always ZAP_CHUNK_FREE */
+ grub_uint8_t lf_pad[ZAP_LEAF_ARRAY_BYTES];
+ grub_uint16_t lf_next; /* next in free list, or CHAIN_END */
+ } l_free;
+} zap_leaf_chunk_t;
+
+#endif /* _SYS_ZAP_LEAF_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs.h
new file mode 100644
index 0000000..153c287
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs.h
@@ -0,0 +1,125 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+ /*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef GRUB_ZFS_HEADER
+#define GRUB_ZFS_HEADER 1
+
+#include <grub/err.h>
+#include <grub/disk.h>
+
+/*
+ * On-disk version number.
+ */
+#define SPA_VERSION 28ULL
+
+/*
+ * The following are configuration names used in the nvlist describing a pool's
+ * configuration.
+ */
+#define ZPOOL_CONFIG_VERSION "version"
+#define ZPOOL_CONFIG_POOL_NAME "name"
+#define ZPOOL_CONFIG_POOL_STATE "state"
+#define ZPOOL_CONFIG_POOL_TXG "txg"
+#define ZPOOL_CONFIG_POOL_GUID "pool_guid"
+#define ZPOOL_CONFIG_CREATE_TXG "create_txg"
+#define ZPOOL_CONFIG_TOP_GUID "top_guid"
+#define ZPOOL_CONFIG_VDEV_TREE "vdev_tree"
+#define ZPOOL_CONFIG_TYPE "type"
+#define ZPOOL_CONFIG_CHILDREN "children"
+#define ZPOOL_CONFIG_ID "id"
+#define ZPOOL_CONFIG_GUID "guid"
+#define ZPOOL_CONFIG_PATH "path"
+#define ZPOOL_CONFIG_DEVID "devid"
+#define ZPOOL_CONFIG_METASLAB_ARRAY "metaslab_array"
+#define ZPOOL_CONFIG_METASLAB_SHIFT "metaslab_shift"
+#define ZPOOL_CONFIG_ASHIFT "ashift"
+#define ZPOOL_CONFIG_ASIZE "asize"
+#define ZPOOL_CONFIG_DTL "DTL"
+#define ZPOOL_CONFIG_STATS "stats"
+#define ZPOOL_CONFIG_WHOLE_DISK "whole_disk"
+#define ZPOOL_CONFIG_ERRCOUNT "error_count"
+#define ZPOOL_CONFIG_NOT_PRESENT "not_present"
+#define ZPOOL_CONFIG_SPARES "spares"
+#define ZPOOL_CONFIG_IS_SPARE "is_spare"
+#define ZPOOL_CONFIG_NPARITY "nparity"
+#define ZPOOL_CONFIG_PHYS_PATH "phys_path"
+#define ZPOOL_CONFIG_L2CACHE "l2cache"
+#define ZPOOL_CONFIG_HOLE_ARRAY "hole_array"
+#define ZPOOL_CONFIG_VDEV_CHILDREN "vdev_children"
+#define ZPOOL_CONFIG_IS_HOLE "is_hole"
+#define ZPOOL_CONFIG_DDT_HISTOGRAM "ddt_histogram"
+#define ZPOOL_CONFIG_DDT_OBJ_STATS "ddt_object_stats"
+#define ZPOOL_CONFIG_DDT_STATS "ddt_stats"
+/*
+ * The persistent vdev state is stored as separate values rather than a single
+ * 'vdev_state' entry. This is because a device can be in multiple states, such
+ * as offline and degraded.
+ */
+#define ZPOOL_CONFIG_OFFLINE "offline"
+#define ZPOOL_CONFIG_FAULTED "faulted"
+#define ZPOOL_CONFIG_DEGRADED "degraded"
+#define ZPOOL_CONFIG_REMOVED "removed"
+
+#define VDEV_TYPE_ROOT "root"
+#define VDEV_TYPE_MIRROR "mirror"
+#define VDEV_TYPE_REPLACING "replacing"
+#define VDEV_TYPE_RAIDZ "raidz"
+#define VDEV_TYPE_DISK "disk"
+#define VDEV_TYPE_FILE "file"
+#define VDEV_TYPE_MISSING "missing"
+#define VDEV_TYPE_HOLE "hole"
+#define VDEV_TYPE_SPARE "spare"
+#define VDEV_TYPE_L2CACHE "l2cache"
+
+/*
+ * pool state. The following states are written to disk as part of the normal
+ * SPA lifecycle: ACTIVE, EXPORTED, DESTROYED, SPARE, L2CACHE. The remaining
+ * states are software abstractions used at various levels to communicate pool
+ * state.
+ */
+typedef enum pool_state {
+ POOL_STATE_ACTIVE = 0, /* In active use */
+ POOL_STATE_EXPORTED, /* Explicitly exported */
+ POOL_STATE_DESTROYED, /* Explicitly destroyed */
+ POOL_STATE_SPARE, /* Reserved for hot spare use */
+ POOL_STATE_L2CACHE, /* Level 2 ARC device */
+ POOL_STATE_UNINITIALIZED, /* Internal spa_t state */
+ POOL_STATE_UNAVAIL, /* Internal libzfs state */
+ POOL_STATE_POTENTIALLY_ACTIVE /* Internal libzfs state */
+} pool_state_t;
+
+struct grub_zfs_data;
+
+grub_err_t grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist);
+grub_err_t grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
+ grub_uint64_t *mdnobj);
+
+char *grub_zfs_nvlist_lookup_string (char *nvlist, char *name);
+char *grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name);
+int grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name,
+ grub_uint64_t *out);
+char *grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
+ grub_size_t index);
+int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name);
+
+#endif /* ! GRUB_ZFS_HEADER */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_acl.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_acl.h
new file mode 100644
index 0000000..65d3fda
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_acl.h
@@ -0,0 +1,60 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_FS_ZFS_ACL_H
+#define _SYS_FS_ZFS_ACL_H
+
+#ifndef _UID_T
+#define _UID_T
+typedef unsigned int uid_t; /* UID type */
+#endif /* _UID_T */
+
+typedef struct zfs_oldace {
+ grub_uint32_t z_fuid; /* "who" */
+ grub_uint32_t z_access_mask; /* access mask */
+ grub_uint16_t z_flags; /* flags, i.e inheritance */
+ grub_uint16_t z_type; /* type of entry allow/deny */
+} zfs_oldace_t;
+
+#define ACE_SLOT_CNT 6
+
+typedef struct zfs_znode_acl_v0 {
+ grub_uint64_t z_acl_extern_obj; /* ext acl pieces */
+ grub_uint32_t z_acl_count; /* Number of ACEs */
+ grub_uint16_t z_acl_version; /* acl version */
+ grub_uint16_t z_acl_pad; /* pad */
+ zfs_oldace_t z_ace_data[ACE_SLOT_CNT]; /* 6 standard ACEs */
+} zfs_znode_acl_v0_t;
+
+#define ZFS_ACE_SPACE (sizeof (zfs_oldace_t) * ACE_SLOT_CNT)
+
+typedef struct zfs_znode_acl {
+ grub_uint64_t z_acl_extern_obj; /* ext acl pieces */
+ grub_uint32_t z_acl_size; /* Number of bytes in ACL */
+ grub_uint16_t z_acl_version; /* acl version */
+ grub_uint16_t z_acl_count; /* ace count */
+ grub_uint8_t z_ace_data[ZFS_ACE_SPACE]; /* space for embedded ACEs */
+} zfs_znode_acl_t;
+
+
+#endif /* _SYS_FS_ZFS_ACL_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_znode.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_znode.h
new file mode 100644
index 0000000..87bc3f9
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zfs_znode.h
@@ -0,0 +1,71 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_FS_ZFS_ZNODE_H
+#define _SYS_FS_ZFS_ZNODE_H
+
+#include <grub/zfs/zfs_acl.h>
+
+#define MASTER_NODE_OBJ 1
+#define ZFS_ROOT_OBJ "ROOT"
+#define ZPL_VERSION_STR "VERSION"
+#define ZFS_SA_ATTRS "SA_ATTRS"
+
+#define ZPL_VERSION 5ULL
+
+#define ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
+
+/*
+ * This is the persistent portion of the znode. It is stored
+ * in the "bonus buffer" of the file. Short symbolic links
+ * are also stored in the bonus buffer.
+ */
+typedef struct znode_phys {
+ grub_uint64_t zp_atime[2]; /* 0 - last file access time */
+ grub_uint64_t zp_mtime[2]; /* 16 - last file modification time */
+ grub_uint64_t zp_ctime[2]; /* 32 - last file change time */
+ grub_uint64_t zp_crtime[2]; /* 48 - creation time */
+ grub_uint64_t zp_gen; /* 64 - generation (txg of creation) */
+ grub_uint64_t zp_mode; /* 72 - file mode bits */
+ grub_uint64_t zp_size; /* 80 - size of file */
+ grub_uint64_t zp_parent; /* 88 - directory parent (`..') */
+ grub_uint64_t zp_links; /* 96 - number of links to file */
+ grub_uint64_t zp_xattr; /* 104 - DMU object for xattrs */
+ grub_uint64_t zp_rdev; /* 112 - dev_t for VBLK & VCHR files */
+ grub_uint64_t zp_flags; /* 120 - persistent flags */
+ grub_uint64_t zp_uid; /* 128 - file owner */
+ grub_uint64_t zp_gid; /* 136 - owning group */
+ grub_uint64_t zp_pad[4]; /* 144 - future */
+ zfs_znode_acl_t zp_acl; /* 176 - 263 ACL */
+ /*
+ * Data may pad out any remaining bytes in the znode buffer, eg:
+ *
+ * |<---------------------- dnode_phys (512) ------------------------>|
+ * |<-- dnode (192) --->|<----------- "bonus" buffer (320) ---------->|
+ * |<---- znode (264) ---->|<---- data (56) ---->|
+ *
+ * At present, we only use this space to store symbolic links.
+ */
+} znode_phys_t;
+
+#endif /* _SYS_FS_ZFS_ZNODE_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zil.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zil.h
new file mode 100644
index 0000000..4ae8daf
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zil.h
@@ -0,0 +1,57 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ZIL_H
+#define _SYS_ZIL_H
+
+/*
+ * Intent log format:
+ *
+ * Each objset has its own intent log. The log header (zil_header_t)
+ * for objset N's intent log is kept in the Nth object of the SPA's
+ * intent_log objset. The log header points to a chain of log blocks,
+ * each of which contains log records (i.e., transactions) followed by
+ * a log block trailer (zil_trailer_t). The format of a log record
+ * depends on the record (or transaction) type, but all records begin
+ * with a common structure that defines the type, length, and txg.
+ */
+
+/*
+ * Intent log header - this on disk structure holds fields to manage
+ * the log. All fields are 64 bit to easily handle cross architectures.
+ */
+typedef struct zil_header {
+ grub_uint64_t zh_claim_txg; /* txg in which log blocks were claimed */
+ grub_uint64_t zh_replay_seq; /* highest replayed sequence number */
+ blkptr_t zh_log; /* log chain */
+ grub_uint64_t zh_claim_seq; /* highest claimed sequence number */
+ grub_uint64_t zh_flags; /* header flags */
+ grub_uint64_t zh_pad[4];
+} zil_header_t;
+
+/*
+ * zh_flags bit settings
+ */
+#define ZIL_REPLAY_NEEDED 0x1 /* replay needed - internal only */
+
+#endif /* _SYS_ZIL_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zio.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zio.h
new file mode 100644
index 0000000..2b177a2
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zio.h
@@ -0,0 +1,85 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ZIO_H
+#define _ZIO_H
+
+#include <grub/zfs/spa.h>
+
+#define ZEC_MAGIC 0x210da7ab10c7a11ULL /* zio data bloc tail */
+
+typedef struct zio_eck {
+ grub_uint64_t zec_magic; /* for validation, endianness */
+ zio_cksum_t zec_cksum; /* 256-bit checksum */
+} zio_eck_t;
+
+/*
+ * Gang block headers are self-checksumming and contain an array
+ * of block pointers.
+ */
+#define SPA_GANGBLOCKSIZE SPA_MINBLOCKSIZE
+#define SPA_GBH_NBLKPTRS ((SPA_GANGBLOCKSIZE - \
+ sizeof (zio_eck_t)) / sizeof (blkptr_t))
+#define SPA_GBH_FILLER ((SPA_GANGBLOCKSIZE - \
+ sizeof (zio_eck_t) - \
+ (SPA_GBH_NBLKPTRS * sizeof (blkptr_t))) /\
+ sizeof (grub_uint64_t))
+
+#define ZIO_GET_IOSIZE(zio) \
+ (BP_IS_GANG((zio)->io_bp) ? \
+ SPA_GANGBLOCKSIZE : BP_GET_PSIZE((zio)->io_bp))
+
+typedef struct zio_gbh {
+ blkptr_t zg_blkptr[SPA_GBH_NBLKPTRS];
+ grub_uint64_t zg_filler[SPA_GBH_FILLER];
+ zio_eck_t zg_tail;
+} zio_gbh_phys_t;
+
+enum zio_checksum {
+ ZIO_CHECKSUM_INHERIT = 0,
+ ZIO_CHECKSUM_ON,
+ ZIO_CHECKSUM_OFF,
+ ZIO_CHECKSUM_LABEL,
+ ZIO_CHECKSUM_GANG_HEADER,
+ ZIO_CHECKSUM_ZILOG,
+ ZIO_CHECKSUM_FLETCHER_2,
+ ZIO_CHECKSUM_FLETCHER_4,
+ ZIO_CHECKSUM_SHA256,
+ ZIO_CHECKSUM_ZILOG2,
+ ZIO_CHECKSUM_FUNCTIONS
+};
+
+#define ZIO_CHECKSUM_ON_VALUE ZIO_CHECKSUM_FLETCHER_2
+#define ZIO_CHECKSUM_DEFAULT ZIO_CHECKSUM_ON
+
+enum zio_compress {
+ ZIO_COMPRESS_INHERIT = 0,
+ ZIO_COMPRESS_ON,
+ ZIO_COMPRESS_OFF,
+ ZIO_COMPRESS_LZJB,
+ ZIO_COMPRESS_EMPTY,
+ ZIO_COMPRESS_GZIP,
+ ZIO_COMPRESS_FUNCTIONS
+};
+
+#endif /* _ZIO_H */
diff --git a/debian/grub-extras/disabled/zfs/include/grub/zfs/zio_checksum.h b/debian/grub-extras/disabled/zfs/include/grub/zfs/zio_checksum.h
new file mode 100644
index 0000000..b4d6382
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/include/grub/zfs/zio_checksum.h
@@ -0,0 +1,50 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ZIO_CHECKSUM_H
+#define _SYS_ZIO_CHECKSUM_H
+
+/*
+ * Signature for checksum functions.
+ */
+typedef void zio_checksum_t(const void *data, grub_uint64_t size,
+ grub_zfs_endian_t endian, zio_cksum_t *zcp);
+
+/*
+ * Information about each checksum function.
+ */
+typedef struct zio_checksum_info {
+ zio_checksum_t *ci_func; /* checksum function for each byteorder */
+ int ci_correctable; /* number of correctable bits */
+ int ci_eck; /* uses zio embedded checksum? */
+ char *ci_name; /* descriptive name */
+} zio_checksum_info_t;
+
+extern void zio_checksum_SHA256 (const void *, grub_uint64_t,
+ grub_zfs_endian_t endian, zio_cksum_t *);
+extern void fletcher_2 (const void *, grub_uint64_t, grub_zfs_endian_t endian,
+ zio_cksum_t *);
+extern void fletcher_4 (const void *, grub_uint64_t, grub_zfs_endian_t endian,
+ zio_cksum_t *);
+
+#endif /* _SYS_ZIO_CHECKSUM_H */
diff --git a/debian/grub-extras/disabled/zfs/zfs.c b/debian/grub-extras/disabled/zfs/zfs.c
new file mode 100644
index 0000000..ce735a3
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/zfs.c
@@ -0,0 +1,2546 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright 2010 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ * Copyright (C) 2010 Robert Millan <rmh@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * The zfs plug-in routines for GRUB are:
+ *
+ * zfs_mount() - locates a valid uberblock of the root pool and reads
+ * in its MOS at the memory address MOS.
+ *
+ * zfs_open() - locates a plain file object by following the MOS
+ * and places its dnode at the memory address DNODE.
+ *
+ * zfs_read() - read in the data blocks pointed by the DNODE.
+ *
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/partition.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+#include <grub/zfs/zfs.h>
+#include <grub/zfs/zio.h>
+#include <grub/zfs/dnode.h>
+#include <grub/zfs/uberblock_impl.h>
+#include <grub/zfs/vdev_impl.h>
+#include <grub/zfs/zio_checksum.h>
+#include <grub/zfs/zap_impl.h>
+#include <grub/zfs/zap_leaf.h>
+#include <grub/zfs/zfs_znode.h>
+#include <grub/zfs/dmu.h>
+#include <grub/zfs/dmu_objset.h>
+#include <grub/zfs/sa_impl.h>
+#include <grub/zfs/dsl_dir.h>
+#include <grub/zfs/dsl_dataset.h>
+
+#define ZPOOL_PROP_BOOTFS "bootfs"
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+/*
+ * For nvlist manipulation. (from nvpair.h)
+ */
+#define NV_ENCODE_NATIVE 0
+#define NV_ENCODE_XDR 1
+#define NV_BIG_ENDIAN 0
+#define NV_LITTLE_ENDIAN 1
+#define DATA_TYPE_UINT64 8
+#define DATA_TYPE_STRING 9
+#define DATA_TYPE_NVLIST 19
+#define DATA_TYPE_NVLIST_ARRAY 20
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+#define P2PHASE(x, align) ((x) & ((align) - 1))
+#define DVA_OFFSET_TO_PHYS_SECTOR(offset) \
+ ((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT)
+
+/*
+ * FAT ZAP data structures
+ */
+#define ZFS_CRC64_POLY 0xC96C5795D7870F42ULL /* ECMA-182, reflected form */
+#define ZAP_HASH_IDX(hash, n) (((n) == 0) ? 0 : ((hash) >> (64 - (n))))
+#define CHAIN_END 0xffff /* end of the chunk chain */
+
+/*
+ * The amount of space within the chunk available for the array is:
+ * chunk size - space for type (1) - space for next pointer (2)
+ */
+#define ZAP_LEAF_ARRAY_BYTES (ZAP_LEAF_CHUNKSIZE - 3)
+
+#define ZAP_LEAF_HASH_SHIFT(bs) (bs - 5)
+#define ZAP_LEAF_HASH_NUMENTRIES(bs) (1 << ZAP_LEAF_HASH_SHIFT(bs))
+#define LEAF_HASH(bs, h) \
+ ((ZAP_LEAF_HASH_NUMENTRIES(bs)-1) & \
+ ((h) >> (64 - ZAP_LEAF_HASH_SHIFT(bs)-l->l_hdr.lh_prefix_len)))
+
+/*
+ * The amount of space available for chunks is:
+ * block size shift - hash entry size (2) * number of hash
+ * entries - header space (2*chunksize)
+ */
+#define ZAP_LEAF_NUMCHUNKS(bs) \
+ (((1<<bs) - 2*ZAP_LEAF_HASH_NUMENTRIES(bs)) / \
+ ZAP_LEAF_CHUNKSIZE - 2)
+
+/*
+ * The chunks start immediately after the hash table. The end of the
+ * hash table is at l_hash + HASH_NUMENTRIES, which we simply cast to a
+ * chunk_t.
+ */
+#define ZAP_LEAF_CHUNK(l, bs, idx) \
+ ((zap_leaf_chunk_t *)(l->l_hash + ZAP_LEAF_HASH_NUMENTRIES(bs)))[idx]
+#define ZAP_LEAF_ENTRY(l, bs, idx) (&ZAP_LEAF_CHUNK(l, bs, idx).l_entry)
+
+
+/*
+ * Decompression Entry - lzjb
+ */
+#ifndef NBBY
+#define NBBY 8
+#endif
+
+extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
+
+typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
+ grub_size_t s_len, grub_size_t d_len);
+typedef struct decomp_entry
+{
+ char *name;
+ zfs_decomp_func_t *decomp_func;
+} decomp_entry_t;
+
+typedef struct dnode_end
+{
+ dnode_phys_t dn;
+ grub_zfs_endian_t endian;
+} dnode_end_t;
+
+struct grub_zfs_data
+{
+ /* cache for a file block of the currently zfs_open()-ed file */
+ char *file_buf;
+ grub_uint64_t file_start;
+ grub_uint64_t file_end;
+
+ /* cache for a dnode block */
+ dnode_phys_t *dnode_buf;
+ dnode_phys_t *dnode_mdn;
+ grub_uint64_t dnode_start;
+ grub_uint64_t dnode_end;
+ grub_zfs_endian_t dnode_endian;
+
+ uberblock_t current_uberblock;
+ grub_disk_t disk;
+
+ dnode_end_t mos;
+ dnode_end_t mdn;
+ dnode_end_t dnode;
+
+ grub_disk_addr_t vdev_phys_sector;
+};
+
+decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = {
+ {"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */
+ {"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */
+ {"off", NULL}, /* ZIO_COMPRESS_OFF */
+ {"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */
+ {"empty", NULL}, /* ZIO_COMPRESS_EMPTY */
+ {"gzip", NULL}, /* ZIO_COMPRESS_GZIP */
+};
+
+static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
+ void *buf, struct grub_zfs_data *data);
+
+/*
+ * Our own version of log2(). Same thing as highbit()-1.
+ */
+static int
+zfs_log2 (grub_uint64_t num)
+{
+ int i = 0;
+
+ while (num > 1)
+ {
+ i++;
+ num = num >> 1;
+ }
+
+ return (i);
+}
+
+/* Checksum Functions */
+static void
+zio_checksum_off (const void *buf __attribute__ ((unused)),
+ grub_uint64_t size __attribute__ ((unused)),
+ grub_zfs_endian_t endian __attribute__ ((unused)),
+ zio_cksum_t * zcp)
+{
+ ZIO_SET_CHECKSUM (zcp, 0, 0, 0, 0);
+}
+
+/* Checksum Table and Values */
+zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
+ {NULL, 0, 0, "inherit"},
+ {NULL, 0, 0, "on"},
+ {zio_checksum_off, 0, 0, "off"},
+ {zio_checksum_SHA256, 1, 1, "label"},
+ {zio_checksum_SHA256, 1, 1, "gang_header"},
+ {NULL, 0, 0, "zilog"},
+ {fletcher_2, 0, 0, "fletcher2"},
+ {fletcher_4, 1, 0, "fletcher4"},
+ {zio_checksum_SHA256, 1, 0, "SHA256"},
+ {NULL, 0, 0, "zilog2"},
+};
+
+/*
+ * zio_checksum_verify: Provides support for checksum verification.
+ *
+ * Fletcher2, Fletcher4, and SHA256 are supported.
+ *
+ */
+static grub_err_t
+zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum,
+ grub_zfs_endian_t endian, char *buf, int size)
+{
+ zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1;
+ zio_checksum_info_t *ci = &zio_checksum_table[checksum];
+ zio_cksum_t actual_cksum, expected_cksum;
+
+ if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func == NULL)
+ {
+ grub_dprintf ("zfs", "unknown checksum function %d\n", checksum);
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "unknown checksum function %d", checksum);
+ }
+
+ if (ci->ci_eck)
+ {
+ expected_cksum = zec->zec_cksum;
+ zec->zec_cksum = zc;
+ ci->ci_func (buf, size, endian, &actual_cksum);
+ zec->zec_cksum = expected_cksum;
+ zc = expected_cksum;
+ }
+ else
+ ci->ci_func (buf, size, endian, &actual_cksum);
+
+ if ((actual_cksum.zc_word[0] != zc.zc_word[0])
+ || (actual_cksum.zc_word[1] != zc.zc_word[1])
+ || (actual_cksum.zc_word[2] != zc.zc_word[2])
+ || (actual_cksum.zc_word[3] != zc.zc_word[3]))
+ {
+ grub_dprintf ("zfs", "checksum %d verification failed\n", checksum);
+ grub_dprintf ("zfs", "actual checksum %16llx %16llx %16llx %16llx\n",
+ (unsigned long long) actual_cksum.zc_word[0],
+ (unsigned long long) actual_cksum.zc_word[1],
+ (unsigned long long) actual_cksum.zc_word[2],
+ (unsigned long long) actual_cksum.zc_word[3]);
+ grub_dprintf ("zfs", "expected checksum %16llx %16llx %16llx %16llx\n",
+ (unsigned long long) zc.zc_word[0],
+ (unsigned long long) zc.zc_word[1],
+ (unsigned long long) zc.zc_word[2],
+ (unsigned long long) zc.zc_word[3]);
+ return grub_error (GRUB_ERR_BAD_FS, "checksum verification failed");
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * vdev_uberblock_compare takes two uberblock structures and returns an integer
+ * indicating the more recent of the two.
+ * Return Value = 1 if ub2 is more recent
+ * Return Value = -1 if ub1 is more recent
+ * The most recent uberblock is determined using its transaction number and
+ * timestamp. The uberblock with the highest transaction number is
+ * considered "newer". If the transaction numbers of the two blocks match, the
+ * timestamps are compared to determine the "newer" of the two.
+ */
+static int
+vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2)
+{
+ grub_zfs_endian_t ub1_endian, ub2_endian;
+ if (grub_zfs_to_cpu64 (ub1->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC)
+ ub1_endian = LITTLE_ENDIAN;
+ else
+ ub1_endian = BIG_ENDIAN;
+ if (grub_zfs_to_cpu64 (ub2->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC)
+ ub2_endian = LITTLE_ENDIAN;
+ else
+ ub2_endian = BIG_ENDIAN;
+
+ if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian)
+ < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
+ return (-1);
+ if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian)
+ > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
+ return (1);
+
+ if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian)
+ < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
+ return (-1);
+ if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian)
+ > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Three pieces of information are needed to verify an uberblock: the magic
+ * number, the version number, and the checksum.
+ *
+ * Currently Implemented: version number, magic number
+ * Need to Implement: checksum
+ *
+ */
+static grub_err_t
+uberblock_verify (uberblock_phys_t * ub, int offset)
+{
+ uberblock_t *uber = &ub->ubp_uberblock;
+ grub_err_t err;
+ grub_zfs_endian_t endian = UNKNOWN_ENDIAN;
+ zio_cksum_t zc;
+
+ if (grub_zfs_to_cpu64 (uber->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC
+ && grub_zfs_to_cpu64 (uber->ub_version, LITTLE_ENDIAN) > 0
+ && grub_zfs_to_cpu64 (uber->ub_version, LITTLE_ENDIAN) <= SPA_VERSION)
+ endian = LITTLE_ENDIAN;
+
+ if (grub_zfs_to_cpu64 (uber->ub_magic, BIG_ENDIAN) == UBERBLOCK_MAGIC
+ && grub_zfs_to_cpu64 (uber->ub_version, BIG_ENDIAN) > 0
+ && grub_zfs_to_cpu64 (uber->ub_version, BIG_ENDIAN) <= SPA_VERSION)
+ endian = BIG_ENDIAN;
+
+ if (endian == UNKNOWN_ENDIAN)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid uberblock magic");
+
+ grub_memset (&zc, 0, sizeof (zc));
+
+ zc.zc_word[0] = grub_cpu_to_zfs64 (offset, endian);
+ err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL, endian,
+ (char *) ub, UBERBLOCK_SIZE);
+
+ return err;
+}
+
+/*
+ * Find the best uberblock.
+ * Return:
+ * Success - Pointer to the best uberblock.
+ * Failure - NULL
+ */
+static uberblock_phys_t *
+find_bestub (uberblock_phys_t * ub_array, grub_disk_addr_t sector)
+{
+ uberblock_phys_t *ubbest = NULL;
+ int i;
+ grub_disk_addr_t offset;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++)
+ {
+ offset = (sector << SPA_MINBLOCKSHIFT) + VDEV_PHYS_SIZE
+ + (i << VDEV_UBERBLOCK_SHIFT);
+
+ err = uberblock_verify (&ub_array[i], offset);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ if (ubbest == NULL
+ || vdev_uberblock_compare (&(ub_array[i].ubp_uberblock),
+ &(ubbest->ubp_uberblock)) > 0)
+ ubbest = &ub_array[i];
+ }
+ if (!ubbest)
+ grub_errno = err;
+
+ return (ubbest);
+}
+
+static inline grub_size_t
+get_psize (blkptr_t * bp, grub_zfs_endian_t endian)
+{
+ return ((((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) >> 16) & 0xffff) + 1)
+ << SPA_MINBLOCKSHIFT);
+}
+
+static grub_uint64_t
+dva_get_offset (dva_t * dva, grub_zfs_endian_t endian)
+{
+ grub_dprintf ("zfs", "dva=%llx, %llx\n",
+ (unsigned long long) dva->dva_word[0],
+ (unsigned long long) dva->dva_word[1]);
+ return grub_zfs_to_cpu64 ((dva)->dva_word[1],
+ endian) << SPA_MINBLOCKSHIFT;
+}
+
+
+/*
+ * Read a block of data based on the gang block address dva,
+ * and put its data in buf.
+ *
+ */
+static grub_err_t
+zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf,
+ struct grub_zfs_data *data)
+{
+ zio_gbh_phys_t *zio_gb;
+ grub_uint64_t offset, sector;
+ unsigned i;
+ grub_err_t err;
+ zio_cksum_t zc;
+
+ grub_memset (&zc, 0, sizeof (zc));
+
+ zio_gb = grub_malloc (SPA_GANGBLOCKSIZE);
+ if (!zio_gb)
+ return grub_errno;
+ grub_dprintf ("zfs", endian == LITTLE_ENDIAN ? "little-endian gang\n"
+ :"big-endian gang\n");
+ offset = dva_get_offset (dva, endian);
+ sector = DVA_OFFSET_TO_PHYS_SECTOR (offset);
+ grub_dprintf ("zfs", "offset=%llx\n", (unsigned long long) offset);
+
+ /* read in the gang block header */
+ err = grub_disk_read (data->disk, sector, 0, SPA_GANGBLOCKSIZE,
+ (char *) zio_gb);
+ if (err)
+ {
+ grub_free (zio_gb);
+ return err;
+ }
+
+ /* XXX */
+ /* self checksuming the gang block header */
+ ZIO_SET_CHECKSUM (&zc, DVA_GET_VDEV (dva),
+ dva_get_offset (dva, endian), bp->blk_birth, 0);
+ err = zio_checksum_verify (zc, ZIO_CHECKSUM_GANG_HEADER, endian,
+ (char *) zio_gb, SPA_GANGBLOCKSIZE);
+ if (err)
+ {
+ grub_free (zio_gb);
+ return err;
+ }
+
+ endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
+
+ for (i = 0; i < SPA_GBH_NBLKPTRS; i++)
+ {
+ if (zio_gb->zg_blkptr[i].blk_birth == 0)
+ continue;
+
+ err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data);
+ if (err)
+ {
+ grub_free (zio_gb);
+ return err;
+ }
+ buf = (char *) buf + get_psize (&zio_gb->zg_blkptr[i], endian);
+ }
+ grub_free (zio_gb);
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Read in a block of raw data to buf.
+ */
+static grub_err_t
+zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf,
+ struct grub_zfs_data *data)
+{
+ int i, psize;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ psize = get_psize (bp, endian);
+
+ /* pick a good dva from the block pointer */
+ for (i = 0; i < SPA_DVAS_PER_BP; i++)
+ {
+ grub_uint64_t offset, sector;
+
+ if (bp->blk_dva[i].dva_word[0] == 0 && bp->blk_dva[i].dva_word[1] == 0)
+ continue;
+
+ if ((grub_zfs_to_cpu64 (bp->blk_dva[i].dva_word[1], endian)>>63) & 1)
+ err = zio_read_gang (bp, endian, &bp->blk_dva[i], buf, data);
+ else
+ {
+ /* read in a data block */
+ offset = dva_get_offset (&bp->blk_dva[i], endian);
+ sector = DVA_OFFSET_TO_PHYS_SECTOR (offset);
+ err = grub_disk_read (data->disk, sector, 0, psize, buf);
+ }
+ if (!err)
+ return GRUB_ERR_NONE;
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ if (!err)
+ err = grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid DVA");
+ grub_errno = err;
+
+ return err;
+}
+
+/*
+ * Read in a block of data, verify its checksum, decompress if needed,
+ * and put the uncompressed data in buf.
+ */
+static grub_err_t
+zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf,
+ grub_size_t *size, struct grub_zfs_data *data)
+{
+ grub_size_t lsize, psize;
+ unsigned int comp;
+ char *compbuf = NULL;
+ grub_err_t err;
+ zio_cksum_t zc = bp->blk_cksum;
+ grub_uint32_t checksum;
+
+ *buf = NULL;
+
+ checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
+ comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7;
+ lsize = (BP_IS_HOLE(bp) ? 0 :
+ (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
+ << SPA_MINBLOCKSHIFT));
+ psize = get_psize (bp, endian);
+
+ if (size)
+ *size = lsize;
+
+ if (comp >= ZIO_COMPRESS_FUNCTIONS)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "compression algorithm %u not supported\n", (unsigned int) comp);
+
+ if (comp != ZIO_COMPRESS_OFF && decomp_table[comp].decomp_func == NULL)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "compression algorithm %s not supported\n", decomp_table[comp].name);
+
+ if (comp != ZIO_COMPRESS_OFF)
+ {
+ compbuf = grub_malloc (psize);
+ if (! compbuf)
+ return grub_errno;
+ }
+ else
+ compbuf = *buf = grub_malloc (lsize);
+
+ grub_dprintf ("zfs", "endian = %d\n", endian);
+ err = zio_read_data (bp, endian, compbuf, data);
+ if (err)
+ {
+ grub_free (compbuf);
+ *buf = NULL;
+ return err;
+ }
+
+ err = zio_checksum_verify (zc, checksum, endian, compbuf, psize);
+ if (err)
+ {
+ grub_dprintf ("zfs", "incorrect checksum\n");
+ grub_free (compbuf);
+ *buf = NULL;
+ return err;
+ }
+
+ if (comp != ZIO_COMPRESS_OFF)
+ {
+ *buf = grub_malloc (lsize);
+ if (!*buf)
+ {
+ grub_free (compbuf);
+ return grub_errno;
+ }
+
+ err = decomp_table[comp].decomp_func (compbuf, *buf, psize, lsize);
+ grub_free (compbuf);
+ if (err)
+ {
+ grub_free (*buf);
+ *buf = NULL;
+ return err;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Get the block from a block id.
+ * push the block onto the stack.
+ *
+ */
+static grub_err_t
+dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
+ grub_zfs_endian_t *endian_out, struct grub_zfs_data *data)
+{
+ int idx, level;
+ blkptr_t *bp_array = dn->dn.dn_blkptr;
+ int epbs = dn->dn.dn_indblkshift - SPA_BLKPTRSHIFT;
+ blkptr_t *bp, *tmpbuf = 0;
+ grub_zfs_endian_t endian;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ bp = grub_malloc (sizeof (blkptr_t));
+ if (!bp)
+ return grub_errno;
+
+ endian = dn->endian;
+ for (level = dn->dn.dn_nlevels - 1; level >= 0; level--)
+ {
+ grub_dprintf ("zfs", "endian = %d\n", endian);
+ idx = (blkid >> (epbs * level)) & ((1 << epbs) - 1);
+ *bp = bp_array[idx];
+ if (bp_array != dn->dn.dn_blkptr)
+ {
+ grub_free (bp_array);
+ bp_array = 0;
+ }
+
+ if (BP_IS_HOLE (bp))
+ {
+ grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec,
+ dn->endian)
+ << SPA_MINBLOCKSHIFT;
+ *buf = grub_malloc (size);
+ if (*buf)
+ {
+ err = grub_errno;
+ break;
+ }
+ grub_memset (*buf, 0, size);
+ endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
+ break;
+ }
+ if (level == 0)
+ {
+ grub_dprintf ("zfs", "endian = %d\n", endian);
+ err = zio_read (bp, endian, buf, 0, data);
+ endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
+ break;
+ }
+ grub_dprintf ("zfs", "endian = %d\n", endian);
+ err = zio_read (bp, endian, (void **) &tmpbuf, 0, data);
+ endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
+ if (err)
+ break;
+ bp_array = tmpbuf;
+ }
+ if (bp_array != dn->dn.dn_blkptr)
+ grub_free (bp_array);
+ if (endian_out)
+ *endian_out = endian;
+
+ grub_free (bp);
+ return err;
+}
+
+/*
+ * mzap_lookup: Looks up property described by "name" and returns the value
+ * in "value".
+ */
+static grub_err_t
+mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
+ int objsize, char *name, grub_uint64_t * value)
+{
+ int i, chunks;
+ mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
+
+ chunks = objsize / MZAP_ENT_LEN - 1;
+ for (i = 0; i < chunks; i++)
+ {
+ if (grub_strcmp (mzap_ent[i].mze_name, name) == 0)
+ {
+ *value = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian);
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't find %s", name);
+}
+
+static int
+mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize,
+ int NESTED_FUNC_ATTR (*hook) (const char *name,
+ grub_uint64_t val))
+{
+ int i, chunks;
+ mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
+
+ chunks = objsize / MZAP_ENT_LEN - 1;
+ for (i = 0; i < chunks; i++)
+ {
+ grub_dprintf ("zfs", "zap: name = %s, value = %llx, cd = %x\n",
+ mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value,
+ (int)mzap_ent[i].mze_cd);
+ if (hook (mzap_ent[i].mze_name,
+ grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian)))
+ return 1;
+ }
+
+ return 0;
+}
+
+static grub_uint64_t
+zap_hash (grub_uint64_t salt, const char *name)
+{
+ static grub_uint64_t table[256];
+ const grub_uint8_t *cp;
+ grub_uint8_t c;
+ grub_uint64_t crc = salt;
+
+ if (table[128] == 0)
+ {
+ grub_uint64_t *ct;
+ int i, j;
+ for (i = 0; i < 256; i++)
+ {
+ for (ct = table + i, *ct = i, j = 8; j > 0; j--)
+ *ct = (*ct >> 1) ^ (-(*ct & 1) & ZFS_CRC64_POLY);
+ }
+ }
+
+ for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++)
+ crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];
+
+ /*
+ * Only use 28 bits, since we need 4 bits in the cookie for the
+ * collision differentiator. We MUST use the high bits, since
+ * those are the onces that we first pay attention to when
+ * chosing the bucket.
+ */
+ crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
+
+ return (crc);
+}
+
+/*
+ * Only to be used on 8-bit arrays.
+ * array_len is actual len in bytes (not encoded le_value_length).
+ * buf is null-terminated.
+ */
+/* XXX */
+static int
+zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
+ int blksft, int chunk, int array_len, const char *buf)
+{
+ int bseen = 0;
+
+ while (bseen < array_len)
+ {
+ struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array;
+ int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES);
+
+ if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
+ return (0);
+
+ if (grub_memcmp (la->la_array, buf + bseen, toread) != 0)
+ break;
+ chunk = grub_zfs_to_cpu16 (la->la_next, endian);
+ bseen += toread;
+ }
+ return (bseen == array_len);
+}
+
+/* XXX */
+static grub_err_t
+zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft,
+ int chunk, int array_len, char *buf)
+{
+ int bseen = 0;
+
+ while (bseen < array_len)
+ {
+ struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array;
+ int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES);
+
+ if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
+ /* Don't use grub_error because this error is to be ignored. */
+ return GRUB_ERR_BAD_FS;
+
+ grub_memcpy (buf + bseen,la->la_array, toread);
+ chunk = grub_zfs_to_cpu16 (la->la_next, endian);
+ bseen += toread;
+ }
+ return GRUB_ERR_NONE;
+}
+
+
+/*
+ * Given a zap_leaf_phys_t, walk thru the zap leaf chunks to get the
+ * value for the property "name".
+ *
+ */
+/* XXX */
+static grub_err_t
+zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
+ int blksft, grub_uint64_t h,
+ const char *name, grub_uint64_t * value)
+{
+ grub_uint16_t chunk;
+ struct zap_leaf_entry *le;
+
+ /* Verify if this is a valid leaf block */
+ if (grub_zfs_to_cpu64 (l->l_hdr.lh_block_type, endian) != ZBT_LEAF)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid leaf type");
+ if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic");
+
+ for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h)], endian);
+ chunk != CHAIN_END; chunk = le->le_next)
+ {
+
+ if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
+ return grub_error (GRUB_ERR_BAD_FS, "invalid chunk number");
+
+ le = ZAP_LEAF_ENTRY (l, blksft, chunk);
+
+ /* Verify the chunk entry */
+ if (le->le_type != ZAP_CHUNK_ENTRY)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid chunk entry");
+
+ if (grub_zfs_to_cpu64 (le->le_hash,endian) != h)
+ continue;
+
+ grub_dprintf ("zfs", "fzap: length %d\n", (int) le->le_name_length);
+
+ if (zap_leaf_array_equal (l, endian, blksft,
+ grub_zfs_to_cpu16 (le->le_name_chunk,endian),
+ grub_zfs_to_cpu16 (le->le_name_length, endian),
+ name))
+ {
+ struct zap_leaf_array *la;
+ grub_uint8_t *ip;
+
+ if (le->le_int_size != 8 || le->le_value_length != 1)
+ return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry");
+
+ /* get the uint64_t property value */
+ la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array;
+ ip = la->la_array;
+
+ *value = grub_be_to_cpu64 (la->la_array64);
+
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't find %s", name);
+}
+
+
+/* Verify if this is a fat zap header block */
+static grub_err_t
+zap_verify (zap_phys_t *zap)
+{
+ if (zap->zap_magic != (grub_uint64_t) ZAP_MAGIC)
+ return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic");
+
+ if (zap->zap_flags != 0)
+ return grub_error (GRUB_ERR_BAD_FS, "bad ZAP flags");
+
+ if (zap->zap_salt == 0)
+ return grub_error (GRUB_ERR_BAD_FS, "bad ZAP salt");
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Fat ZAP lookup
+ *
+ */
+/* XXX */
+static grub_err_t
+fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
+ char *name, grub_uint64_t * value, struct grub_zfs_data *data)
+{
+ zap_leaf_phys_t *l;
+ grub_uint64_t hash, idx, blkid;
+ int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
+ zap_dnode->endian) << DNODE_SHIFT);
+ grub_err_t err;
+ grub_zfs_endian_t leafendian;
+
+ err = zap_verify (zap);
+ if (err)
+ return err;
+
+ hash = zap_hash (zap->zap_salt, name);
+
+ /* get block id from index */
+ if (zap->zap_ptrtbl.zt_numblks != 0)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "external pointer tables not supported");
+ idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift);
+ blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))];
+
+ /* Get the leaf block */
+ if ((1U << blksft) < sizeof (zap_leaf_phys_t))
+ return grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small");
+ err = dmu_read (zap_dnode, blkid, (void **) &l, &leafendian, data);
+ if (err)
+ return err;
+
+ err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value);
+ grub_free (l);
+ return err;
+}
+
+/* XXX */
+static int
+fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
+ int NESTED_FUNC_ATTR (*hook) (const char *name,
+ grub_uint64_t val),
+ struct grub_zfs_data *data)
+{
+ zap_leaf_phys_t *l;
+ grub_uint64_t idx, blkid;
+ grub_uint16_t chunk;
+ int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
+ zap_dnode->endian) << DNODE_SHIFT);
+ grub_err_t err;
+ grub_zfs_endian_t endian;
+
+ if (zap_verify (zap))
+ return 0;
+
+ /* get block id from index */
+ if (zap->zap_ptrtbl.zt_numblks != 0)
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "external pointer tables not supported");
+ return 0;
+ }
+ /* Get the leaf block */
+ if ((1U << blksft) < sizeof (zap_leaf_phys_t))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small");
+ return 0;
+ }
+ for (idx = 0; idx < zap->zap_ptrtbl.zt_numblks; idx++)
+ {
+ blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))];
+
+ err = dmu_read (zap_dnode, blkid, (void **) &l, &endian, data);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ /* Verify if this is a valid leaf block */
+ if (grub_zfs_to_cpu64 (l->l_hdr.lh_block_type, endian) != ZBT_LEAF)
+ {
+ grub_free (l);
+ continue;
+ }
+ if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC)
+ {
+ grub_free (l);
+ continue;
+ }
+
+ for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++)
+ {
+ char *buf;
+ struct zap_leaf_array *la;
+ struct zap_leaf_entry *le;
+ grub_uint64_t val;
+ le = ZAP_LEAF_ENTRY (l, blksft, chunk);
+
+ /* Verify the chunk entry */
+ if (le->le_type != ZAP_CHUNK_ENTRY)
+ continue;
+
+ buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
+ + 1);
+ if (zap_leaf_array_get (l, endian, blksft, le->le_name_chunk,
+ le->le_name_length, buf))
+ {
+ grub_free (buf);
+ continue;
+ }
+ buf[le->le_name_length] = 0;
+
+ if (le->le_int_size != 8
+ || grub_zfs_to_cpu16 (le->le_value_length, endian) != 1)
+ continue;
+
+ /* get the uint64_t property value */
+ la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array;
+ val = grub_be_to_cpu64 (la->la_array64);
+ if (hook (buf, val))
+ return 1;
+ grub_free (buf);
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Read in the data of a zap object and find the value for a matching
+ * property name.
+ *
+ */
+static grub_err_t
+zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val,
+ struct grub_zfs_data *data)
+{
+ grub_uint64_t block_type;
+ int size;
+ void *zapbuf;
+ grub_err_t err;
+ grub_zfs_endian_t endian;
+
+ grub_dprintf ("zfs", "looking for '%s'\n", name);
+
+ /* Read in the first block of the zap object data. */
+ size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
+ zap_dnode->endian) << SPA_MINBLOCKSHIFT;
+ err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
+ if (err)
+ return err;
+ block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
+
+ grub_dprintf ("zfs", "zap read\n");
+
+ if (block_type == ZBT_MICRO)
+ {
+ grub_dprintf ("zfs", "micro zap\n");
+ err = (mzap_lookup (zapbuf, endian, size, name, val));
+ grub_dprintf ("zfs", "returned %d\n", err);
+ grub_free (zapbuf);
+ return err;
+ }
+ else if (block_type == ZBT_HEADER)
+ {
+ grub_dprintf ("zfs", "fat zap\n");
+ /* this is a fat zap */
+ err = (fzap_lookup (zap_dnode, zapbuf, name, val, data));
+ grub_dprintf ("zfs", "returned %d\n", err);
+ grub_free (zapbuf);
+ return err;
+ }
+
+ return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
+}
+
+static int
+zap_iterate (dnode_end_t * zap_dnode,
+ int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t val),
+ struct grub_zfs_data *data)
+{
+ grub_uint64_t block_type;
+ int size;
+ void *zapbuf;
+ grub_err_t err;
+ int ret;
+ grub_zfs_endian_t endian;
+
+ /* Read in the first block of the zap object data. */
+ size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT;
+ err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
+ if (err)
+ return 0;
+ block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
+
+ grub_dprintf ("zfs", "zap read\n");
+
+ if (block_type == ZBT_MICRO)
+ {
+ grub_dprintf ("zfs", "micro zap\n");
+ ret = mzap_iterate (zapbuf, endian, size, hook);
+ grub_free (zapbuf);
+ return ret;
+ }
+ else if (block_type == ZBT_HEADER)
+ {
+ grub_dprintf ("zfs", "fat zap\n");
+ /* this is a fat zap */
+ ret = fzap_iterate (zap_dnode, zapbuf, hook, data);
+ grub_free (zapbuf);
+ return ret;
+ }
+ grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
+ return 0;
+}
+
+
+/*
+ * Get the dnode of an object number from the metadnode of an object set.
+ *
+ * Input
+ * mdn - metadnode to get the object dnode
+ * objnum - object number for the object dnode
+ * buf - data buffer that holds the returning dnode
+ */
+static grub_err_t
+dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type,
+ dnode_end_t * buf, struct grub_zfs_data *data)
+{
+ grub_uint64_t blkid, blksz; /* the block id this object dnode is in */
+ int epbs; /* shift of number of dnodes in a block */
+ int idx; /* index within a block */
+ dnode_phys_t *dnbuf;
+ grub_err_t err;
+ grub_zfs_endian_t endian;
+
+ blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec,
+ mdn->endian) << SPA_MINBLOCKSHIFT;
+ epbs = zfs_log2 (blksz) - DNODE_SHIFT;
+ blkid = objnum >> epbs;
+ idx = objnum & ((1 << epbs) - 1);
+
+ if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn,
+ sizeof (*mdn)) == 0
+ && objnum >= data->dnode_start && objnum < data->dnode_end)
+ {
+ grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE);
+ buf->endian = data->dnode_endian;
+ if (type && buf->dn.dn_type != type)
+ return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type");
+ return GRUB_ERR_NONE;
+ }
+
+ grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian,
+ (unsigned long long) blkid);
+ err = dmu_read (mdn, blkid, (void **) &dnbuf, &endian, data);
+ if (err)
+ return err;
+ grub_dprintf ("zfs", "alive\n");
+
+ grub_free (data->dnode_buf);
+ grub_free (data->dnode_mdn);
+ data->dnode_mdn = grub_malloc (sizeof (*mdn));
+ if (! data->dnode_mdn)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ data->dnode_buf = 0;
+ }
+ else
+ {
+ grub_memcpy (data->dnode_mdn, mdn, sizeof (*mdn));
+ data->dnode_buf = dnbuf;
+ data->dnode_start = blkid << epbs;
+ data->dnode_end = (blkid + 1) << epbs;
+ data->dnode_endian = endian;
+ }
+
+ grub_memmove (&(buf->dn), &dnbuf[idx], DNODE_SIZE);
+ buf->endian = endian;
+ if (type && buf->dn.dn_type != type)
+ return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type");
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Get the file dnode for a given file name where mdn is the meta dnode
+ * for this ZFS object set. When found, place the file dnode in dn.
+ * The 'path' argument will be mangled.
+ *
+ */
+static grub_err_t
+dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
+ struct grub_zfs_data *data)
+{
+ grub_uint64_t objnum, version;
+ char *cname, ch;
+ grub_err_t err = GRUB_ERR_NONE;
+ char *path, *path_buf;
+ struct dnode_chain
+ {
+ struct dnode_chain *next;
+ dnode_end_t dn;
+ };
+ struct dnode_chain *dnode_path = 0, *dn_new, *root;
+
+ dn_new = grub_malloc (sizeof (*dn_new));
+ if (! dn_new)
+ return grub_errno;
+ dn_new->next = 0;
+ dnode_path = root = dn_new;
+
+ err = dnode_get (mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
+ &(dnode_path->dn), data);
+ if (err)
+ {
+ grub_free (dn_new);
+ return err;
+ }
+
+ err = zap_lookup (&(dnode_path->dn), ZPL_VERSION_STR, &version, data);
+ if (err)
+ {
+ grub_free (dn_new);
+ return err;
+ }
+ if (version > ZPL_VERSION)
+ {
+ grub_free (dn_new);
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new ZPL version");
+ }
+
+ err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data);
+ if (err)
+ {
+ grub_free (dn_new);
+ return err;
+ }
+
+ err = dnode_get (mdn, objnum, 0, &(dnode_path->dn), data);
+ if (err)
+ {
+ grub_free (dn_new);
+ return err;
+ }
+
+ path = path_buf = grub_strdup (path_in);
+ if (!path_buf)
+ {
+ grub_free (dn_new);
+ return grub_errno;
+ }
+
+ while (1)
+ {
+ /* skip leading slashes */
+ while (*path == '/')
+ path++;
+ if (!*path)
+ break;
+ /* get the next component name */
+ cname = path;
+ while (*path && *path != '/')
+ path++;
+ /* Skip dot. */
+ if (cname + 1 == path && cname[0] == '.')
+ continue;
+ /* Handle double dot. */
+ if (cname + 2 == path && cname[0] == '.' && cname[1] == '.')
+ {
+ if (dn_new->next)
+ {
+ dn_new = dnode_path;
+ dnode_path = dn_new->next;
+ grub_free (dn_new);
+ }
+ else
+ {
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ "can't resolve ..");
+ break;
+ }
+ continue;
+ }
+
+ ch = *path;
+ *path = 0; /* ensure null termination */
+
+ if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
+ {
+ grub_free (path_buf);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+ }
+ err = zap_lookup (&(dnode_path->dn), cname, &objnum, data);
+ if (err)
+ break;
+
+ dn_new = grub_malloc (sizeof (*dn_new));
+ if (! dn_new)
+ {
+ err = grub_errno;
+ break;
+ }
+ dn_new->next = dnode_path;
+ dnode_path = dn_new;
+
+ objnum = ZFS_DIRENT_OBJ (objnum);
+ err = dnode_get (mdn, objnum, 0, &(dnode_path->dn), data);
+ if (err)
+ break;
+
+ *path = ch;
+#if 0
+ if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa && ch)
+ {
+ char *oldpath = path, *oldpathbuf = path_buf;
+ path = path_buf
+ = grub_malloc (sizeof (dnode_path->dn.dn.dn_bonus)
+ - sizeof (znode_phys_t) + grub_strlen (oldpath) + 1);
+ if (!path_buf)
+ {
+ grub_free (oldpathbuf);
+ return grub_errno;
+ }
+ grub_memcpy (path,
+ (char *) DN_BONUS(&dnode_path->dn.dn) + sizeof (znode_phys_t),
+ sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t));
+ path [sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)] = 0;
+ grub_memcpy (path + grub_strlen (path), oldpath,
+ grub_strlen (oldpath) + 1);
+
+ grub_free (oldpathbuf);
+ if (path[0] != '/')
+ {
+ dn_new = dnode_path;
+ dnode_path = dn_new->next;
+ grub_free (dn_new);
+ }
+ else while (dnode_path != root)
+ {
+ dn_new = dnode_path;
+ dnode_path = dn_new->next;
+ grub_free (dn_new);
+ }
+ }
+#endif
+ }
+
+ if (!err)
+ grub_memcpy (dn, &(dnode_path->dn), sizeof (*dn));
+
+ while (dnode_path)
+ {
+ dn_new = dnode_path->next;
+ grub_free (dnode_path);
+ dnode_path = dn_new;
+ }
+ grub_free (path_buf);
+ return err;
+}
+
+#if 0
+/*
+ * Get the default 'bootfs' property value from the rootpool.
+ *
+ */
+static grub_err_t
+get_default_bootfsobj (dnode_phys_t * mosmdn, grub_uint64_t * obj,
+ struct grub_zfs_data *data)
+{
+ grub_uint64_t objnum = 0;
+ dnode_phys_t *dn;
+ if (!dn)
+ return grub_errno;
+
+ if ((grub_errno = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT,
+ DMU_OT_OBJECT_DIRECTORY, dn, data)))
+ {
+ grub_free (dn);
+ return (grub_errno);
+ }
+
+ /*
+ * find the object number for 'pool_props', and get the dnode
+ * of the 'pool_props'.
+ */
+ if (zap_lookup (dn, DMU_POOL_PROPS, &objnum, data))
+ {
+ grub_free (dn);
+ return (GRUB_ERR_BAD_FS);
+ }
+ if ((grub_errno = dnode_get (mosmdn, objnum, DMU_OT_POOL_PROPS, dn, data)))
+ {
+ grub_free (dn);
+ return (grub_errno);
+ }
+ if (zap_lookup (dn, ZPOOL_PROP_BOOTFS, &objnum, data))
+ {
+ grub_free (dn);
+ return (GRUB_ERR_BAD_FS);
+ }
+
+ if (!objnum)
+ {
+ grub_free (dn);
+ return (GRUB_ERR_BAD_FS);
+ }
+
+ *obj = objnum;
+ return (0);
+}
+#endif
+/*
+ * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname),
+ * e.g. pool/rootfs, or a given object number (obj), e.g. the object number
+ * of pool/rootfs.
+ *
+ * If no fsname and no obj are given, return the DSL_DIR metadnode.
+ * If fsname is given, return its metadnode and its matching object number.
+ * If only obj is given, return the metadnode for this object number.
+ *
+ */
+static grub_err_t
+get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
+ dnode_end_t * mdn, struct grub_zfs_data *data)
+{
+ grub_uint64_t objnum;
+ grub_err_t err;
+
+ grub_dprintf ("zfs", "endian = %d\n", mosmdn->endian);
+
+ err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT,
+ DMU_OT_OBJECT_DIRECTORY, mdn, data);
+ if (err)
+ return err;
+
+ grub_dprintf ("zfs", "alive\n");
+
+ err = zap_lookup (mdn, DMU_POOL_ROOT_DATASET, &objnum, data);
+ if (err)
+ return err;
+
+ grub_dprintf ("zfs", "alive\n");
+
+ err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data);
+ if (err)
+ return err;
+
+ grub_dprintf ("zfs", "alive\n");
+
+ while (*fsname)
+ {
+ grub_uint64_t childobj;
+ char *cname, ch;
+
+ while (*fsname == '/')
+ fsname++;
+
+ if (! *fsname || *fsname == '@')
+ break;
+
+ cname = fsname;
+ while (*fsname && !grub_isspace (*fsname) && *fsname != '/')
+ fsname++;
+ ch = *fsname;
+ *fsname = 0;
+
+ childobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *) DN_BONUS (&mdn->dn)))->dd_child_dir_zapobj, mdn->endian);
+ err = dnode_get (mosmdn, childobj,
+ DMU_OT_DSL_DIR_CHILD_MAP, mdn, data);
+ if (err)
+ return err;
+
+ err = zap_lookup (mdn, cname, &objnum, data);
+ if (err)
+ return err;
+
+ err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data);
+ if (err)
+ return err;
+
+ *fsname = ch;
+ }
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
+{
+ objset_phys_t *osp;
+ blkptr_t *bp;
+ grub_size_t ospsize;
+ grub_err_t err;
+
+ grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
+
+ bp = &(((dsl_dataset_phys_t *) DN_BONUS (&mdn->dn))->ds_bp);
+ err = zio_read (bp, mdn->endian, (void **) &osp, &ospsize, data);
+ if (err)
+ return err;
+ if (ospsize < OBJSET_PHYS_SIZE_V14)
+ {
+ grub_free (osp);
+ return grub_error (GRUB_ERR_BAD_FS, "too small osp");
+ }
+
+ mdn->endian = (grub_zfs_to_cpu64 (bp->blk_prop, mdn->endian)>>63) & 1;
+ grub_memmove ((char *) &(mdn->dn), (char *) &osp->os_meta_dnode, DNODE_SIZE);
+ grub_free (osp);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
+ grub_uint64_t *mdnobj, dnode_end_t * dn, int *isfs,
+ struct grub_zfs_data *data)
+{
+ char *fsname, *snapname;
+ const char *ptr_at, *filename;
+ grub_uint64_t headobj;
+ grub_err_t err;
+
+ ptr_at = grub_strchr (fullpath, '@');
+ if (! ptr_at)
+ {
+ *isfs = 1;
+ filename = 0;
+ snapname = 0;
+ fsname = grub_strdup (fullpath);
+ }
+ else
+ {
+ const char *ptr_slash = grub_strchr (ptr_at, '/');
+
+ *isfs = 0;
+ fsname = grub_malloc (ptr_at - fullpath + 1);
+ if (!fsname)
+ return grub_errno;
+ grub_memcpy (fsname, fullpath, ptr_at - fullpath);
+ fsname[ptr_at - fullpath] = 0;
+ if (ptr_at[1] && ptr_at[1] != '/')
+ {
+ snapname = grub_malloc (ptr_slash - ptr_at);
+ if (!snapname)
+ {
+ grub_free (fsname);
+ return grub_errno;
+ }
+ grub_memcpy (snapname, ptr_at + 1, ptr_slash - ptr_at - 1);
+ snapname[ptr_slash - ptr_at - 1] = 0;
+ }
+ else
+ snapname = 0;
+ if (ptr_slash)
+ filename = ptr_slash;
+ else
+ filename = "/";
+ grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n",
+ fsname, snapname, filename);
+ }
+ grub_dprintf ("zfs", "alive\n");
+ err = get_filesystem_dnode (&(data->mos), fsname, dn, data);
+ if (err)
+ {
+ grub_free (fsname);
+ grub_free (snapname);
+ return err;
+ }
+
+ grub_dprintf ("zfs", "alive\n");
+
+ headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_head_dataset_obj, dn->endian);
+
+ grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
+
+ err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data);
+ if (err)
+ {
+ grub_free (fsname);
+ grub_free (snapname);
+ return err;
+ }
+ grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
+
+ if (snapname)
+ {
+ grub_uint64_t snapobj;
+
+ snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&mdn->dn))->ds_snapnames_zapobj, mdn->endian);
+
+ err = dnode_get (&(data->mos), snapobj,
+ DMU_OT_DSL_DS_SNAP_MAP, mdn, data);
+ if (!err)
+ err = zap_lookup (mdn, snapname, &headobj, data);
+ if (!err)
+ err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data);
+ if (err)
+ {
+ grub_free (fsname);
+ grub_free (snapname);
+ return err;
+ }
+ }
+
+ if (mdnobj)
+ *mdnobj = headobj;
+
+ make_mdn (mdn, data);
+
+ grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
+
+ if (*isfs)
+ {
+ grub_free (fsname);
+ grub_free (snapname);
+ return GRUB_ERR_NONE;
+ }
+ err = dnode_get_path (mdn, filename, dn, data);
+ grub_free (fsname);
+ grub_free (snapname);
+ return err;
+}
+
+/*
+ * For a given XDR packed nvlist, verify the first 4 bytes and move on.
+ *
+ * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
+ *
+ * encoding method/host endian (4 bytes)
+ * nvl_version (4 bytes)
+ * nvl_nvflag (4 bytes)
+ * encoded nvpairs:
+ * encoded size of the nvpair (4 bytes)
+ * decoded size of the nvpair (4 bytes)
+ * name string size (4 bytes)
+ * name string data (sizeof(NV_ALIGN4(string))
+ * data type (4 bytes)
+ * # of elements in the nvpair (4 bytes)
+ * data
+ * 2 zero's for the last nvpair
+ * (end of the entire list) (8 bytes)
+ *
+ */
+
+static int
+nvlist_find_value (char *nvlist, char *name, int valtype, char **val,
+ grub_size_t *size_out, grub_size_t *nelm_out)
+{
+ int name_len, type, encode_size;
+ char *nvpair, *nvp_name;
+
+ /* Verify if the 1st and 2nd byte in the nvlist are valid. */
+ /* NOTE: independently of what endianness header announces all
+ subsequent values are big-endian. */
+ if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN
+ && nvlist[1] != NV_BIG_ENDIAN))
+ {
+ grub_dprintf ("zfs", "incorrect nvlist header\n");
+ grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
+ return 0;
+ }
+
+ /* skip the header, nvl_version, and nvl_nvflag */
+ nvlist = nvlist + 4 * 3;
+ /*
+ * Loop thru the nvpair list
+ * The XDR representation of an integer is in big-endian byte order.
+ */
+ while ((encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvlist)))
+ {
+ int nelm;
+
+ nvpair = nvlist + 4 * 2; /* skip the encode/decode size */
+
+ name_len = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
+ nvpair += 4;
+
+ nvp_name = nvpair;
+ nvpair = nvpair + ((name_len + 3) & ~3); /* align */
+
+ type = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
+ nvpair += 4;
+
+ nelm = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
+ if (nelm < 1)
+ return grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
+
+ nvpair += 4;
+
+ if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype)
+ {
+ *val = nvpair;
+ *size_out = encode_size;
+ if (nelm_out)
+ *nelm_out = nelm;
+ return 1;
+ }
+
+ nvlist += encode_size; /* goto the next nvpair */
+ }
+ return 0;
+}
+
+int
+grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name, grub_uint64_t * out)
+{
+ char *nvpair;
+ grub_size_t size;
+ int found;
+
+ found = nvlist_find_value (nvlist, name, DATA_TYPE_UINT64, &nvpair, &size, 0);
+ if (!found)
+ return 0;
+ if (size < sizeof (grub_uint64_t))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "invalid uint64");
+ return 0;
+ }
+
+ *out = grub_be_to_cpu64 (*(grub_uint64_t *) nvpair);
+ return 1;
+}
+
+char *
+grub_zfs_nvlist_lookup_string (char *nvlist, char *name)
+{
+ char *nvpair;
+ char *ret;
+ grub_size_t slen;
+ grub_size_t size;
+ int found;
+
+ found = nvlist_find_value (nvlist, name, DATA_TYPE_STRING, &nvpair, &size, 0);
+ if (!found)
+ return 0;
+ if (size < 4)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "invalid string");
+ return 0;
+ }
+ slen = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
+ if (slen > size - 4)
+ slen = size - 4;
+ ret = grub_malloc (slen + 1);
+ if (!ret)
+ return 0;
+ grub_memcpy (ret, nvpair + 4, slen);
+ ret[slen] = 0;
+ return ret;
+}
+
+char *
+grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name)
+{
+ char *nvpair;
+ char *ret;
+ grub_size_t size;
+ int found;
+
+ found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
+ &size, 0);
+ if (!found)
+ return 0;
+ ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t));
+ if (!ret)
+ return 0;
+ grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
+
+ grub_memcpy (ret + sizeof (grub_uint32_t), nvpair, size);
+ return ret;
+}
+
+int
+grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name)
+{
+ char *nvpair;
+ grub_size_t nelm, size;
+ int found;
+
+ found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
+ &size, &nelm);
+ if (! found)
+ return -1;
+ return nelm;
+}
+
+char *
+grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
+ grub_size_t index)
+{
+ char *nvpair, *nvpairptr;
+ int found;
+ char *ret;
+ grub_size_t size;
+ unsigned i;
+ grub_size_t nelm;
+
+ found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
+ &size, &nelm);
+ if (!found)
+ return 0;
+ if (index >= nelm)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "trying to lookup past nvlist array");
+ return 0;
+ }
+
+ nvpairptr = nvpair;
+
+ for (i = 0; i < index; i++)
+ {
+ grub_uint32_t encode_size;
+
+ /* skip the header, nvl_version, and nvl_nvflag */
+ nvpairptr = nvpairptr + 4 * 2;
+
+ while (nvpairptr < nvpair + size
+ && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvpairptr)))
+ nvlist += encode_size; /* goto the next nvpair */
+
+ nvlist = nvlist + 4 * 2; /* skip the ending 2 zeros - 8 bytes */
+ }
+
+ if (nvpairptr >= nvpair + size
+ || nvpairptr + grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2))
+ >= nvpair + size)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist array");
+ return 0;
+ }
+
+ ret = grub_zalloc (grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2))
+ + 3 * sizeof (grub_uint32_t));
+ if (!ret)
+ return 0;
+ grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
+
+ grub_memcpy (ret + sizeof (grub_uint32_t), nvpairptr, size);
+ return ret;
+}
+
+static grub_err_t
+zfs_fetch_nvlist (struct grub_zfs_data * data, char **nvlist)
+{
+ grub_err_t err;
+
+ *nvlist = grub_malloc (VDEV_PHYS_SIZE);
+ /* Read in the vdev name-value pair list (112K). */
+ err = grub_disk_read (data->disk, data->vdev_phys_sector, 0,
+ VDEV_PHYS_SIZE, *nvlist);
+ if (err)
+ {
+ grub_free (*nvlist);
+ *nvlist = 0;
+ return err;
+ }
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Check the disk label information and retrieve needed vdev name-value pairs.
+ *
+ */
+static grub_err_t
+check_pool_label (struct grub_zfs_data *data)
+{
+ grub_uint64_t pool_state, txg = 0;
+ char *nvlist;
+#if 0
+ char *nv;
+#endif
+ grub_uint64_t diskguid;
+ grub_uint64_t version;
+ int found;
+ grub_err_t err;
+
+ err = zfs_fetch_nvlist (data, &nvlist);
+ if (err)
+ return err;
+
+ grub_dprintf ("zfs", "check 2 passed\n");
+
+ found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
+ &pool_state);
+ if (! found)
+ {
+ grub_free (nvlist);
+ if (! grub_errno)
+ grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_STATE " not found");
+ return grub_errno;
+ }
+ grub_dprintf ("zfs", "check 3 passed\n");
+
+ if (pool_state == POOL_STATE_DESTROYED)
+ {
+ grub_free (nvlist);
+ return grub_error (GRUB_ERR_BAD_FS, "zpool is marked as destroyed");
+ }
+ grub_dprintf ("zfs", "check 4 passed\n");
+
+ found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_TXG, &txg);
+ if (!found)
+ {
+ grub_free (nvlist);
+ if (! grub_errno)
+ grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_TXG " not found");
+ return grub_errno;
+ }
+ grub_dprintf ("zfs", "check 6 passed\n");
+
+ /* not an active device */
+ if (txg == 0)
+ {
+ grub_free (nvlist);
+ return grub_error (GRUB_ERR_BAD_FS, "zpool isn't active");
+ }
+ grub_dprintf ("zfs", "check 7 passed\n");
+
+ found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_VERSION,
+ &version);
+ if (! found)
+ {
+ grub_free (nvlist);
+ if (! grub_errno)
+ grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_VERSION " not found");
+ return grub_errno;
+ }
+ grub_dprintf ("zfs", "check 8 passed\n");
+
+ if (version > SPA_VERSION)
+ {
+ grub_free (nvlist);
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "too new version %llu > %llu",
+ (unsigned long long) version,
+ (unsigned long long) SPA_VERSION);
+ }
+ grub_dprintf ("zfs", "check 9 passed\n");
+#if 0
+ if (nvlist_lookup_value (nvlist, ZPOOL_CONFIG_VDEV_TREE, &nv,
+ DATA_TYPE_NVLIST, NULL))
+ {
+ grub_free (vdev);
+ return (GRUB_ERR_BAD_FS);
+ }
+ grub_dprintf ("zfs", "check 10 passed\n");
+#endif
+
+ found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, &diskguid);
+ if (! found)
+ {
+ grub_free (nvlist);
+ if (! grub_errno)
+ grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_GUID " not found");
+ return grub_errno;
+ }
+ grub_dprintf ("zfs", "check 11 passed\n");
+
+ grub_free (nvlist);
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+zfs_unmount (struct grub_zfs_data *data)
+{
+ grub_free (data->dnode_buf);
+ grub_free (data->dnode_mdn);
+ grub_free (data->file_buf);
+ grub_free (data);
+}
+
+/*
+ * zfs_mount() locates a valid uberblock of the root pool and read in its MOS
+ * to the memory address MOS.
+ *
+ */
+static struct grub_zfs_data *
+zfs_mount (grub_device_t dev)
+{
+ struct grub_zfs_data *data = 0;
+ int label = 0;
+ uberblock_phys_t *ub_array, *ubbest = NULL;
+ vdev_boot_header_t *bh;
+ objset_phys_t *osp = 0;
+ grub_size_t ospsize;
+ grub_err_t err;
+ int vdevnum;
+
+ if (! dev->disk)
+ {
+ grub_error (GRUB_ERR_BAD_DEVICE, "not a disk");
+ return 0;
+ }
+
+ data = grub_malloc (sizeof (*data));
+ if (!data)
+ return 0;
+ grub_memset (data, 0, sizeof (*data));
+#if 0
+ /* if it's our first time here, zero the best uberblock out */
+ if (data->best_drive == 0 && data->best_part == 0 && find_best_root)
+ grub_memset (&current_uberblock, 0, sizeof (uberblock_t));
+#endif
+
+ data->disk = dev->disk;
+
+ ub_array = grub_malloc (VDEV_UBERBLOCK_RING);
+ if (!ub_array)
+ {
+ zfs_unmount (data);
+ return 0;
+ }
+
+ bh = grub_malloc (VDEV_BOOT_HEADER_SIZE);
+ if (!bh)
+ {
+ zfs_unmount (data);
+ grub_free (ub_array);
+ return 0;
+ }
+
+ vdevnum = VDEV_LABELS;
+
+ /* Don't check back labels on CDROM. */
+ if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
+ vdevnum = VDEV_LABELS / 2;
+
+ for (label = 0; ubbest == NULL && label < vdevnum; label++)
+ {
+ grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN;
+ grub_dprintf ("zfs", "label %d\n", label);
+
+ data->vdev_phys_sector
+ = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
+ + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
+ + (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (dev->disk)
+ - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
+
+ /* Read in the uberblock ring (128K). */
+ err = grub_disk_read (data->disk, data->vdev_phys_sector
+ + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT),
+ 0, VDEV_UBERBLOCK_RING, (char *) ub_array);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ grub_dprintf ("zfs", "label ok %d\n", label);
+
+ ubbest = find_bestub (ub_array, data->vdev_phys_sector);
+ if (!ubbest)
+ {
+ grub_dprintf ("zfs", "No uberblock found\n");
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ ub_endian = (grub_zfs_to_cpu64 (ubbest->ubp_uberblock.ub_magic,
+ LITTLE_ENDIAN) == UBERBLOCK_MAGIC
+ ? LITTLE_ENDIAN : BIG_ENDIAN);
+ err = zio_read (&ubbest->ubp_uberblock.ub_rootbp,
+ ub_endian,
+ (void **) &osp, &ospsize, data);
+ if (err)
+ {
+ grub_dprintf ("zfs", "couldn't zio_read\n");
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ if (ospsize < OBJSET_PHYS_SIZE_V14)
+ {
+ grub_dprintf ("zfs", "osp too small\n");
+ grub_free (osp);
+ continue;
+ }
+ grub_dprintf ("zfs", "ubbest %p\n", ubbest);
+
+ err = check_pool_label (data);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+#if 0
+ if (find_best_root &&
+ vdev_uberblock_compare (&ubbest->ubp_uberblock,
+ &(current_uberblock)) <= 0)
+ continue;
+#endif
+ /* Got the MOS. Save it at the memory addr MOS. */
+ grub_memmove (&(data->mos.dn), &osp->os_meta_dnode, DNODE_SIZE);
+ data->mos.endian = (grub_zfs_to_cpu64 (ubbest->ubp_uberblock.ub_rootbp.blk_prop, ub_endian) >> 63) & 1;
+ grub_memmove (&(data->current_uberblock),
+ &ubbest->ubp_uberblock, sizeof (uberblock_t));
+ grub_free (ub_array);
+ grub_free (bh);
+ grub_free (osp);
+ return data;
+ }
+ grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
+ zfs_unmount (data);
+ grub_free (ub_array);
+ grub_free (bh);
+ grub_free (osp);
+
+ return 0;
+}
+
+grub_err_t
+grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist)
+{
+ struct grub_zfs_data *zfs;
+ grub_err_t err;
+
+ zfs = zfs_mount (dev);
+ if (!zfs)
+ return grub_errno;
+ err = zfs_fetch_nvlist (zfs, nvlist);
+ zfs_unmount (zfs);
+ return err;
+}
+
+static grub_err_t
+zfs_label (grub_device_t device, char **label)
+{
+ char *nvlist;
+ grub_err_t err;
+ struct grub_zfs_data *data;
+
+ data = zfs_mount (device);
+ if (! data)
+ return grub_errno;
+
+ err = zfs_fetch_nvlist (data, &nvlist);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+
+ *label = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
+ grub_free (nvlist);
+ zfs_unmount (data);
+ return grub_errno;
+}
+
+static grub_err_t
+zfs_uuid (grub_device_t device, char **uuid)
+{
+ char *nvlist;
+ int found;
+ struct grub_zfs_data *data;
+ grub_uint64_t guid;
+ grub_err_t err;
+
+ *uuid = 0;
+
+ data = zfs_mount (device);
+ if (! data)
+ return grub_errno;
+
+ err = zfs_fetch_nvlist (data, &nvlist);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+
+ found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
+ if (! found)
+ return grub_errno;
+ grub_free (nvlist);
+ *uuid = grub_xasprintf ("%016llx", (long long unsigned) guid);
+ zfs_unmount (data);
+ if (! *uuid)
+ return grub_errno;
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * zfs_open() locates a file in the rootpool by following the
+ * MOS and places the dnode of the file in the memory address DNODE.
+ */
+static grub_err_t
+grub_zfs_open (struct grub_file *file, const char *fsfilename)
+{
+ struct grub_zfs_data *data;
+ grub_err_t err;
+ int isfs;
+
+ data = zfs_mount (file->device);
+ if (! data)
+ return grub_errno;
+
+ err = dnode_get_fullpath (fsfilename, &(data->mdn), 0,
+ &(data->dnode), &isfs, data);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+
+ if (isfs)
+ {
+ zfs_unmount (data);
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Missing @ or / separator");
+ }
+
+ /* We found the dnode for this file. Verify if it is a plain file. */
+ if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS)
+ {
+ zfs_unmount (data);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
+ }
+
+ /* get the file size and set the file position to 0 */
+
+ /*
+ * For DMU_OT_SA we will need to locate the SIZE attribute
+ * attribute, which could be either in the bonus buffer
+ * or the "spill" block.
+ */
+ if (data->dnode.dn.dn_bonustype == DMU_OT_SA)
+ {
+ sa_hdr_phys_t *sahdrp;
+ int hdrsize;
+
+ if (data->dnode.dn.dn_bonuslen != 0)
+ {
+ sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
+ }
+ else if (data->dnode.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
+ {
+ blkptr_t *bp = &data->dnode.dn.dn_spill;
+
+ err = zio_read (bp, data->dnode.endian, (void **) &sahdrp, NULL, data);
+ if (err)
+ return err;
+ }
+ else
+ {
+ return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
+ }
+
+ hdrsize = SA_HDR_SIZE (sahdrp);
+ file->size = *(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET);
+ }
+ else
+ {
+ file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian);
+ }
+
+ file->data = data;
+ file->offset = 0;
+
+#ifndef GRUB_UTIL
+ grub_dl_ref (my_mod);
+#endif
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+grub_zfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+ struct grub_zfs_data *data = (struct grub_zfs_data *) file->data;
+ int blksz, movesize;
+ grub_size_t length;
+ grub_size_t read;
+ grub_err_t err;
+
+ if (data->file_buf == NULL)
+ {
+ data->file_buf = grub_malloc (SPA_MAXBLOCKSIZE);
+ if (!data->file_buf)
+ return -1;
+ data->file_start = data->file_end = 0;
+ }
+
+ /*
+ * If offset is in memory, move it into the buffer provided and return.
+ */
+ if (file->offset >= data->file_start
+ && file->offset + len <= data->file_end)
+ {
+ grub_memmove (buf, data->file_buf + file->offset - data->file_start,
+ len);
+ return len;
+ }
+
+ blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec,
+ data->dnode.endian) << SPA_MINBLOCKSHIFT;
+
+ /*
+ * Entire Dnode is too big to fit into the space available. We
+ * will need to read it in chunks. This could be optimized to
+ * read in as large a chunk as there is space available, but for
+ * now, this only reads in one data block at a time.
+ */
+ length = len;
+ read = 0;
+ while (length)
+ {
+ /*
+ * Find requested blkid and the offset within that block.
+ */
+ grub_uint64_t blkid = grub_divmod64 (file->offset + read, blksz, 0);
+ grub_free (data->file_buf);
+ data->file_buf = 0;
+
+ err = dmu_read (&(data->dnode), blkid, (void **) &(data->file_buf),
+ 0, data);
+ if (err)
+ return -1;
+
+ data->file_start = blkid * blksz;
+ data->file_end = data->file_start + blksz;
+
+ movesize = MIN (length, data->file_end - (int) file->offset - read);
+
+ grub_memmove (buf, data->file_buf + file->offset + read
+ - data->file_start, movesize);
+ buf += movesize;
+ length -= movesize;
+ read += movesize;
+ }
+
+ return len;
+}
+
+static grub_err_t
+grub_zfs_close (grub_file_t file)
+{
+ zfs_unmount ((struct grub_zfs_data *) file->data);
+
+#ifndef GRUB_UTIL
+ grub_dl_unref (my_mod);
+#endif
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
+ grub_uint64_t *mdnobj)
+{
+ struct grub_zfs_data *data;
+ grub_err_t err;
+ int isfs;
+
+ data = zfs_mount (dev);
+ if (! data)
+ return grub_errno;
+
+ err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj,
+ &(data->dnode), &isfs, data);
+ zfs_unmount (data);
+ return err;
+}
+
+static void
+fill_fs_info (struct grub_dirhook_info *info,
+ dnode_end_t mdn, struct grub_zfs_data *data)
+{
+ grub_err_t err;
+ dnode_end_t dn;
+ grub_uint64_t objnum;
+ grub_uint64_t headobj;
+
+ grub_memset (info, 0, sizeof (*info));
+
+ info->dir = 1;
+
+ if (mdn.dn.dn_type == DMU_OT_DSL_DIR)
+ {
+ headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian);
+
+ err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data);
+ if (err)
+ {
+ grub_dprintf ("zfs", "failed here\n");
+ return;
+ }
+ }
+ make_mdn (&mdn, data);
+ err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
+ &dn, data);
+ if (err)
+ {
+ grub_dprintf ("zfs", "failed here\n");
+ return;
+ }
+
+ err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data);
+ if (err)
+ {
+ grub_dprintf ("zfs", "failed here\n");
+ return;
+ }
+
+ err = dnode_get (&mdn, objnum, 0, &dn, data);
+ if (err)
+ {
+ grub_dprintf ("zfs", "failed here\n");
+ return;
+ }
+
+ info->mtimeset = 1;
+ info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
+ return;
+}
+
+static grub_err_t
+grub_zfs_dir (grub_device_t device, const char *path,
+ int (*hook) (const char *, const struct grub_dirhook_info *))
+{
+ struct grub_zfs_data *data;
+ grub_err_t err;
+ int isfs;
+ auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
+ auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name,
+ grub_uint64_t val);
+ auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name,
+ grub_uint64_t val);
+
+ int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val)
+ {
+ struct grub_dirhook_info info;
+ dnode_end_t dn;
+ grub_memset (&info, 0, sizeof (info));
+
+ dnode_get (&(data->mdn), val, 0, &dn, data);
+ info.mtimeset = 1;
+ info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
+ info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
+ grub_dprintf ("zfs", "type=%d, name=%s\n",
+ (int)dn.dn.dn_type, (char *)name);
+ return hook (name, &info);
+ }
+
+ int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val)
+ {
+ struct grub_dirhook_info info;
+ dnode_end_t mdn;
+ err = dnode_get (&(data->mos), val, 0, &mdn, data);
+ if (err)
+ return 0;
+ if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
+ return 0;
+
+ fill_fs_info (&info, mdn, data);
+ return hook (name, &info);
+ }
+ int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
+ {
+ struct grub_dirhook_info info;
+ char *name2;
+ int ret;
+ dnode_end_t mdn;
+
+ err = dnode_get (&(data->mos), val, 0, &mdn, data);
+ if (err)
+ return 0;
+
+ if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
+ return 0;
+
+ fill_fs_info (&info, mdn, data);
+
+ name2 = grub_malloc (grub_strlen (name) + 2);
+ name2[0] = '@';
+ grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
+ ret = hook (name2, &info);
+ grub_free (name2);
+ return ret;
+ }
+
+ data = zfs_mount (device);
+ if (! data)
+ return grub_errno;
+ err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+ if (isfs)
+ {
+ grub_uint64_t childobj, headobj;
+ grub_uint64_t snapobj;
+ dnode_end_t dn;
+ struct grub_dirhook_info info;
+
+ fill_fs_info (&info, data->dnode, data);
+ hook ("@", &info);
+
+ childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian);
+ headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian);
+ err = dnode_get (&(data->mos), childobj,
+ DMU_OT_DSL_DIR_CHILD_MAP, &dn, data);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+
+ zap_iterate (&dn, iterate_zap_fs, data);
+
+ err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+
+ snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&dn.dn))->ds_snapnames_zapobj, dn.endian);
+
+ err = dnode_get (&(data->mos), snapobj,
+ DMU_OT_DSL_DS_SNAP_MAP, &dn, data);
+ if (err)
+ {
+ zfs_unmount (data);
+ return err;
+ }
+
+ zap_iterate (&dn, iterate_zap_snap, data);
+ }
+ else
+ {
+ if (data->dnode.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
+ {
+ zfs_unmount (data);
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+ }
+ zap_iterate (&(data->dnode), iterate_zap, data);
+ }
+ zfs_unmount (data);
+ return grub_errno;
+}
+
+static struct grub_fs grub_zfs_fs = {
+ .name = "zfs",
+ .dir = grub_zfs_dir,
+ .open = grub_zfs_open,
+ .read = grub_zfs_read,
+ .close = grub_zfs_close,
+ .label = zfs_label,
+ .uuid = zfs_uuid,
+ .mtime = 0,
+ .next = 0
+};
+
+GRUB_MOD_INIT (zfs)
+{
+ grub_fs_register (&grub_zfs_fs);
+#ifndef GRUB_UTIL
+ my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI (zfs)
+{
+ grub_fs_unregister (&grub_zfs_fs);
+}
diff --git a/debian/grub-extras/disabled/zfs/zfs_fletcher.c b/debian/grub-extras/disabled/zfs/zfs_fletcher.c
new file mode 100644
index 0000000..eaed15a
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/zfs_fletcher.c
@@ -0,0 +1,86 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright 2007 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+#include <grub/zfs/zfs.h>
+#include <grub/zfs/zio.h>
+#include <grub/zfs/dnode.h>
+#include <grub/zfs/uberblock_impl.h>
+#include <grub/zfs/vdev_impl.h>
+#include <grub/zfs/zio_checksum.h>
+#include <grub/zfs/zap_impl.h>
+#include <grub/zfs/zap_leaf.h>
+#include <grub/zfs/zfs_znode.h>
+#include <grub/zfs/dmu.h>
+#include <grub/zfs/dmu_objset.h>
+#include <grub/zfs/dsl_dir.h>
+#include <grub/zfs/dsl_dataset.h>
+
+void
+fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian,
+ zio_cksum_t *zcp)
+{
+ const grub_uint64_t *ip = buf;
+ const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t));
+ grub_uint64_t a0, b0, a1, b1;
+
+ for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2)
+ {
+ a0 += grub_zfs_to_cpu64 (ip[0], endian);
+ a1 += grub_zfs_to_cpu64 (ip[1], endian);
+ b0 += a0;
+ b1 += a1;
+ }
+
+ zcp->zc_word[0] = grub_cpu_to_zfs64 (a0, endian);
+ zcp->zc_word[1] = grub_cpu_to_zfs64 (a1, endian);
+ zcp->zc_word[2] = grub_cpu_to_zfs64 (b0, endian);
+ zcp->zc_word[3] = grub_cpu_to_zfs64 (b1, endian);
+}
+
+void
+fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian,
+ zio_cksum_t *zcp)
+{
+ const grub_uint32_t *ip = buf;
+ const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t));
+ grub_uint64_t a, b, c, d;
+
+ for (a = b = c = d = 0; ip < ipend; ip++)
+ {
+ a += grub_zfs_to_cpu32 (ip[0], endian);;
+ b += a;
+ c += b;
+ d += c;
+ }
+
+ zcp->zc_word[0] = grub_cpu_to_zfs64 (a, endian);
+ zcp->zc_word[1] = grub_cpu_to_zfs64 (b, endian);
+ zcp->zc_word[2] = grub_cpu_to_zfs64 (c, endian);
+ zcp->zc_word[3] = grub_cpu_to_zfs64 (d, endian);
+}
+
diff --git a/debian/grub-extras/disabled/zfs/zfs_lzjb.c b/debian/grub-extras/disabled/zfs/zfs_lzjb.c
new file mode 100644
index 0000000..0965d2d
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/zfs_lzjb.c
@@ -0,0 +1,95 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright 2007 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+#include <grub/zfs/zfs.h>
+#include <grub/zfs/zio.h>
+#include <grub/zfs/dnode.h>
+#include <grub/zfs/uberblock_impl.h>
+#include <grub/zfs/vdev_impl.h>
+#include <grub/zfs/zio_checksum.h>
+#include <grub/zfs/zap_impl.h>
+#include <grub/zfs/zap_leaf.h>
+#include <grub/zfs/zfs_znode.h>
+#include <grub/zfs/dmu.h>
+#include <grub/zfs/dmu_objset.h>
+#include <grub/zfs/dsl_dir.h>
+#include <grub/zfs/dsl_dataset.h>
+
+#define MATCH_BITS 6
+#define MATCH_MIN 3
+#define OFFSET_MASK ((1 << (16 - MATCH_BITS)) - 1)
+
+/*
+ * Decompression Entry - lzjb
+ */
+#ifndef NBBY
+#define NBBY 8
+#endif
+
+grub_err_t
+lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
+ grub_size_t d_len);
+
+grub_err_t
+lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
+ grub_size_t d_len)
+{
+ grub_uint8_t *src = s_start;
+ grub_uint8_t *dst = d_start;
+ grub_uint8_t *d_end = (grub_uint8_t *) d_start + d_len;
+ grub_uint8_t *s_end = (grub_uint8_t *) s_start + s_len;
+ grub_uint8_t *cpy, copymap = 0;
+ int copymask = 1 << (NBBY - 1);
+
+ while (dst < d_end && src < s_end)
+ {
+ if ((copymask <<= 1) == (1 << NBBY))
+ {
+ copymask = 1;
+ copymap = *src++;
+ }
+ if (src >= s_end)
+ return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
+ if (copymap & copymask)
+ {
+ int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
+ int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
+ src += 2;
+ cpy = dst - offset;
+ if (src > s_end || cpy < (grub_uint8_t *) d_start)
+ return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
+ while (--mlen >= 0 && dst < d_end)
+ *dst++ = *cpy++;
+ }
+ else
+ *dst++ = *src++;
+ }
+ if (dst < d_end)
+ return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
+ return GRUB_ERR_NONE;
+}
diff --git a/debian/grub-extras/disabled/zfs/zfs_sha256.c b/debian/grub-extras/disabled/zfs/zfs_sha256.c
new file mode 100644
index 0000000..3dc7926
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/zfs_sha256.c
@@ -0,0 +1,145 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright 2007 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+#include <grub/zfs/zfs.h>
+#include <grub/zfs/zio.h>
+#include <grub/zfs/dnode.h>
+#include <grub/zfs/uberblock_impl.h>
+#include <grub/zfs/vdev_impl.h>
+#include <grub/zfs/zio_checksum.h>
+#include <grub/zfs/zap_impl.h>
+#include <grub/zfs/zap_leaf.h>
+#include <grub/zfs/zfs_znode.h>
+#include <grub/zfs/dmu.h>
+#include <grub/zfs/dmu_objset.h>
+#include <grub/zfs/dsl_dir.h>
+#include <grub/zfs/dsl_dataset.h>
+
+/*
+ * SHA-256 checksum, as specified in FIPS 180-2, available at:
+ * http://csrc.nist.gov/cryptval
+ *
+ * This is a very compact implementation of SHA-256.
+ * It is designed to be simple and portable, not to be fast.
+ */
+
+/*
+ * The literal definitions according to FIPS180-2 would be:
+ *
+ * Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
+ * Maj(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+ *
+ * We use logical equivalents which require one less op.
+ */
+#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define Maj(x, y, z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))
+#define Rot32(x, s) (((x) >> s) | ((x) << (32 - s)))
+#define SIGMA0(x) (Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
+#define SIGMA1(x) (Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
+#define sigma0(x) (Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
+#define sigma1(x) (Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
+
+static const grub_uint32_t SHA256_K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+static void
+SHA256Transform(grub_uint32_t *H, const grub_uint8_t *cp)
+{
+ grub_uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
+
+ for (t = 0; t < 16; t++, cp += 4)
+ W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
+
+ for (t = 16; t < 64; t++)
+ W[t] = sigma1(W[t - 2]) + W[t - 7] +
+ sigma0(W[t - 15]) + W[t - 16];
+
+ a = H[0]; b = H[1]; c = H[2]; d = H[3];
+ e = H[4]; f = H[5]; g = H[6]; h = H[7];
+
+ for (t = 0; t < 64; t++) {
+ T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
+ T2 = SIGMA0(a) + Maj(a, b, c);
+ h = g; g = f; f = e; e = d + T1;
+ d = c; c = b; b = a; a = T1 + T2;
+ }
+
+ H[0] += a; H[1] += b; H[2] += c; H[3] += d;
+ H[4] += e; H[5] += f; H[6] += g; H[7] += h;
+}
+
+void
+zio_checksum_SHA256(const void *buf, grub_uint64_t size,
+ grub_zfs_endian_t endian, zio_cksum_t *zcp)
+{
+ grub_uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
+ grub_uint8_t pad[128];
+ unsigned padsize = size & 63;
+ unsigned i;
+
+ for (i = 0; i < size - padsize; i += 64)
+ SHA256Transform(H, (grub_uint8_t *)buf + i);
+
+ for (i = 0; i < padsize; i++)
+ pad[i] = ((grub_uint8_t *)buf)[i];
+
+ for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
+ pad[padsize] = 0;
+
+ for (i = 0; i < 8; i++)
+ pad[padsize++] = (size << 3) >> (56 - 8 * i);
+
+ for (i = 0; i < padsize; i += 64)
+ SHA256Transform(H, pad + i);
+
+ zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1],
+ endian);
+ zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3],
+ endian);
+ zcp->zc_word[2] = grub_cpu_to_zfs64 ((grub_uint64_t)H[4] << 32 | H[5],
+ endian);
+ zcp->zc_word[3] = grub_cpu_to_zfs64 ((grub_uint64_t)H[6] << 32 | H[7],
+ endian);
+}
diff --git a/debian/grub-extras/disabled/zfs/zfsinfo.c b/debian/grub-extras/disabled/zfs/zfsinfo.c
new file mode 100644
index 0000000..a9a1350
--- /dev/null
+++ b/debian/grub-extras/disabled/zfs/zfsinfo.c
@@ -0,0 +1,414 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ * Copyright 2008 Sun Microsystems, Inc.
+ * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/zfs/zfs.h>
+#include <grub/device.h>
+#include <grub/file.h>
+#include <grub/command.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+
+static inline void
+print_tabs (int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ grub_printf (" ");
+}
+
+static grub_err_t
+print_state (char *nvlist, int tab)
+{
+ grub_uint64_t ival;
+ int isok = 1;
+
+ print_tabs (tab);
+ grub_printf ("State: ");
+
+ if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival))
+ {
+ grub_printf ("removed ");
+ isok = 0;
+ }
+
+ if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
+ {
+ grub_printf ("faulted ");
+ isok = 0;
+ }
+
+ if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival))
+ {
+ grub_printf ("offline ");
+ isok = 0;
+ }
+
+ if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
+ grub_printf ("degraded ");
+
+ if (isok)
+ grub_printf ("online");
+ grub_printf ("\n");
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+print_vdev_info (char *nvlist, int tab)
+{
+ char *type = 0;
+
+ type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
+
+ if (!type)
+ {
+ print_tabs (tab);
+ grub_printf ("Incorrect VDEV: no type available\n");
+ return grub_errno;
+ }
+
+ if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
+ {
+ char *bootpath = 0;
+ char *path = 0;
+ char *devid = 0;
+
+ print_tabs (tab);
+ grub_printf ("Leaf VDEV\n");
+
+ print_state (nvlist, tab);
+
+ bootpath =
+ grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH);
+ print_tabs (tab);
+ if (!bootpath)
+ grub_printf ("Bootpath: unavailable\n");
+ else
+ grub_printf ("Bootpath: %s\n", bootpath);
+
+ path = grub_zfs_nvlist_lookup_string (nvlist, "path");
+ print_tabs (tab);
+ if (!path)
+ grub_printf ("Path: unavailable\n");
+ else
+ grub_printf ("Path: %s\n", path);
+
+ devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
+ print_tabs (tab);
+ if (!devid)
+ grub_printf ("Devid: unavailable\n");
+ else
+ grub_printf ("Devid: %s\n", devid);
+ grub_free (bootpath);
+ grub_free (devid);
+ grub_free (path);
+ return GRUB_ERR_NONE;
+ }
+
+ if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
+ {
+ int nelm, i;
+
+ nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
+ (nvlist, ZPOOL_CONFIG_CHILDREN);
+
+ print_tabs (tab);
+ if (nelm <= 0)
+ {
+ grub_printf ("Incorrect mirror VDEV\n");
+ return GRUB_ERR_NONE;
+ }
+ grub_printf ("Mirror VDEV with %d children\n", nelm);
+ print_state (nvlist, tab);
+
+ for (i = 0; i < nelm; i++)
+ {
+ char *child;
+
+ child = grub_zfs_nvlist_lookup_nvlist_array
+ (nvlist, ZPOOL_CONFIG_CHILDREN, i);
+
+ print_tabs (tab);
+ if (!child)
+ {
+ grub_printf ("Mirror VDEV element %d isn't correct\n", i);
+ continue;
+ }
+
+ grub_printf ("Mirror VDEV element %d:\n", i);
+ print_vdev_info (child, tab + 1);
+
+ grub_free (child);
+ }
+ }
+
+ print_tabs (tab);
+ grub_printf ("Unknown VDEV type: %s\n", type);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+get_bootpath (char *nvlist, char **bootpath, char **devid)
+{
+ char *type = 0;
+
+ type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
+
+ if (!type)
+ return grub_errno;
+
+ if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
+ {
+ *bootpath = grub_zfs_nvlist_lookup_string (nvlist,
+ ZPOOL_CONFIG_PHYS_PATH);
+ *devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
+ if (!*bootpath || !*devid)
+ {
+ grub_free (*bootpath);
+ grub_free (*devid);
+ *bootpath = 0;
+ *devid = 0;
+ }
+ return GRUB_ERR_NONE;
+ }
+
+ if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
+ {
+ int nelm, i;
+
+ nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
+ (nvlist, ZPOOL_CONFIG_CHILDREN);
+
+ for (i = 0; i < nelm; i++)
+ {
+ char *child;
+
+ child = grub_zfs_nvlist_lookup_nvlist_array (nvlist,
+ ZPOOL_CONFIG_CHILDREN,
+ i);
+
+ get_bootpath (child, bootpath, devid);
+
+ grub_free (child);
+
+ if (*bootpath && *devid)
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static char *poolstates[] = {
+ [POOL_STATE_ACTIVE] = "active",
+ [POOL_STATE_EXPORTED] = "exported",
+ [POOL_STATE_DESTROYED] = "destroyed",
+ [POOL_STATE_SPARE] = "reserved for hot spare",
+ [POOL_STATE_L2CACHE] = "level 2 ARC device",
+ [POOL_STATE_UNINITIALIZED] = "uninitialized",
+ [POOL_STATE_UNAVAIL] = "unavailable",
+ [POOL_STATE_POTENTIALLY_ACTIVE] = "potentially active"
+};
+
+static grub_err_t
+grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc,
+ char **args)
+{
+ grub_device_t dev;
+ char *devname;
+ grub_err_t err;
+ char *nvlist = 0;
+ char *nv = 0;
+ char *poolname;
+ grub_uint64_t guid;
+ grub_uint64_t pool_state;
+ int found;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+
+ if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
+ {
+ devname = grub_strdup (args[0] + 1);
+ if (devname)
+ devname[grub_strlen (devname) - 1] = 0;
+ }
+ else
+ devname = grub_strdup (args[0]);
+ if (!devname)
+ return grub_errno;
+
+ dev = grub_device_open (devname);
+ grub_free (devname);
+ if (!dev)
+ return grub_errno;
+
+ err = grub_zfs_fetch_nvlist (dev, &nvlist);
+
+ grub_device_close (dev);
+
+ if (err)
+ return err;
+
+ poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
+ if (!poolname)
+ grub_printf ("Pool name: unavailable\n");
+ else
+ grub_printf ("Pool name: %s\n", poolname);
+
+ found =
+ grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
+ if (!found)
+ grub_printf ("Pool GUID: unavailable\n");
+ else
+ grub_printf ("Pool GUID: %016llx\n", (long long unsigned) guid);
+
+ found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
+ &pool_state);
+ if (!found)
+ grub_printf ("Unable to retrieve pool state\n");
+ else if (pool_state >= ARRAY_SIZE (poolstates))
+ grub_printf ("Unrecognized pool state\n");
+ else
+ grub_printf ("Pool state: %s\n", poolstates[pool_state]);
+
+ nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
+
+ if (!nv)
+ grub_printf ("No vdev tree available\n");
+ else
+ print_vdev_info (nv, 1);
+
+ grub_free (nv);
+ grub_free (nvlist);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
+ char **args)
+{
+ grub_device_t dev;
+ char *devname;
+ grub_err_t err;
+ char *nvlist = 0;
+ char *nv = 0;
+ char *bootpath = 0, *devid = 0;
+ char *fsname;
+ char *bootfs;
+ char *poolname;
+ grub_uint64_t mdnobj;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "filesystem name required");
+
+ devname = grub_file_get_device_name (args[0]);
+ if (grub_errno)
+ return grub_errno;
+
+ dev = grub_device_open (devname);
+ grub_free (devname);
+ if (!dev)
+ return grub_errno;
+
+ err = grub_zfs_fetch_nvlist (dev, &nvlist);
+
+ fsname = grub_strchr (args[0], ')');
+ if (fsname)
+ fsname++;
+ else
+ fsname = args[0];
+
+ if (!err)
+ err = grub_zfs_getmdnobj (dev, fsname, &mdnobj);
+
+ grub_device_close (dev);
+
+ if (err)
+ return err;
+
+ poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
+ if (!poolname)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_FS, "No poolname found");
+ return grub_errno;
+ }
+
+ nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
+
+ if (nv)
+ get_bootpath (nv, &bootpath, &devid);
+
+ grub_free (nv);
+ grub_free (nvlist);
+
+ if (bootpath && devid)
+ {
+ bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu bootpath=%s diskdevid=%s",
+ poolname, (unsigned long long) mdnobj,
+ bootpath, devid);
+ if (!bootfs)
+ return grub_errno;
+ }
+ else
+ {
+ bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu",
+ poolname, (unsigned long long) mdnobj);
+ if (!bootfs)
+ return grub_errno;
+ }
+ if (argc >= 2)
+ grub_env_set (args[1], bootfs);
+ else
+ grub_printf ("%s\n", bootfs);
+
+ grub_free (bootfs);
+ grub_free (poolname);
+ grub_free (bootpath);
+ grub_free (devid);
+
+ return GRUB_ERR_NONE;
+}
+
+
+static grub_command_t cmd_info, cmd_bootfs;
+
+GRUB_MOD_INIT (zfsinfo)
+{
+ cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
+ "zfsinfo DEVICE",
+ "Print ZFS info about DEVICE.");
+ cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
+ "zfs-bootfs FILESYSTEM [VARIABLE]",
+ "Print ZFS-BOOTFSOBJ or set it to VARIABLE");
+}
+
+GRUB_MOD_FINI (zfsinfo)
+{
+ grub_unregister_command (cmd_info);
+ grub_unregister_command (cmd_bootfs);
+}
diff --git a/debian/grub-extras/lua/COPYING b/debian/grub-extras/lua/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/debian/grub-extras/lua/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/debian/grub-extras/lua/Makefile.core.def b/debian/grub-extras/lua/Makefile.core.def
new file mode 100644
index 0000000..416d41f
--- /dev/null
+++ b/debian/grub-extras/lua/Makefile.core.def
@@ -0,0 +1,39 @@
+AutoGen definitions Makefile.tpl;
+
+module = {
+ name = lua;
+ common = contrib/lua/lapi.c;
+ common = contrib/lua/lcode.c;
+ common = contrib/lua/ldebug.c;
+ common = contrib/lua/ldo.c;
+ common = contrib/lua/ldump.c;
+ common = contrib/lua/lfunc.c;
+ common = contrib/lua/lgc.c;
+ common = contrib/lua/llex.c;
+ common = contrib/lua/lmem.c;
+ common = contrib/lua/lobject.c;
+ common = contrib/lua/lopcodes.c;
+ common = contrib/lua/lparser.c;
+ common = contrib/lua/lstate.c;
+ common = contrib/lua/lstring.c;
+ common = contrib/lua/ltable.c;
+ common = contrib/lua/ltm.c;
+ common = contrib/lua/lundump.c;
+ common = contrib/lua/lvm.c;
+ common = contrib/lua/lzio.c;
+ common = contrib/lua/lauxlib.c;
+ common = contrib/lua/lbaselib.c;
+ common = contrib/lua/linit.c;
+ common = contrib/lua/ltablib.c;
+ common = contrib/lua/lstrlib.c;
+ common = contrib/lua/grub_main.c;
+ common = contrib/lua/grub_lib.c;
+
+ cflags = '$(CFLAGS_POSIX)';
+ cppflags = '$(CPPFLAGS_POSIX)';
+ pci_cppflags = '$(CPPFLAGS_POSIX) -DENABLE_LUA_PCI';
+};
+
+/* Extra libraries for lua
+ script/lua/lmathlib.c script/lua/loslib.c script/lua/liolib.c
+ script/lua/ldblib.c script/lua/loadlib.c */
diff --git a/debian/grub-extras/lua/README b/debian/grub-extras/lua/README
new file mode 100644
index 0000000..874bd08
--- /dev/null
+++ b/debian/grub-extras/lua/README
@@ -0,0 +1,11 @@
+
+grub-extras is meant to be used as an overlay on grub2 source tree.
+
+Build instructions:
+
+ - Copy grub-extras in a subdirectory of your grub2 checkout.
+ For example, "grub-extras".
+
+ - Export GRUB_CONTRIB environment variable to point to this directory.
+
+ - Build GRUB as usual.
diff --git a/debian/grub-extras/lua/grub_lib.c b/debian/grub-extras/lua/grub_lib.c
new file mode 100644
index 0000000..3d25d02
--- /dev/null
+++ b/debian/grub-extras/lua/grub_lib.c
@@ -0,0 +1,537 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+#include "grub_lib.h"
+
+#include <grub/env.h>
+#include <grub/parser.h>
+#include <grub/command.h>
+#include <grub/normal.h>
+#include <grub/file.h>
+#include <grub/device.h>
+
+#ifdef ENABLE_LUA_PCI
+#include <grub/pci.h>
+#endif
+
+/* Updates the globals grub_errno and grub_msg, leaving their values on the
+ top of the stack, and clears grub_errno. When grub_errno is zero, grub_msg
+ is not left on the stack. The value returned is the number of values left on
+ the stack. */
+static int
+push_result (lua_State *state)
+{
+ int saved_errno;
+ int num_results;
+
+ saved_errno = grub_errno;
+ grub_errno = 0;
+
+ /* Push once for setfield, and again to leave on the stack */
+ lua_pushinteger (state, saved_errno);
+ lua_pushinteger (state, saved_errno);
+ lua_setfield (state, LUA_GLOBALSINDEX, "grub_errno");
+
+ if (saved_errno)
+ {
+ /* Push once for setfield, and again to leave on the stack */
+ lua_pushstring (state, grub_errmsg);
+ lua_pushstring (state, grub_errmsg);
+ num_results = 2;
+ }
+ else
+ {
+ lua_pushnil (state);
+ num_results = 1;
+ }
+
+ lua_setfield (state, LUA_GLOBALSINDEX, "grub_errmsg");
+
+ return num_results;
+}
+
+/* Updates the globals grub_errno and grub_msg ( without leaving them on the
+ stack ), clears grub_errno, and returns the value of grub_errno before it
+ was cleared. */
+static int
+save_errno (lua_State *state)
+{
+ int saved_errno;
+
+ saved_errno = grub_errno;
+ lua_pop(state, push_result(state));
+
+ return saved_errno;
+}
+
+static int
+grub_lua_run (lua_State *state)
+{
+ int n;
+ char **args;
+ const char *s;
+
+ s = luaL_checkstring (state, 1);
+ if ((! grub_parser_split_cmdline (s, 0, 0, &n, &args))
+ && (n >= 0))
+ {
+ grub_command_t cmd;
+
+ cmd = grub_command_find (args[0]);
+ if (cmd)
+ (cmd->func) (cmd, n-1, &args[1]);
+ else
+ grub_error (GRUB_ERR_FILE_NOT_FOUND, "command not found");
+
+ grub_free (args[0]);
+ grub_free (args);
+ }
+
+ return push_result (state);
+}
+
+static int
+grub_lua_getenv (lua_State *state)
+{
+ int n, i;
+
+ n = lua_gettop (state);
+ for (i = 1; i <= n; i++)
+ {
+ const char *name, *value;
+
+ name = luaL_checkstring (state, i);
+ value = grub_env_get (name);
+ if (value)
+ lua_pushstring (state, value);
+ else
+ lua_pushnil (state);
+ }
+
+ return n;
+}
+
+static int
+grub_lua_setenv (lua_State *state)
+{
+ const char *name, *value;
+
+ name = luaL_checkstring (state, 1);
+ value = luaL_checkstring (state, 2);
+
+ if (name[0])
+ grub_env_set (name, value);
+
+ return 0;
+}
+
+/* Helper for grub_lua_enum_device. */
+static int
+grub_lua_enum_device_iter (const char *name, void *data)
+{
+ lua_State *state = data;
+ int result;
+ grub_device_t dev;
+
+ result = 0;
+ dev = grub_device_open (name);
+ if (dev)
+ {
+ grub_fs_t fs;
+
+ fs = grub_fs_probe (dev);
+ if (fs)
+ {
+ lua_pushvalue (state, 1);
+ lua_pushstring (state, name);
+ lua_pushstring (state, fs->name);
+ if (! fs->uuid)
+ lua_pushnil (state);
+ else
+ {
+ int err;
+ char *uuid;
+
+ err = fs->uuid (dev, &uuid);
+ if (err)
+ {
+ grub_errno = 0;
+ lua_pushnil (state);
+ }
+ else
+ {
+ lua_pushstring (state, uuid);
+ grub_free (uuid);
+ }
+ }
+
+ if (! fs->label)
+ lua_pushnil (state);
+ else
+ {
+ int err;
+ char *label = NULL;
+
+ err = fs->label (dev, &label);
+ if (err)
+ {
+ grub_errno = 0;
+ lua_pushnil (state);
+ }
+ else
+ {
+ if (label == NULL)
+ {
+ lua_pushnil (state);
+ }
+ else
+ {
+ lua_pushstring (state, label);
+ }
+ grub_free (label);
+ }
+ }
+
+ lua_call (state, 4, 1);
+ result = lua_tointeger (state, -1);
+ lua_pop (state, 1);
+ }
+ else
+ grub_errno = 0;
+ grub_device_close (dev);
+ }
+ else
+ grub_errno = 0;
+
+ return result;
+}
+
+static int
+grub_lua_enum_device (lua_State *state)
+{
+ luaL_checktype (state, 1, LUA_TFUNCTION);
+ grub_device_iterate (grub_lua_enum_device_iter, state);
+ return push_result (state);
+}
+
+static int
+enum_file (const char *name, const struct grub_dirhook_info *info,
+ void *data)
+{
+ int result;
+ lua_State *state = data;
+
+ lua_pushvalue (state, 1);
+ lua_pushstring (state, name);
+ lua_pushinteger (state, info->dir != 0);
+ lua_call (state, 2, 1);
+ result = lua_tointeger (state, -1);
+ lua_pop (state, 1);
+
+ return result;
+}
+
+static int
+grub_lua_enum_file (lua_State *state)
+{
+ char *device_name;
+ const char *arg;
+ grub_device_t dev;
+
+ luaL_checktype (state, 1, LUA_TFUNCTION);
+ arg = luaL_checkstring (state, 2);
+ device_name = grub_file_get_device_name (arg);
+ dev = grub_device_open (device_name);
+ if (dev)
+ {
+ grub_fs_t fs;
+ const char *path;
+
+ fs = grub_fs_probe (dev);
+ path = grub_strchr (arg, ')');
+ if (! path)
+ path = arg;
+ else
+ path++;
+
+ if (fs)
+ {
+ (fs->dir) (dev, path, enum_file, state);
+ }
+
+ grub_device_close (dev);
+ }
+
+ grub_free (device_name);
+
+ return push_result (state);
+}
+
+#ifdef ENABLE_LUA_PCI
+/* Helper for grub_lua_enum_pci. */
+static int
+grub_lua_enum_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+{
+ lua_State *state = data;
+ int result;
+ grub_pci_address_t addr;
+ grub_uint32_t class;
+
+ lua_pushvalue (state, 1);
+ lua_pushinteger (state, grub_pci_get_bus (dev));
+ lua_pushinteger (state, grub_pci_get_device (dev));
+ lua_pushinteger (state, grub_pci_get_function (dev));
+ lua_pushinteger (state, pciid);
+
+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+ class = grub_pci_read (addr);
+ lua_pushinteger (state, class);
+
+ lua_call (state, 5, 1);
+ result = lua_tointeger (state, -1);
+ lua_pop (state, 1);
+
+ return result;
+}
+
+static int
+grub_lua_enum_pci (lua_State *state)
+{
+ luaL_checktype (state, 1, LUA_TFUNCTION);
+ grub_pci_iterate (grub_lua_enum_pci_iter, state);
+ return push_result (state);
+}
+#endif
+
+static int
+grub_lua_file_open (lua_State *state)
+{
+ grub_file_t file;
+ const char *name;
+
+ name = luaL_checkstring (state, 1);
+ file = grub_file_open (name);
+ save_errno (state);
+
+ if (! file)
+ return 0;
+
+ lua_pushlightuserdata (state, file);
+ return 1;
+}
+
+static int
+grub_lua_file_close (lua_State *state)
+{
+ grub_file_t file;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+ grub_file_close (file);
+
+ return push_result (state);
+}
+
+static int
+grub_lua_file_seek (lua_State *state)
+{
+ grub_file_t file;
+ grub_off_t offset;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+ offset = luaL_checkinteger (state, 2);
+
+ offset = grub_file_seek (file, offset);
+ save_errno (state);
+
+ lua_pushinteger (state, offset);
+ return 1;
+}
+
+static int
+grub_lua_file_read (lua_State *state)
+{
+ grub_file_t file;
+ luaL_Buffer b;
+ int n;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+ n = luaL_checkinteger (state, 2);
+
+ luaL_buffinit (state, &b);
+ while (n)
+ {
+ char *p;
+ int nr;
+
+ nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n;
+ p = luaL_prepbuffer (&b);
+
+ nr = grub_file_read (file, p, nr);
+ if (nr <= 0)
+ break;
+
+ luaL_addsize (&b, nr);
+ n -= nr;
+ }
+
+ save_errno (state);
+ luaL_pushresult (&b);
+ return 1;
+}
+
+static int
+grub_lua_file_getline (lua_State *state)
+{
+ grub_file_t file;
+ char *line;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+
+ line = grub_file_getline (file);
+ save_errno (state);
+
+ if (! line)
+ return 0;
+
+ lua_pushstring (state, line);
+ grub_free (line);
+ return 1;
+}
+
+static int
+grub_lua_file_getsize (lua_State *state)
+{
+ grub_file_t file;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+
+ lua_pushinteger (state, file->size);
+ return 1;
+}
+
+static int
+grub_lua_file_getpos (lua_State *state)
+{
+ grub_file_t file;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+
+ lua_pushinteger (state, file->offset);
+ return 1;
+}
+
+static int
+grub_lua_file_eof (lua_State *state)
+{
+ grub_file_t file;
+
+ luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+ file = lua_touserdata (state, 1);
+
+ lua_pushboolean (state, file->offset >= file->size);
+ return 1;
+}
+
+static int
+grub_lua_file_exist (lua_State *state)
+{
+ grub_file_t file;
+ const char *name;
+ int result;
+
+ result = 0;
+ name = luaL_checkstring (state, 1);
+ file = grub_file_open (name);
+ if (file)
+ {
+ result++;
+ grub_file_close (file);
+ }
+ else
+ grub_errno = 0;
+
+ lua_pushboolean (state, result);
+ return 1;
+}
+
+static int
+grub_lua_add_menu (lua_State *state)
+{
+ int n;
+ const char *source;
+
+ source = luaL_checklstring (state, 1, 0);
+ n = lua_gettop (state) - 1;
+ if (n > 0)
+ {
+ const char **args;
+ char *p;
+ int i;
+
+ args = grub_malloc (n * sizeof (args[0]));
+ if (!args)
+ return push_result (state);
+ for (i = 0; i < n; i++)
+ args[i] = luaL_checkstring (state, 2 + i);
+
+ p = grub_strdup (source);
+ if (! p)
+ return push_result (state);
+
+ grub_normal_add_menu_entry (n, args, NULL, NULL, NULL, NULL, NULL, p, 0);
+ }
+ else
+ {
+ lua_pushstring (state, "not enough parameter");
+ lua_error (state);
+ }
+
+ return push_result (state);
+}
+
+luaL_Reg grub_lua_lib[] =
+ {
+ {"run", grub_lua_run},
+ {"getenv", grub_lua_getenv},
+ {"setenv", grub_lua_setenv},
+ {"enum_device", grub_lua_enum_device},
+ {"enum_file", grub_lua_enum_file},
+#ifdef ENABLE_LUA_PCI
+ {"enum_pci", grub_lua_enum_pci},
+#endif
+ {"file_open", grub_lua_file_open},
+ {"file_close", grub_lua_file_close},
+ {"file_seek", grub_lua_file_seek},
+ {"file_read", grub_lua_file_read},
+ {"file_getline", grub_lua_file_getline},
+ {"file_getsize", grub_lua_file_getsize},
+ {"file_getpos", grub_lua_file_getpos},
+ {"file_eof", grub_lua_file_eof},
+ {"file_exist", grub_lua_file_exist},
+ {"add_menu", grub_lua_add_menu},
+ {0, 0}
+ };
diff --git a/debian/grub-extras/lua/grub_lib.h b/debian/grub-extras/lua/grub_lib.h
new file mode 100644
index 0000000..2253a41
--- /dev/null
+++ b/debian/grub-extras/lua/grub_lib.h
@@ -0,0 +1,24 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_LUA_LIB_HEADER
+#define GRUB_LUA_LIB_HEADER 1
+
+extern luaL_Reg grub_lua_lib[];
+
+#endif
diff --git a/debian/grub-extras/lua/grub_lua.h b/debian/grub-extras/lua/grub_lua.h
new file mode 100644
index 0000000..2d017d0
--- /dev/null
+++ b/debian/grub-extras/lua/grub_lua.h
@@ -0,0 +1,50 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_LUA_HEADER
+#define GRUB_LUA_HEADER 1
+
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/setjmp.h>
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+#undef UNUSED
+#define UNUSED (void)
+
+#define strtoul grub_strtoul
+#define strtod(s,e) grub_strtoul(s,e,0)
+
+#define exit(a) grub_exit()
+#define jmp_buf grub_jmp_buf
+#define setjmp grub_setjmp
+#define longjmp grub_longjmp
+
+#define fputs(s,f) grub_printf("%s", s)
+
+int strcspn (const char *s1, const char *s2);
+char *strpbrk (const char *s1, const char *s2);
+
+#endif
diff --git a/debian/grub-extras/lua/grub_main.c b/debian/grub-extras/lua/grub_main.c
new file mode 100644
index 0000000..cbb1790
--- /dev/null
+++ b/debian/grub-extras/lua/grub_main.c
@@ -0,0 +1,230 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+#include "grub_lib.h"
+
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+
+GRUB_MOD_LICENSE("GPLv3+");
+
+static const char *
+scan_str (const char *s1, const char *s2)
+{
+ while (*s1)
+ {
+ const char *p = s2;
+
+ while (*p)
+ {
+ if (*s1 == *p)
+ return s1;
+ p++;
+ }
+
+ s1++;
+ }
+
+ return s1;
+}
+
+int
+strcspn (const char *s1, const char *s2)
+{
+ const char *r;
+
+ r = scan_str (s1, s2);
+ return r - s1;
+}
+
+char *
+strpbrk (const char *s1, const char *s2)
+{
+ const char *r;
+
+ r = scan_str (s1, s2);
+ return (*r) ? (char *) r : 0;
+}
+
+static lua_State *state;
+
+/* Call `grub_error' to report a Lua error. The error message string must be
+ on the top of the Lua stack (at index -1). The error message is popped off
+ the Lua stack before this function returns. */
+static void
+handle_lua_error (const char *error_type)
+{
+ const char *error_msg;
+ error_msg = lua_tostring (state, -1);
+ if (error_msg == NULL)
+ error_msg = "(error message not a string)";
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "%s: %s", error_type, error_msg);
+ /* Pop the error message. */
+ lua_pop (state, 1);
+}
+
+/* Taken from lua.c */
+static int
+incomplete (lua_State * L, int status)
+{
+ if (status == LUA_ERRSYNTAX)
+ {
+ size_t lmsg;
+ const char *msg = lua_tolstring (L, -1, &lmsg);
+ const char *tp = msg + lmsg - (sizeof (LUA_QL ("<eof>")) - 1);
+ if (strstr (msg, LUA_QL ("<eof>")) == tp)
+ {
+ lua_pop (L, 1);
+ return 1;
+ }
+ }
+ return 0; /* else... */
+}
+
+static grub_err_t
+interactive (void)
+{
+ const char *ps1 = "lua> ";
+ const char *ps2 = "lua>> ";
+ const char *prompt = ps1;
+ char *line;
+ char *chunk = NULL;
+ size_t len;
+ size_t oldlen = 0;
+ int r;
+
+ grub_printf ("%s", N_ ("Welcome to lua, press the escape key to exit."));
+
+ while ((line = grub_cmdline_get (prompt)) != NULL)
+ {
+ /* len = lenght of chunk + line + newline character */
+ len = oldlen + grub_strlen (line) + 1;
+ chunk = grub_realloc (chunk, len + 1);
+ grub_strcpy (chunk + oldlen , line);
+ chunk[len - 1] = '\n';
+ chunk[len] = '\0';
+ grub_free (line);
+
+ r = luaL_loadbuffer (state, chunk, len, "stdin");
+ if (!r)
+ {
+ /* No error: Execute this chunk and prepare to read another */
+ r = lua_pcall (state, 0, 0, 0);
+ if (r)
+ {
+ handle_lua_error ("Lua");
+ grub_print_error ();
+ }
+
+ grub_free (chunk);
+ chunk = NULL;
+ len = 0;
+ prompt = ps1;
+ }
+ else if (incomplete (state, r))
+ {
+ /* Chunk is incomplete, try reading another line */
+ prompt = ps2;
+ }
+ else if (r == LUA_ERRSYNTAX)
+ {
+ handle_lua_error ("Lua");
+ grub_print_error ();
+
+ /* This chunk is garbage, try starting another one */
+ grub_free (chunk);
+ chunk = NULL;
+ len = 0;
+ prompt = ps1;
+ }
+ else
+ {
+ /* Handle errors other than syntax errors (out of memory, etc.) */
+ grub_free (chunk);
+ handle_lua_error ("Lua parser failed");
+ return grub_errno;
+ }
+
+ oldlen = len;
+ }
+
+ grub_free (chunk);
+ lua_gc (state, LUA_GCCOLLECT, 0);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_lua (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ if (argc == 1)
+ {
+ if (luaL_loadfile (state, args[0]))
+ {
+ handle_lua_error ("Lua");
+ }
+ else if (lua_pcall (state, 0, 0, 0))
+ {
+ handle_lua_error ("Lua");
+ }
+ }
+ else if (argc == 0)
+ {
+ return interactive ();
+ }
+ else
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "1 or 0 arguments expected");
+ }
+
+ return grub_errno;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT (lua)
+{
+ (void) mod;
+
+ state = lua_open ();
+ if (state)
+ {
+ lua_gc (state, LUA_GCSTOP, 0);
+ luaL_openlibs (state);
+ luaL_register (state, "grub", grub_lua_lib);
+ lua_gc (state, LUA_GCRESTART, 0);
+ cmd = grub_register_command ("lua", grub_cmd_lua, N_("[FILE]"),
+ N_ ("Run lua script FILE or start interactive lua shell"));
+ }
+}
+
+GRUB_MOD_FINI (lua)
+{
+ if (state)
+ {
+ lua_close (state);
+ grub_unregister_command (cmd);
+ }
+}
diff --git a/debian/grub-extras/lua/lapi.c b/debian/grub-extras/lua/lapi.c
new file mode 100644
index 0000000..2eaf45c
--- /dev/null
+++ b/debian/grub-extras/lua/lapi.c
@@ -0,0 +1,1088 @@
+/*
+** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $
+** Lua API
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <string.h>
+#endif
+
+#define lapi_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+
+
+
+const char lua_ident[] =
+ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n"
+ "$Authors: " LUA_AUTHORS " $\n"
+ "$URL: www.lua.org $\n";
+
+
+
+#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
+
+#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject)
+
+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
+
+
+
+static TValue *index2adr (lua_State *L, int idx) {
+ if (idx > 0) {
+ TValue *o = L->base + (idx - 1);
+ api_check(L, idx <= L->ci->top - L->base);
+ if (o >= L->top) return cast(TValue *, luaO_nilobject);
+ else return o;
+ }
+ else if (idx > LUA_REGISTRYINDEX) {
+ api_check(L, idx != 0 && -idx <= L->top - L->base);
+ return L->top + idx;
+ }
+ else switch (idx) { /* pseudo-indices */
+ case LUA_REGISTRYINDEX: return registry(L);
+ case LUA_ENVIRONINDEX: {
+ Closure *func = curr_func(L);
+ sethvalue(L, &L->env, func->c.env);
+ return &L->env;
+ }
+ case LUA_GLOBALSINDEX: return gt(L);
+ default: {
+ Closure *func = curr_func(L);
+ idx = LUA_GLOBALSINDEX - idx;
+ return (idx <= func->c.nupvalues)
+ ? &func->c.upvalue[idx-1]
+ : cast(TValue *, luaO_nilobject);
+ }
+ }
+}
+
+
+static Table *getcurrenv (lua_State *L) {
+ if (L->ci == L->base_ci) /* no enclosing function? */
+ return hvalue(gt(L)); /* use global table as environment */
+ else {
+ Closure *func = curr_func(L);
+ return func->c.env;
+ }
+}
+
+
+void luaA_pushobject (lua_State *L, const TValue *o) {
+ setobj2s(L, L->top, o);
+ api_incr_top(L);
+}
+
+
+LUA_API int lua_checkstack (lua_State *L, int size) {
+ int res = 1;
+ lua_lock(L);
+ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)
+ res = 0; /* stack overflow */
+ else if (size > 0) {
+ luaD_checkstack(L, size);
+ if (L->ci->top < L->top + size)
+ L->ci->top = L->top + size;
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
+ int i;
+ if (from == to) return;
+ lua_lock(to);
+ api_checknelems(from, n);
+ api_check(from, G(from) == G(to));
+ api_check(from, to->ci->top - to->top >= n);
+ from->top -= n;
+ for (i = 0; i < n; i++) {
+ setobj2s(to, to->top++, from->top + i);
+ }
+ lua_unlock(to);
+}
+
+
+LUA_API void lua_setlevel (lua_State *from, lua_State *to) {
+ to->nCcalls = from->nCcalls;
+}
+
+
+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
+ lua_CFunction old;
+ lua_lock(L);
+ old = G(L)->panic;
+ G(L)->panic = panicf;
+ lua_unlock(L);
+ return old;
+}
+
+
+LUA_API lua_State *lua_newthread (lua_State *L) {
+ lua_State *L1;
+ lua_lock(L);
+ luaC_checkGC(L);
+ L1 = luaE_newthread(L);
+ setthvalue(L, L->top, L1);
+ api_incr_top(L);
+ lua_unlock(L);
+ luai_userstatethread(L, L1);
+ return L1;
+}
+
+
+
+/*
+** basic stack manipulation
+*/
+
+
+LUA_API int lua_gettop (lua_State *L) {
+ return cast_int(L->top - L->base);
+}
+
+
+LUA_API void lua_settop (lua_State *L, int idx) {
+ lua_lock(L);
+ if (idx >= 0) {
+ api_check(L, idx <= L->stack_last - L->base);
+ while (L->top < L->base + idx)
+ setnilvalue(L->top++);
+ L->top = L->base + idx;
+ }
+ else {
+ api_check(L, -(idx+1) <= (L->top - L->base));
+ L->top += idx+1; /* `subtract' index (index is negative) */
+ }
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_remove (lua_State *L, int idx) {
+ StkId p;
+ lua_lock(L);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ while (++p < L->top) setobjs2s(L, p-1, p);
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_insert (lua_State *L, int idx) {
+ StkId p;
+ StkId q;
+ lua_lock(L);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
+ setobjs2s(L, p, L->top);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_replace (lua_State *L, int idx) {
+ StkId o;
+ lua_lock(L);
+ /* explicit test for incompatible code */
+ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)
+ luaG_runerror(L, "no calling environment");
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ if (idx == LUA_ENVIRONINDEX) {
+ Closure *func = curr_func(L);
+ api_check(L, ttistable(L->top - 1));
+ func->c.env = hvalue(L->top - 1);
+ luaC_barrier(L, func, L->top - 1);
+ }
+ else {
+ setobj(L, o, L->top - 1);
+ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */
+ luaC_barrier(L, curr_func(L), L->top - 1);
+ }
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushvalue (lua_State *L, int idx) {
+ lua_lock(L);
+ setobj2s(L, L->top, index2adr(L, idx));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+
+/*
+** access functions (stack -> C)
+*/
+
+
+LUA_API int lua_type (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
+}
+
+
+LUA_API const char *lua_typename (lua_State *L, int t) {
+ UNUSED(L);
+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+}
+
+
+LUA_API int lua_iscfunction (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return iscfunction(o);
+}
+
+
+LUA_API int lua_isnumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ return tonumber(o, &n);
+}
+
+
+LUA_API int lua_isstring (lua_State *L, int idx) {
+ int t = lua_type(L, idx);
+ return (t == LUA_TSTRING || t == LUA_TNUMBER);
+}
+
+
+LUA_API int lua_isuserdata (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return (ttisuserdata(o) || ttislightuserdata(o));
+}
+
+
+LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
+ StkId o1 = index2adr(L, index1);
+ StkId o2 = index2adr(L, index2);
+ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaO_rawequalObj(o1, o2);
+}
+
+
+LUA_API int lua_equal (lua_State *L, int index1, int index2) {
+ StkId o1, o2;
+ int i;
+ lua_lock(L); /* may call tag method */
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
+ lua_unlock(L);
+ return i;
+}
+
+
+LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
+ StkId o1, o2;
+ int i;
+ lua_lock(L); /* may call tag method */
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaV_lessthan(L, o1, o2);
+ lua_unlock(L);
+ return i;
+}
+
+
+
+LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n))
+ return nvalue(o);
+ else
+ return 0;
+}
+
+
+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+ lua_Integer res;
+ lua_Number num = nvalue(o);
+ lua_number2integer(res, num);
+ return res;
+ }
+ else
+ return 0;
+}
+
+
+LUA_API int lua_toboolean (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
+}
+
+
+LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
+ StkId o = index2adr(L, idx);
+ if (!ttisstring(o)) {
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ if (!luaV_tostring(L, o)) { /* conversion failed? */
+ if (len != NULL) *len = 0;
+ lua_unlock(L);
+ return NULL;
+ }
+ luaC_checkGC(L);
+ o = index2adr(L, idx); /* previous call may reallocate the stack */
+ lua_unlock(L);
+ }
+ if (len != NULL) *len = tsvalue(o)->len;
+ return svalue(o);
+}
+
+
+LUA_API size_t lua_objlen (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
+ lua_unlock(L);
+ return l;
+ }
+ default: return 0;
+ }
+}
+
+
+LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
+}
+
+
+LUA_API void *lua_touserdata (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TUSERDATA: return (rawuvalue(o) + 1);
+ case LUA_TLIGHTUSERDATA: return pvalue(o);
+ default: return NULL;
+ }
+}
+
+
+LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ return (!ttisthread(o)) ? NULL : thvalue(o);
+}
+
+
+LUA_API const void *lua_topointer (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TTABLE: return hvalue(o);
+ case LUA_TFUNCTION: return clvalue(o);
+ case LUA_TTHREAD: return thvalue(o);
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ return lua_touserdata(L, idx);
+ default: return NULL;
+ }
+}
+
+
+
+/*
+** push functions (C -> stack)
+*/
+
+
+LUA_API void lua_pushnil (lua_State *L) {
+ lua_lock(L);
+ setnilvalue(L->top);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+ lua_lock(L);
+ setnvalue(L->top, n);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
+ lua_lock(L);
+ setnvalue(L->top, cast_num(n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+ lua_lock(L);
+ luaC_checkGC(L);
+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushstring (lua_State *L, const char *s) {
+ if (s == NULL)
+ lua_pushnil(L);
+ else
+ lua_pushlstring(L, s, strlen(s));
+}
+
+
+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp) {
+ const char *ret;
+ lua_lock(L);
+ luaC_checkGC(L);
+ ret = luaO_pushvfstring(L, fmt, argp);
+ lua_unlock(L);
+ return ret;
+}
+
+
+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
+ const char *ret;
+ va_list argp;
+ lua_lock(L);
+ luaC_checkGC(L);
+ va_start(argp, fmt);
+ ret = luaO_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ lua_unlock(L);
+ return ret;
+}
+
+
+LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
+ Closure *cl;
+ lua_lock(L);
+ luaC_checkGC(L);
+ api_checknelems(L, n);
+ cl = luaF_newCclosure(L, n, getcurrenv(L));
+ cl->c.f = fn;
+ L->top -= n;
+ while (n--)
+ setobj2n(L, &cl->c.upvalue[n], L->top+n);
+ setclvalue(L, L->top, cl);
+ lua_assert(iswhite(obj2gco(cl)));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushboolean (lua_State *L, int b) {
+ lua_lock(L);
+ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
+ lua_lock(L);
+ setpvalue(L->top, p);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_pushthread (lua_State *L) {
+ lua_lock(L);
+ setthvalue(L, L->top, L);
+ api_incr_top(L);
+ lua_unlock(L);
+ return (G(L)->mainthread == L);
+}
+
+
+
+/*
+** get functions (Lua -> stack)
+*/
+
+
+LUA_API void lua_gettable (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_gettable(L, t, L->top - 1, L->top - 1);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_gettable(L, t, &key, L->top);
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawget (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
+ StkId o;
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
+ lua_lock(L);
+ luaC_checkGC(L);
+ sethvalue(L, L->top, luaH_new(L, narray, nrec));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_getmetatable (lua_State *L, int objindex) {
+ const TValue *obj;
+ Table *mt = NULL;
+ int res;
+ lua_lock(L);
+ obj = index2adr(L, objindex);
+ switch (ttype(obj)) {
+ case LUA_TTABLE:
+ mt = hvalue(obj)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
+ }
+ if (mt == NULL)
+ res = 0;
+ else {
+ sethvalue(L, L->top, mt);
+ api_incr_top(L);
+ res = 1;
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+LUA_API void lua_getfenv (lua_State *L, int idx) {
+ StkId o;
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ sethvalue(L, L->top, clvalue(o)->c.env);
+ break;
+ case LUA_TUSERDATA:
+ sethvalue(L, L->top, uvalue(o)->env);
+ break;
+ case LUA_TTHREAD:
+ setobj2s(L, L->top, gt(thvalue(o)));
+ break;
+ default:
+ setnilvalue(L->top);
+ break;
+ }
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
+/*
+** set functions (stack -> Lua)
+*/
+
+
+LUA_API void lua_settable (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ api_checknelems(L, 2);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_settable(L, t, L->top - 2, L->top - 1);
+ L->top -= 2; /* pop index and value */
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_settable(L, t, &key, L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawset (lua_State *L, int idx) {
+ StkId t;
+ lua_lock(L);
+ api_checknelems(L, 2);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
+ luaC_barriert(L, hvalue(t), L->top-1);
+ L->top -= 2;
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
+ StkId o;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
+ L->top--;
+ lua_unlock(L);
+}
+
+
+LUA_API int lua_setmetatable (lua_State *L, int objindex) {
+ TValue *obj;
+ Table *mt;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ obj = index2adr(L, objindex);
+ api_checkvalidindex(L, obj);
+ if (ttisnil(L->top - 1))
+ mt = NULL;
+ else {
+ api_check(L, ttistable(L->top - 1));
+ mt = hvalue(L->top - 1);
+ }
+ switch (ttype(obj)) {
+ case LUA_TTABLE: {
+ hvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarriert(L, hvalue(obj), mt);
+ break;
+ }
+ case LUA_TUSERDATA: {
+ uvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarrier(L, rawuvalue(obj), mt);
+ break;
+ }
+ default: {
+ G(L)->mt[ttype(obj)] = mt;
+ break;
+ }
+ }
+ L->top--;
+ lua_unlock(L);
+ return 1;
+}
+
+
+LUA_API int lua_setfenv (lua_State *L, int idx) {
+ StkId o;
+ int res = 1;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ api_check(L, ttistable(L->top - 1));
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ clvalue(o)->c.env = hvalue(L->top - 1);
+ break;
+ case LUA_TUSERDATA:
+ uvalue(o)->env = hvalue(L->top - 1);
+ break;
+ case LUA_TTHREAD:
+ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));
+ break;
+ default:
+ res = 0;
+ break;
+ }
+ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
+ L->top--;
+ lua_unlock(L);
+ return res;
+}
+
+
+/*
+** `load' and `call' functions (run Lua code)
+*/
+
+
+#define adjustresults(L,nres) \
+ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
+
+
+#define checkresults(L,na,nr) \
+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
+
+
+LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
+ StkId func;
+ lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ func = L->top - (nargs+1);
+ luaD_call(L, func, nresults);
+ adjustresults(L, nresults);
+ lua_unlock(L);
+}
+
+
+
+/*
+** Execute a protected call.
+*/
+struct CallS { /* data to `f_call' */
+ StkId func;
+ int nresults;
+};
+
+
+static void f_call (lua_State *L, void *ud) {
+ struct CallS *c = cast(struct CallS *, ud);
+ luaD_call(L, c->func, c->nresults);
+}
+
+
+
+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
+ struct CallS c;
+ int status;
+ ptrdiff_t func;
+ lua_lock(L);
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ if (errfunc == 0)
+ func = 0;
+ else {
+ StkId o = index2adr(L, errfunc);
+ api_checkvalidindex(L, o);
+ func = savestack(L, o);
+ }
+ c.func = L->top - (nargs+1); /* function to be called */
+ c.nresults = nresults;
+ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
+ adjustresults(L, nresults);
+ lua_unlock(L);
+ return status;
+}
+
+
+/*
+** Execute a protected C call.
+*/
+struct CCallS { /* data to `f_Ccall' */
+ lua_CFunction func;
+ void *ud;
+};
+
+
+static void f_Ccall (lua_State *L, void *ud) {
+ struct CCallS *c = cast(struct CCallS *, ud);
+ Closure *cl;
+ cl = luaF_newCclosure(L, 0, getcurrenv(L));
+ cl->c.f = c->func;
+ setclvalue(L, L->top, cl); /* push function */
+ api_incr_top(L);
+ setpvalue(L->top, c->ud); /* push only argument */
+ api_incr_top(L);
+ luaD_call(L, L->top - 2, 0);
+}
+
+
+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
+ struct CCallS c;
+ int status;
+ lua_lock(L);
+ c.func = func;
+ c.ud = ud;
+ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
+ const char *chunkname) {
+ ZIO z;
+ int status;
+ lua_lock(L);
+ if (!chunkname) chunkname = "?";
+ luaZ_init(L, &z, reader, data);
+ status = luaD_protectedparser(L, &z, chunkname);
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
+ int status;
+ TValue *o;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ o = L->top - 1;
+ if (isLfunction(o))
+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
+ else
+ status = 1;
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_status (lua_State *L) {
+ return L->status;
+}
+
+
+/*
+** Garbage-collection function
+*/
+
+LUA_API int lua_gc (lua_State *L, int what, int data) {
+ int res = 0;
+ global_State *g;
+ lua_lock(L);
+ g = G(L);
+ switch (what) {
+ case LUA_GCSTOP: {
+ g->GCthreshold = MAX_LUMEM;
+ break;
+ }
+ case LUA_GCRESTART: {
+ g->GCthreshold = g->totalbytes;
+ break;
+ }
+ case LUA_GCCOLLECT: {
+ luaC_fullgc(L);
+ break;
+ }
+ case LUA_GCCOUNT: {
+ /* GC values are expressed in Kbytes: #bytes/2^10 */
+ res = cast_int(g->totalbytes >> 10);
+ break;
+ }
+ case LUA_GCCOUNTB: {
+ res = cast_int(g->totalbytes & 0x3ff);
+ break;
+ }
+ case LUA_GCSTEP: {
+ lu_mem a = (cast(lu_mem, data) << 10);
+ if (a <= g->totalbytes)
+ g->GCthreshold = g->totalbytes - a;
+ else
+ g->GCthreshold = 0;
+ while (g->GCthreshold <= g->totalbytes) {
+ luaC_step(L);
+ if (g->gcstate == GCSpause) { /* end of cycle? */
+ res = 1; /* signal it */
+ break;
+ }
+ }
+ break;
+ }
+ case LUA_GCSETPAUSE: {
+ res = g->gcpause;
+ g->gcpause = data;
+ break;
+ }
+ case LUA_GCSETSTEPMUL: {
+ res = g->gcstepmul;
+ g->gcstepmul = data;
+ break;
+ }
+ default: res = -1; /* invalid option */
+ }
+ lua_unlock(L);
+ return res;
+}
+
+
+
+/*
+** miscellaneous functions
+*/
+
+
+LUA_API int lua_error (lua_State *L) {
+ lua_lock(L);
+ api_checknelems(L, 1);
+ luaG_errormsg(L);
+ lua_unlock(L);
+ return 0; /* to avoid warnings */
+}
+
+
+LUA_API int lua_next (lua_State *L, int idx) {
+ StkId t;
+ int more;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_check(L, ttistable(t));
+ more = luaH_next(L, hvalue(t), L->top - 1);
+ if (more) {
+ api_incr_top(L);
+ }
+ else /* no more elements */
+ L->top -= 1; /* remove key */
+ lua_unlock(L);
+ return more;
+}
+
+
+LUA_API void lua_concat (lua_State *L, int n) {
+ lua_lock(L);
+ api_checknelems(L, n);
+ if (n >= 2) {
+ luaC_checkGC(L);
+ luaV_concat(L, n, cast_int(L->top - L->base) - 1);
+ L->top -= (n-1);
+ }
+ else if (n == 0) { /* push empty string */
+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
+ api_incr_top(L);
+ }
+ /* else n == 1; nothing to do */
+ lua_unlock(L);
+}
+
+
+LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
+ lua_Alloc f;
+ lua_lock(L);
+ if (ud) *ud = G(L)->ud;
+ f = G(L)->frealloc;
+ lua_unlock(L);
+ return f;
+}
+
+
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
+ lua_lock(L);
+ G(L)->ud = ud;
+ G(L)->frealloc = f;
+ lua_unlock(L);
+}
+
+
+LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
+ Udata *u;
+ lua_lock(L);
+ luaC_checkGC(L);
+ u = luaS_newudata(L, size, getcurrenv(L));
+ setuvalue(L, L->top, u);
+ api_incr_top(L);
+ lua_unlock(L);
+ return u + 1;
+}
+
+
+
+
+static const char *aux_upvalue (StkId fi, int n, TValue **val) {
+ Closure *f;
+ if (!ttisfunction(fi)) return NULL;
+ f = clvalue(fi);
+ if (f->c.isC) {
+ if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
+ *val = &f->c.upvalue[n-1];
+ return "";
+ }
+ else {
+ Proto *p = f->l.p;
+ if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
+ *val = f->l.upvals[n-1]->v;
+ return getstr(p->upvalues[n-1]);
+ }
+}
+
+
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
+ const char *name;
+ TValue *val;
+ lua_lock(L);
+ name = aux_upvalue(index2adr(L, funcindex), n, &val);
+ if (name) {
+ setobj2s(L, L->top, val);
+ api_incr_top(L);
+ }
+ lua_unlock(L);
+ return name;
+}
+
+
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
+ const char *name;
+ TValue *val;
+ StkId fi;
+ lua_lock(L);
+ fi = index2adr(L, funcindex);
+ api_checknelems(L, 1);
+ name = aux_upvalue(fi, n, &val);
+ if (name) {
+ L->top--;
+ setobj(L, val, L->top);
+ luaC_barrier(L, clvalue(fi), L->top);
+ }
+ lua_unlock(L);
+ return name;
+}
+
diff --git a/debian/grub-extras/lua/lapi.h b/debian/grub-extras/lua/lapi.h
new file mode 100644
index 0000000..2c3fab2
--- /dev/null
+++ b/debian/grub-extras/lua/lapi.h
@@ -0,0 +1,16 @@
+/*
+** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions from Lua API
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lapi_h
+#define lapi_h
+
+
+#include "lobject.h"
+
+
+LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+
+#endif
diff --git a/debian/grub-extras/lua/lauxlib.c b/debian/grub-extras/lua/lauxlib.c
new file mode 100644
index 0000000..ab3c869
--- /dev/null
+++ b/debian/grub-extras/lua/lauxlib.c
@@ -0,0 +1,687 @@
+/*
+** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <grub/file.h>
+
+/* This file uses only the official API of Lua.
+** Any function declared here could be written as an application function.
+*/
+
+#define lauxlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+
+
+#define FREELIST_REF 0 /* free list of references */
+
+
+/* convert a stack index to positive */
+#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
+ lua_gettop(L) + (i) + 1)
+
+
+/*
+** {======================================================
+** Error-report functions
+** =======================================================
+*/
+
+
+LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
+ lua_Debug ar;
+ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
+ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
+ lua_getinfo(L, "n", &ar);
+ if (strcmp(ar.namewhat, "method") == 0) {
+ narg--; /* do not count `self' */
+ if (narg == 0) /* error is in the self argument itself? */
+ return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
+ ar.name, extramsg);
+ }
+ if (ar.name == NULL)
+ ar.name = "?";
+ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
+ narg, ar.name, extramsg);
+}
+
+
+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
+ const char *msg = lua_pushfstring(L, "%s expected, got %s",
+ tname, luaL_typename(L, narg));
+ return luaL_argerror(L, narg, msg);
+}
+
+
+static void tag_error (lua_State *L, int narg, int tag) {
+ luaL_typerror(L, narg, lua_typename(L, tag));
+}
+
+
+LUALIB_API void luaL_where (lua_State *L, int level) {
+ lua_Debug ar;
+ if (lua_getstack(L, level, &ar)) { /* check function at level */
+ lua_getinfo(L, "Sl", &ar); /* get info about it */
+ if (ar.currentline > 0) { /* is there info? */
+ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
+ return;
+ }
+ }
+ lua_pushliteral(L, ""); /* else, no information available... */
+}
+
+
+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ luaL_where(L, 1);
+ lua_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ lua_concat(L, 2);
+ return lua_error(L);
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
+ const char *const lst[]) {
+ const char *name = (def) ? luaL_optstring(L, narg, def) :
+ luaL_checkstring(L, narg);
+ int i;
+ for (i=0; lst[i]; i++)
+ if (strcmp(lst[i], name) == 0)
+ return i;
+ return luaL_argerror(L, narg,
+ lua_pushfstring(L, "invalid option " LUA_QS, name));
+}
+
+
+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
+ if (!lua_isnil(L, -1)) /* name already in use? */
+ return 0; /* leave previous value on top, but return 0 */
+ lua_pop(L, 1);
+ lua_newtable(L); /* create metatable */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
+ return 1;
+}
+
+
+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return p;
+ }
+ }
+ }
+ luaL_typerror(L, ud, tname); /* else error */
+ return NULL; /* to avoid warnings */
+}
+
+
+LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
+ if (!lua_checkstack(L, space))
+ luaL_error(L, "stack overflow (%s)", mes);
+}
+
+
+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
+ if (lua_type(L, narg) != t)
+ tag_error(L, narg, t);
+}
+
+
+LUALIB_API void luaL_checkany (lua_State *L, int narg) {
+ if (lua_type(L, narg) == LUA_TNONE)
+ luaL_argerror(L, narg, "value expected");
+}
+
+
+LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
+ const char *s = lua_tolstring(L, narg, len);
+ if (!s) tag_error(L, narg, LUA_TSTRING);
+ return s;
+}
+
+
+LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
+ const char *def, size_t *len) {
+ if (lua_isnoneornil(L, narg)) {
+ if (len)
+ *len = (def ? strlen(def) : 0);
+ return def;
+ }
+ else return luaL_checklstring(L, narg, len);
+}
+
+
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
+ lua_Number d = lua_tonumber(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
+ return luaL_opt(L, luaL_checknumber, narg, def);
+}
+
+
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+ lua_Integer def) {
+ return luaL_opt(L, luaL_checkinteger, narg, def);
+}
+
+
+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return 0;
+ lua_pushstring(L, event);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 2); /* remove metatable and metafield */
+ return 0;
+ }
+ else {
+ lua_remove(L, -2); /* remove only metatable */
+ return 1;
+ }
+}
+
+
+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
+ obj = abs_index(L, obj);
+ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
+ return 0;
+ lua_pushvalue(L, obj);
+ lua_call(L, 1, 1);
+ return 1;
+}
+
+
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l) {
+ luaI_openlib(L, libname, l, 0);
+}
+
+
+static int libsize (const luaL_Reg *l) {
+ int size = 0;
+ for (; l->name; l++) size++;
+ return size;
+}
+
+
+LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup) {
+ if (libname) {
+ int size = libsize(l);
+ /* check whether lib already exists */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
+ lua_getfield(L, -1, libname); /* get _LOADED[libname] */
+ if (!lua_istable(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
+ /* try global variable (and create one if it does not exist) */
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
+ luaL_error(L, "name conflict for module " LUA_QS, libname);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
+ }
+ lua_remove(L, -2); /* remove _LOADED table */
+ lua_insert(L, -(nup+1)); /* move library table to below upvalues */
+ }
+ for (; l->name; l++) {
+ int i;
+ for (i=0; i<nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushcclosure(L, l->func, nup);
+ lua_setfield(L, -(nup+2), l->name);
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+
+
+
+/*
+** {======================================================
+** getn-setn: size for arrays
+** =======================================================
+*/
+
+#if defined(LUA_COMPAT_GETN)
+
+static int checkint (lua_State *L, int topop) {
+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
+ lua_pop(L, topop);
+ return n;
+}
+
+
+static void getsizes (lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
+ if (lua_isnil(L, -1)) { /* no `size' table? */
+ lua_pop(L, 1); /* remove nil */
+ lua_newtable(L); /* create it */
+ lua_pushvalue(L, -1); /* `size' will be its own metatable */
+ lua_setmetatable(L, -2);
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
+ }
+}
+
+
+LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
+ t = abs_index(L, t);
+ lua_pushliteral(L, "n");
+ lua_rawget(L, t);
+ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
+ lua_pushliteral(L, "n"); /* use it */
+ lua_pushinteger(L, n);
+ lua_rawset(L, t);
+ }
+ else { /* use `sizes' */
+ getsizes(L);
+ lua_pushvalue(L, t);
+ lua_pushinteger(L, n);
+ lua_rawset(L, -3); /* sizes[t] = n */
+ lua_pop(L, 1); /* remove `sizes' */
+ }
+}
+
+
+LUALIB_API int luaL_getn (lua_State *L, int t) {
+ int n;
+ t = abs_index(L, t);
+ lua_pushliteral(L, "n"); /* try t.n */
+ lua_rawget(L, t);
+ if ((n = checkint(L, 1)) >= 0) return n;
+ getsizes(L); /* else try sizes[t] */
+ lua_pushvalue(L, t);
+ lua_rawget(L, -2);
+ if ((n = checkint(L, 2)) >= 0) return n;
+ return (int)lua_objlen(L, t);
+}
+
+#endif
+
+/* }====================================================== */
+
+
+
+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
+ const char *r) {
+ const char *wild;
+ size_t l = strlen(p);
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while ((wild = strstr(s, p)) != NULL) {
+ luaL_addlstring(&b, s, wild - s); /* push prefix */
+ luaL_addstring(&b, r); /* push replacement in place of pattern */
+ s = wild + l; /* continue after `p' */
+ }
+ luaL_addstring(&b, s); /* push last suffix */
+ luaL_pushresult(&b);
+ return lua_tostring(L, -1);
+}
+
+
+LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
+ const char *fname, int szhint) {
+ const char *e;
+ lua_pushvalue(L, idx);
+ do {
+ e = strchr(fname, '.');
+ if (e == NULL) e = fname + strlen(fname);
+ lua_pushlstring(L, fname, e - fname);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) { /* no such field? */
+ lua_pop(L, 1); /* remove this nil */
+ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
+ lua_pushlstring(L, fname, e - fname);
+ lua_pushvalue(L, -2);
+ lua_settable(L, -4); /* set new table into field */
+ }
+ else if (!lua_istable(L, -1)) { /* field has a non-table value? */
+ lua_pop(L, 2); /* remove table and value */
+ return fname; /* return problematic part of the name */
+ }
+ lua_remove(L, -2); /* remove previous table */
+ fname = e + 1;
+ } while (*e == '.');
+ return NULL;
+}
+
+
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+#define bufflen(B) ((B)->p - (B)->buffer)
+#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
+
+#define LIMIT (LUA_MINSTACK/2)
+
+
+static int emptybuffer (luaL_Buffer *B) {
+ size_t l = bufflen(B);
+ if (l == 0) return 0; /* put nothing on stack */
+ else {
+ lua_pushlstring(B->L, B->buffer, l);
+ B->p = B->buffer;
+ B->lvl++;
+ return 1;
+ }
+}
+
+
+static void adjuststack (luaL_Buffer *B) {
+ if (B->lvl > 1) {
+ lua_State *L = B->L;
+ int toget = 1; /* number of levels to concat */
+ size_t toplen = lua_strlen(L, -1);
+ do {
+ size_t l = lua_strlen(L, -(toget+1));
+ if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
+ toplen += l;
+ toget++;
+ }
+ else break;
+ } while (toget < B->lvl);
+ lua_concat(L, toget);
+ B->lvl = B->lvl - toget + 1;
+ }
+}
+
+
+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
+ if (emptybuffer(B))
+ adjuststack(B);
+ return B->buffer;
+}
+
+
+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
+ while (l--)
+ luaL_addchar(B, *s++);
+}
+
+
+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
+ luaL_addlstring(B, s, strlen(s));
+}
+
+
+LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
+ emptybuffer(B);
+ lua_concat(B->L, B->lvl);
+ B->lvl = 1;
+}
+
+
+LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
+ lua_State *L = B->L;
+ size_t vl;
+ const char *s = lua_tolstring(L, -1, &vl);
+ if (vl <= bufffree(B)) { /* fit into buffer? */
+ memcpy(B->p, s, vl); /* put it there */
+ B->p += vl;
+ lua_pop(L, 1); /* remove from stack */
+ }
+ else {
+ if (emptybuffer(B))
+ lua_insert(L, -2); /* put buffer before new value */
+ B->lvl++; /* add new value into B stack */
+ adjuststack(B);
+ }
+}
+
+
+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
+ B->L = L;
+ B->p = B->buffer;
+ B->lvl = 0;
+}
+
+/* }====================================================== */
+
+
+LUALIB_API int luaL_ref (lua_State *L, int t) {
+ int ref;
+ t = abs_index(L, t);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1); /* remove from stack */
+ return LUA_REFNIL; /* `nil' has a unique fixed reference */
+ }
+ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
+ lua_pop(L, 1); /* remove it from stack */
+ if (ref != 0) { /* any free element? */
+ lua_rawgeti(L, t, ref); /* remove it from list */
+ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
+ }
+ else { /* no free elements */
+ ref = (int)lua_objlen(L, t);
+ ref++; /* create new reference */
+ }
+ lua_rawseti(L, t, ref);
+ return ref;
+}
+
+
+LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
+ if (ref >= 0) {
+ t = abs_index(L, t);
+ lua_rawgeti(L, t, FREELIST_REF);
+ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
+ lua_pushinteger(L, ref);
+ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
+ }
+}
+
+
+
+/*
+** {======================================================
+** Load functions
+** =======================================================
+*/
+
+#define GRUB_EOF -1
+
+static int
+grub_getc (grub_file_t file)
+{
+ grub_uint8_t c = 0;
+
+ return (grub_file_read (file, &c, 1) != 1) ? GRUB_EOF : c;
+ return GRUB_EOF;
+}
+
+#define grub_eof(file) (file->offset >= file->size)
+
+typedef struct LoadF {
+ int extraline;
+ grub_file_t f;
+ int ungetc;
+ char buff[LUAL_BUFFERSIZE];
+} LoadF;
+
+
+static const char *getF (lua_State *L, void *ud, size_t *size) {
+ LoadF *lf = (LoadF *)ud;
+ char *p;
+ int s;
+ (void)L;
+ if (lf->extraline) {
+ lf->extraline = 0;
+ *size = 1;
+ return "\n";
+ }
+ s = sizeof (lf->buff);
+ p = lf->buff;
+ if (lf->ungetc >= 0)
+ {
+ lf->buff[0] = lf->ungetc;
+ lf->ungetc = -1;
+ s--;
+ p++;
+ }
+
+ if (grub_eof(lf->f)) return NULL;
+ s = grub_file_read(lf->f, p, s);
+ if (s <= 0)
+ return NULL;
+
+ *size = s + (p - lf->buff);
+ return (*size > 0) ? lf->buff : NULL;
+}
+
+static int errfile (lua_State *L, const char *what, int fnameindex) {
+ const char *serr = grub_errmsg;
+ const char *filename = lua_tostring(L, fnameindex) + 1;
+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
+ lua_remove(L, fnameindex);
+ return LUA_ERRFILE;
+}
+
+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
+ LoadF lf;
+ int status, readstatus;
+ int c;
+ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
+ lf.extraline = 0;
+ if (filename == NULL) {
+ lua_pushliteral(L, "=stdin");
+ return errfile(L, "open", fnameindex);
+ }
+ else {
+ lua_pushfstring(L, "@%s", filename);
+ lf.f = grub_file_open(filename);
+ if (lf.f == NULL) return errfile(L, "open", fnameindex);
+ }
+
+ c = grub_getc(lf.f);
+ if (c == '#') { /* Unix exec. file? */
+ lf.extraline = 1;
+ while ((c = grub_getc(lf.f)) != GRUB_EOF && c != '\n')
+ ; /* skip first line */
+ if (c == '\n') c = grub_getc(lf.f);
+ }
+ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
+ /* skip eventual `#!...' */
+ while ((c = grub_getc(lf.f)) != GRUB_EOF && c != LUA_SIGNATURE[0])
+ ;
+ lf.extraline = 0;
+ }
+ lf.ungetc = c;
+ status = lua_load(L, getF, &lf, lua_tostring(L, -1));
+ readstatus = grub_errno;
+ grub_file_close(lf.f); /* close file (even in case of errors) */
+ if (readstatus) {
+ lua_settop(L, fnameindex); /* ignore results from `lua_load' */
+ return errfile(L, "read", fnameindex);
+ }
+ lua_remove(L, fnameindex);
+ return status;
+}
+
+typedef struct LoadS {
+ const char *s;
+ size_t size;
+} LoadS;
+
+
+static const char *getS (lua_State *L, void *ud, size_t *size) {
+ LoadS *ls = (LoadS *)ud;
+ (void)L;
+ if (ls->size == 0) return NULL;
+ *size = ls->size;
+ ls->size = 0;
+ return ls->s;
+}
+
+
+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
+ const char *name) {
+ LoadS ls;
+ ls.s = buff;
+ ls.size = size;
+ return lua_load(L, getS, &ls, name);
+}
+
+
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
+ return luaL_loadbuffer(L, s, strlen(s), s);
+}
+
+
+
+/* }====================================================== */
+
+
+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ (void)ud;
+ (void)osize;
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
+ }
+ else
+ return realloc(ptr, nsize);
+}
+
+
+static int panic (lua_State *L) {
+ (void)L; /* to avoid warnings */
+#if 0
+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
+#else
+ grub_fatal ("PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
+#endif
+ return 0;
+}
+
+
+LUALIB_API lua_State *luaL_newstate (void) {
+ lua_State *L = lua_newstate(l_alloc, NULL);
+ if (L) lua_atpanic(L, &panic);
+ return L;
+}
+
diff --git a/debian/grub-extras/lua/lauxlib.h b/debian/grub-extras/lua/lauxlib.h
new file mode 100644
index 0000000..f18864d
--- /dev/null
+++ b/debian/grub-extras/lua/lauxlib.h
@@ -0,0 +1,175 @@
+/*
+** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lauxlib_h
+#define lauxlib_h
+
+#if 0
+#include <stddef.h>
+#include <stdio.h>
+#endif
+
+#include "lua.h"
+
+
+#if defined(LUA_COMPAT_GETN)
+LUALIB_API int (luaL_getn) (lua_State *L, int t);
+LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
+#else
+#define luaL_getn(L,i) ((int)lua_objlen(L, i))
+#define luaL_setn(L,i,j) ((void)0) /* no op! */
+#endif
+
+#if defined(LUA_COMPAT_OPENLIB)
+#define luaI_openlib luaL_openlib
+#endif
+
+
+/* extra error code for `luaL_load' */
+#define LUA_ERRFILE (LUA_ERRERR+1)
+
+
+typedef struct luaL_Reg {
+ const char *name;
+ lua_CFunction func;
+} luaL_Reg;
+
+
+
+LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup);
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l);
+LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
+LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
+ size_t *l);
+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
+ const char *def, size_t *l);
+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
+
+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+ lua_Integer def);
+
+LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
+
+LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
+LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
+
+LUALIB_API void (luaL_where) (lua_State *L, int lvl);
+LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
+
+LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
+ const char *const lst[]);
+
+LUALIB_API int (luaL_ref) (lua_State *L, int t);
+LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
+
+LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
+LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
+ const char *name);
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
+
+LUALIB_API lua_State *(luaL_newstate) (void);
+
+
+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
+ const char *r);
+
+LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
+ const char *fname, int szhint);
+
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define luaL_argcheck(L, cond,numarg,extramsg) \
+ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
+#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
+#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
+#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
+#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
+#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
+#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
+
+#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
+
+#define luaL_dofile(L, fn) \
+ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_dostring(L, s) \
+ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
+
+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+
+typedef struct luaL_Buffer {
+ char *p; /* current position in buffer */
+ int lvl; /* number of strings in the stack (level) */
+ lua_State *L;
+ char buffer[LUAL_BUFFERSIZE];
+} luaL_Buffer;
+
+#define luaL_addchar(B,c) \
+ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
+ (*(B)->p++ = (char)(c)))
+
+/* compatibility only */
+#define luaL_putchar(B,c) luaL_addchar(B,c)
+
+#define luaL_addsize(B,n) ((B)->p += (n))
+
+LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
+LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
+LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
+LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
+LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
+LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
+
+
+/* }====================================================== */
+
+
+/* compatibility with ref system */
+
+/* pre-defined references */
+#define LUA_NOREF (-2)
+#define LUA_REFNIL (-1)
+
+#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
+ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
+
+#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
+
+#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
+
+
+#define luaL_reg luaL_Reg
+
+#endif
+
+
diff --git a/debian/grub-extras/lua/lbaselib.c b/debian/grub-extras/lua/lbaselib.c
new file mode 100644
index 0000000..1bbb126
--- /dev/null
+++ b/debian/grub-extras/lua/lbaselib.c
@@ -0,0 +1,652 @@
+/*
+** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $
+** Basic library
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define lbaselib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+
+/*
+** If your system does not support `stdout', you can just remove this function.
+** If you need, you can define your own `print' function, following this
+** model but changing `fputs' to put the strings at a proper place
+** (a console window or a log file, for instance).
+*/
+static int luaB_print (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ lua_getglobal(L, "tostring");
+ for (i=1; i<=n; i++) {
+ const char *s;
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ s = lua_tostring(L, -1); /* get result */
+ if (s == NULL)
+ return luaL_error(L, LUA_QL("tostring") " must return a string to "
+ LUA_QL("print"));
+ if (i>1) fputs("\t", stdout);
+ fputs(s, stdout);
+ lua_pop(L, 1); /* pop result */
+ }
+ fputs("\n", stdout);
+ return 0;
+}
+
+
+static int luaB_tonumber (lua_State *L) {
+ int base = luaL_optint(L, 2, 10);
+ if (base == 10) { /* standard conversion */
+ luaL_checkany(L, 1);
+ if (lua_isnumber(L, 1)) {
+ lua_pushnumber(L, lua_tonumber(L, 1));
+ return 1;
+ }
+ }
+ else {
+ const char *s1 = luaL_checkstring(L, 1);
+ char *s2;
+ unsigned long n;
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+ n = strtoul(s1, &s2, base);
+ if (s1 != s2) { /* at least one valid digit? */
+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
+ if (*s2 == '\0') { /* no invalid trailing characters? */
+ lua_pushnumber(L, (lua_Number)n);
+ return 1;
+ }
+ }
+ }
+ lua_pushnil(L); /* else not a number */
+ return 1;
+}
+
+
+static int luaB_error (lua_State *L) {
+ int level = luaL_optint(L, 2, 1);
+ lua_settop(L, 1);
+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
+ luaL_where(L, level);
+ lua_pushvalue(L, 1);
+ lua_concat(L, 2);
+ }
+ return lua_error(L);
+}
+
+
+static int luaB_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L);
+ return 1; /* no metatable */
+ }
+ luaL_getmetafield(L, 1, "__metatable");
+ return 1; /* returns either __metatable field (if present) or metatable */
+}
+
+
+static int luaB_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ if (luaL_getmetafield(L, 1, "__metatable"))
+ luaL_error(L, "cannot change a protected metatable");
+ lua_settop(L, 2);
+ lua_setmetatable(L, 1);
+ return 1;
+}
+
+
+static void getfunc (lua_State *L, int opt) {
+ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
+ else {
+ lua_Debug ar;
+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
+ luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
+ if (lua_getstack(L, level, &ar) == 0)
+ luaL_argerror(L, 1, "invalid level");
+ lua_getinfo(L, "f", &ar);
+ if (lua_isnil(L, -1))
+ luaL_error(L, "no function environment for tail call at level %d",
+ level);
+ }
+}
+
+
+static int luaB_getfenv (lua_State *L) {
+ getfunc(L, 1);
+ if (lua_iscfunction(L, -1)) /* is a C function? */
+ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
+ else
+ lua_getfenv(L, -1);
+ return 1;
+}
+
+
+static int luaB_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ getfunc(L, 0);
+ lua_pushvalue(L, 2);
+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+ lua_setfenv(L, -2);
+ return 0;
+ }
+ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
+ luaL_error(L,
+ LUA_QL("setfenv") " cannot change environment of given object");
+ return 1;
+}
+
+
+static int luaB_rawequal (lua_State *L) {
+ luaL_checkany(L, 1);
+ luaL_checkany(L, 2);
+ lua_pushboolean(L, lua_rawequal(L, 1, 2));
+ return 1;
+}
+
+
+static int luaB_rawget (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_rawget(L, 1);
+ return 1;
+}
+
+static int luaB_rawset (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ luaL_checkany(L, 3);
+ lua_settop(L, 3);
+ lua_rawset(L, 1);
+ return 1;
+}
+
+
+static int luaB_gcinfo (lua_State *L) {
+ lua_pushinteger(L, lua_getgccount(L));
+ return 1;
+}
+
+
+static int luaB_collectgarbage (lua_State *L) {
+ static const char *const opts[] = {"stop", "restart", "collect",
+ "count", "step", "setpause", "setstepmul", NULL};
+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
+ int o = luaL_checkoption(L, 1, "collect", opts);
+ int ex = luaL_optint(L, 2, 0);
+ int res = lua_gc(L, optsnum[o], ex);
+ switch (optsnum[o]) {
+ case LUA_GCCOUNT: {
+ int b = lua_gc(L, LUA_GCCOUNTB, 0);
+ lua_pushnumber(L, res + ((lua_Number)b/1024));
+ return 1;
+ }
+ case LUA_GCSTEP: {
+ lua_pushboolean(L, res);
+ return 1;
+ }
+ default: {
+ lua_pushnumber(L, res);
+ return 1;
+ }
+ }
+}
+
+
+static int luaB_type (lua_State *L) {
+ luaL_checkany(L, 1);
+ lua_pushstring(L, luaL_typename(L, 1));
+ return 1;
+}
+
+
+static int luaB_next (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */
+ if (lua_next(L, 1))
+ return 2;
+ else {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+static int luaB_pairs (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushnil(L); /* and initial value */
+ return 3;
+}
+
+
+static int ipairsaux (lua_State *L) {
+ int i = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i++; /* next value */
+ lua_pushinteger(L, i);
+ lua_rawgeti(L, 1, i);
+ return (lua_isnil(L, -1)) ? 0 : 2;
+}
+
+
+static int luaB_ipairs (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushinteger(L, 0); /* and initial value */
+ return 3;
+}
+
+
+static int load_aux (lua_State *L, int status) {
+ if (status == 0) /* OK? */
+ return 1;
+ else {
+ lua_pushnil(L);
+ lua_insert(L, -2); /* put before error message */
+ return 2; /* return nil plus error message */
+ }
+}
+
+
+static int luaB_loadstring (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ const char *chunkname = luaL_optstring(L, 2, s);
+ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
+}
+
+
+static int luaB_loadfile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ return load_aux(L, luaL_loadfile(L, fname));
+}
+
+
+/*
+** Reader for generic `load' function: `lua_load' uses the
+** stack for internal stuff, so the reader cannot change the
+** stack top. Instead, it keeps its resulting string in a
+** reserved slot inside the stack.
+*/
+static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
+ (void)ud; /* to avoid warnings */
+ luaL_checkstack(L, 2, "too many nested functions");
+ lua_pushvalue(L, 1); /* get function */
+ lua_call(L, 0, 1); /* call it */
+ if (lua_isnil(L, -1)) {
+ *size = 0;
+ return NULL;
+ }
+ else if (lua_isstring(L, -1)) {
+ lua_replace(L, 3); /* save string in a reserved stack slot */
+ return lua_tolstring(L, 3, size);
+ }
+ else luaL_error(L, "reader function must return a string");
+ return NULL; /* to avoid warnings */
+}
+
+
+static int luaB_load (lua_State *L) {
+ int status;
+ const char *cname = luaL_optstring(L, 2, "=(load)");
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */
+ status = lua_load(L, generic_reader, NULL, cname);
+ return load_aux(L, status);
+}
+
+
+static int luaB_dofile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ int n = lua_gettop(L);
+ if (luaL_loadfile(L, fname) != 0) lua_error(L);
+ lua_call(L, 0, LUA_MULTRET);
+ return lua_gettop(L) - n;
+}
+
+
+static int luaB_assert (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_toboolean(L, 1))
+ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
+ return lua_gettop(L);
+}
+
+
+static int luaB_unpack (lua_State *L) {
+ int i, e, n;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i = luaL_optint(L, 2, 1);
+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
+ if (i > e) return 0; /* empty range */
+ n = e - i + 1; /* number of elements */
+ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
+ return luaL_error(L, "too many results to unpack");
+ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
+ while (i++ < e) /* push arg[i + 1...e] */
+ lua_rawgeti(L, 1, i);
+ return n;
+}
+
+
+static int luaB_select (lua_State *L) {
+ int n = lua_gettop(L);
+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
+ lua_pushinteger(L, n-1);
+ return 1;
+ }
+ else {
+ int i = luaL_checkint(L, 1);
+ if (i < 0) i = n + i;
+ else if (i > n) i = n;
+ luaL_argcheck(L, 1 <= i, 1, "index out of range");
+ return n - i;
+ }
+}
+
+
+static int luaB_pcall (lua_State *L) {
+ int status;
+ luaL_checkany(L, 1);
+ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
+ lua_pushboolean(L, (status == 0));
+ lua_insert(L, 1);
+ return lua_gettop(L); /* return status + all results */
+}
+
+
+static int luaB_xpcall (lua_State *L) {
+ int status;
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_insert(L, 1); /* put error function under function to be called */
+ status = lua_pcall(L, 0, LUA_MULTRET, 1);
+ lua_pushboolean(L, (status == 0));
+ lua_replace(L, 1);
+ return lua_gettop(L); /* return status + all results */
+}
+
+static int luaB_tostring (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
+ return 1; /* use its value */
+ switch (lua_type(L, 1)) {
+ case LUA_TNUMBER:
+ lua_pushstring(L, lua_tostring(L, 1));
+ break;
+ case LUA_TSTRING:
+ lua_pushvalue(L, 1);
+ break;
+ case LUA_TBOOLEAN:
+ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
+ break;
+ case LUA_TNIL:
+ lua_pushliteral(L, "nil");
+ break;
+ default:
+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
+ break;
+ }
+ return 1;
+}
+
+
+static int luaB_newproxy (lua_State *L) {
+ lua_settop(L, 1);
+ lua_newuserdata(L, 0); /* create proxy */
+ if (lua_toboolean(L, 1) == 0)
+ return 1; /* no metatable */
+ else if (lua_isboolean(L, 1)) {
+ lua_newtable(L); /* create a new metatable `m' ... */
+ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
+ lua_pushboolean(L, 1);
+ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
+ }
+ else {
+ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
+ if (lua_getmetatable(L, 1)) {
+ lua_rawget(L, lua_upvalueindex(1));
+ validproxy = lua_toboolean(L, -1);
+ lua_pop(L, 1); /* remove value */
+ }
+ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
+ lua_getmetatable(L, 1); /* metatable is valid; get it */
+ }
+ lua_setmetatable(L, 2);
+ return 1;
+}
+
+
+static const luaL_Reg base_funcs[] = {
+ {"assert", luaB_assert},
+ {"collectgarbage", luaB_collectgarbage},
+ {"dofile", luaB_dofile},
+ {"error", luaB_error},
+ {"gcinfo", luaB_gcinfo},
+ {"getfenv", luaB_getfenv},
+ {"getmetatable", luaB_getmetatable},
+ {"loadfile", luaB_loadfile},
+ {"load", luaB_load},
+ {"loadstring", luaB_loadstring},
+ {"next", luaB_next},
+ {"pcall", luaB_pcall},
+ {"print", luaB_print},
+ {"rawequal", luaB_rawequal},
+ {"rawget", luaB_rawget},
+ {"rawset", luaB_rawset},
+ {"select", luaB_select},
+ {"setfenv", luaB_setfenv},
+ {"setmetatable", luaB_setmetatable},
+ {"tonumber", luaB_tonumber},
+ {"tostring", luaB_tostring},
+ {"type", luaB_type},
+ {"unpack", luaB_unpack},
+ {"xpcall", luaB_xpcall},
+ {NULL, NULL}
+};
+
+
+/*
+** {======================================================
+** Coroutine library
+** =======================================================
+*/
+
+#define CO_RUN 0 /* running */
+#define CO_SUS 1 /* suspended */
+#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */
+#define CO_DEAD 3
+
+static const char *const statnames[] =
+ {"running", "suspended", "normal", "dead"};
+
+static int costatus (lua_State *L, lua_State *co) {
+ if (L == co) return CO_RUN;
+ switch (lua_status(co)) {
+ case LUA_YIELD:
+ return CO_SUS;
+ case 0: {
+ lua_Debug ar;
+ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
+ return CO_NOR; /* it is running */
+ else if (lua_gettop(co) == 0)
+ return CO_DEAD;
+ else
+ return CO_SUS; /* initial state */
+ }
+ default: /* some error occured */
+ return CO_DEAD;
+ }
+}
+
+
+static int luaB_costatus (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ lua_pushstring(L, statnames[costatus(L, co)]);
+ return 1;
+}
+
+
+static int auxresume (lua_State *L, lua_State *co, int narg) {
+ int status = costatus(L, co);
+ if (!lua_checkstack(co, narg))
+ luaL_error(L, "too many arguments to resume");
+ if (status != CO_SUS) {
+ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
+ return -1; /* error flag */
+ }
+ lua_xmove(L, co, narg);
+ lua_setlevel(L, co);
+ status = lua_resume(co, narg);
+ if (status == 0 || status == LUA_YIELD) {
+ int nres = lua_gettop(co);
+ if (!lua_checkstack(L, nres + 1))
+ luaL_error(L, "too many results to resume");
+ lua_xmove(co, L, nres); /* move yielded values */
+ return nres;
+ }
+ else {
+ lua_xmove(co, L, 1); /* move error message */
+ return -1; /* error flag */
+ }
+}
+
+
+static int luaB_coresume (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ int r;
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ r = auxresume(L, co, lua_gettop(L) - 1);
+ if (r < 0) {
+ lua_pushboolean(L, 0);
+ lua_insert(L, -2);
+ return 2; /* return false + error message */
+ }
+ else {
+ lua_pushboolean(L, 1);
+ lua_insert(L, -(r + 1));
+ return r + 1; /* return true + `resume' returns */
+ }
+}
+
+
+static int luaB_auxwrap (lua_State *L) {
+ lua_State *co = lua_tothread(L, lua_upvalueindex(1));
+ int r = auxresume(L, co, lua_gettop(L));
+ if (r < 0) {
+ if (lua_isstring(L, -1)) { /* error object is a string? */
+ luaL_where(L, 1); /* add extra info */
+ lua_insert(L, -2);
+ lua_concat(L, 2);
+ }
+ lua_error(L); /* propagate error */
+ }
+ return r;
+}
+
+
+static int luaB_cocreate (lua_State *L) {
+ lua_State *NL = lua_newthread(L);
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
+ "Lua function expected");
+ lua_pushvalue(L, 1); /* move function to top */
+ lua_xmove(L, NL, 1); /* move function from L to NL */
+ return 1;
+}
+
+
+static int luaB_cowrap (lua_State *L) {
+ luaB_cocreate(L);
+ lua_pushcclosure(L, luaB_auxwrap, 1);
+ return 1;
+}
+
+
+static int luaB_yield (lua_State *L) {
+ return lua_yield(L, lua_gettop(L));
+}
+
+
+static int luaB_corunning (lua_State *L) {
+ if (lua_pushthread(L))
+ lua_pushnil(L); /* main thread is not a coroutine */
+ return 1;
+}
+
+
+static const luaL_Reg co_funcs[] = {
+ {"create", luaB_cocreate},
+ {"resume", luaB_coresume},
+ {"running", luaB_corunning},
+ {"status", luaB_costatus},
+ {"wrap", luaB_cowrap},
+ {"yield", luaB_yield},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+static void auxopen (lua_State *L, const char *name,
+ lua_CFunction f, lua_CFunction u) {
+ lua_pushcfunction(L, u);
+ lua_pushcclosure(L, f, 1);
+ lua_setfield(L, -2, name);
+}
+
+
+static void base_open (lua_State *L) {
+ /* set global _G */
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setglobal(L, "_G");
+ /* open lib into global table */
+ luaL_register(L, "_G", base_funcs);
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
+ /* `newproxy' needs a weaktable as upvalue */
+ lua_createtable(L, 0, 1); /* new table `w' */
+ lua_pushvalue(L, -1); /* `w' will be its own metatable */
+ lua_setmetatable(L, -2);
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
+ lua_pushcclosure(L, luaB_newproxy, 1);
+ lua_setglobal(L, "newproxy"); /* set global `newproxy' */
+}
+
+
+LUALIB_API int luaopen_base (lua_State *L) {
+ base_open(L);
+ luaL_register(L, LUA_COLIBNAME, co_funcs);
+ return 2;
+}
+
diff --git a/debian/grub-extras/lua/lcode.c b/debian/grub-extras/lua/lcode.c
new file mode 100644
index 0000000..05dc3bf
--- /dev/null
+++ b/debian/grub-extras/lua/lcode.c
@@ -0,0 +1,852 @@
+/*
+** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <stdlib.h>
+#endif
+
+#define lcode_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "ltable.h"
+
+
+#define hasjumps(e) ((e)->t != (e)->f)
+
+
+static int isnumeral(expdesc *e) {
+ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+}
+
+
+void luaK_nil (FuncState *fs, int from, int n) {
+ Instruction *previous;
+ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
+ if (fs->pc == 0) { /* function start? */
+ if (from >= fs->nactvar)
+ return; /* positions are already clean */
+ }
+ else {
+ previous = &fs->f->code[fs->pc-1];
+ if (GET_OPCODE(*previous) == OP_LOADNIL) {
+ int pfrom = GETARG_A(*previous);
+ int pto = GETARG_B(*previous);
+ if (pfrom <= from && from <= pto+1) { /* can connect both? */
+ if (from+n-1 > pto)
+ SETARG_B(*previous, from+n-1);
+ return;
+ }
+ }
+ }
+ }
+ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
+}
+
+
+int luaK_jump (FuncState *fs) {
+ int jpc = fs->jpc; /* save list of jumps to here */
+ int j;
+ fs->jpc = NO_JUMP;
+ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
+ luaK_concat(fs, &j, jpc); /* keep them on hold */
+ return j;
+}
+
+
+void luaK_ret (FuncState *fs, int first, int nret) {
+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
+}
+
+
+static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
+ luaK_codeABC(fs, op, A, B, C);
+ return luaK_jump(fs);
+}
+
+
+static void fixjump (FuncState *fs, int pc, int dest) {
+ Instruction *jmp = &fs->f->code[pc];
+ int offset = dest-(pc+1);
+ lua_assert(dest != NO_JUMP);
+ if (abs(offset) > MAXARG_sBx)
+ luaX_syntaxerror(fs->ls, "control structure too long");
+ SETARG_sBx(*jmp, offset);
+}
+
+
+/*
+** returns current `pc' and marks it as a jump target (to avoid wrong
+** optimizations with consecutive instructions not in the same basic block).
+*/
+int luaK_getlabel (FuncState *fs) {
+ fs->lasttarget = fs->pc;
+ return fs->pc;
+}
+
+
+static int getjump (FuncState *fs, int pc) {
+ int offset = GETARG_sBx(fs->f->code[pc]);
+ if (offset == NO_JUMP) /* point to itself represents end of list */
+ return NO_JUMP; /* end of list */
+ else
+ return (pc+1)+offset; /* turn offset into absolute position */
+}
+
+
+static Instruction *getjumpcontrol (FuncState *fs, int pc) {
+ Instruction *pi = &fs->f->code[pc];
+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
+ return pi-1;
+ else
+ return pi;
+}
+
+
+/*
+** check whether list has any jump that do not produce a value
+** (or produce an inverted value)
+*/
+static int need_value (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list)) {
+ Instruction i = *getjumpcontrol(fs, list);
+ if (GET_OPCODE(i) != OP_TESTSET) return 1;
+ }
+ return 0; /* not found */
+}
+
+
+static int patchtestreg (FuncState *fs, int node, int reg) {
+ Instruction *i = getjumpcontrol(fs, node);
+ if (GET_OPCODE(*i) != OP_TESTSET)
+ return 0; /* cannot patch other instructions */
+ if (reg != NO_REG && reg != GETARG_B(*i))
+ SETARG_A(*i, reg);
+ else /* no register to put value or register already has the value */
+ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
+
+ return 1;
+}
+
+
+static void removevalues (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list))
+ patchtestreg(fs, list, NO_REG);
+}
+
+
+static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
+ int dtarget) {
+ while (list != NO_JUMP) {
+ int next = getjump(fs, list);
+ if (patchtestreg(fs, list, reg))
+ fixjump(fs, list, vtarget);
+ else
+ fixjump(fs, list, dtarget); /* jump to default target */
+ list = next;
+ }
+}
+
+
+static void dischargejpc (FuncState *fs) {
+ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
+ fs->jpc = NO_JUMP;
+}
+
+
+void luaK_patchlist (FuncState *fs, int list, int target) {
+ if (target == fs->pc)
+ luaK_patchtohere(fs, list);
+ else {
+ lua_assert(target < fs->pc);
+ patchlistaux(fs, list, target, NO_REG, target);
+ }
+}
+
+
+void luaK_patchtohere (FuncState *fs, int list) {
+ luaK_getlabel(fs);
+ luaK_concat(fs, &fs->jpc, list);
+}
+
+
+void luaK_concat (FuncState *fs, int *l1, int l2) {
+ if (l2 == NO_JUMP) return;
+ else if (*l1 == NO_JUMP)
+ *l1 = l2;
+ else {
+ int list = *l1;
+ int next;
+ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
+ list = next;
+ fixjump(fs, list, l2);
+ }
+}
+
+
+void luaK_checkstack (FuncState *fs, int n) {
+ int newstack = fs->freereg + n;
+ if (newstack > fs->f->maxstacksize) {
+ if (newstack >= MAXSTACK)
+ luaX_syntaxerror(fs->ls, "function or expression too complex");
+ fs->f->maxstacksize = cast_byte(newstack);
+ }
+}
+
+
+void luaK_reserveregs (FuncState *fs, int n) {
+ luaK_checkstack(fs, n);
+ fs->freereg += n;
+}
+
+
+static void freereg (FuncState *fs, int reg) {
+ if (!ISK(reg) && reg >= fs->nactvar) {
+ fs->freereg--;
+ lua_assert(reg == fs->freereg);
+ }
+}
+
+
+static void freeexp (FuncState *fs, expdesc *e) {
+ if (e->k == VNONRELOC)
+ freereg(fs, e->u.s.info);
+}
+
+
+static int addk (FuncState *fs, TValue *k, TValue *v) {
+ lua_State *L = fs->L;
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
+ if (ttisnumber(idx)) {
+ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+ return cast_int(nvalue(idx));
+ }
+ else { /* constant not found; create a new entry */
+ setnvalue(idx, cast_num(fs->nk));
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+ setobj(L, &f->k[fs->nk], v);
+ luaC_barrier(L, f, v);
+ return fs->nk++;
+ }
+}
+
+
+int luaK_stringK (FuncState *fs, TString *s) {
+ TValue o;
+ setsvalue(fs->L, &o, s);
+ return addk(fs, &o, &o);
+}
+
+
+int luaK_numberK (FuncState *fs, lua_Number r) {
+ TValue o;
+ setnvalue(&o, r);
+ return addk(fs, &o, &o);
+}
+
+
+static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+ return addk(fs, &o, &o);
+}
+
+
+static int nilK (FuncState *fs) {
+ TValue k, v;
+ setnilvalue(&v);
+ /* cannot use nil as key; instead use table itself to represent nil */
+ sethvalue(fs->L, &k, fs->h);
+ return addk(fs, &k, &v);
+}
+
+
+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ SETARG_C(getcode(fs, e), nresults+1);
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), nresults+1);
+ SETARG_A(getcode(fs, e), fs->freereg);
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+void luaK_setoneret (FuncState *fs, expdesc *e) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ e->k = VNONRELOC;
+ e->u.s.info = GETARG_A(getcode(fs, e));
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), 2);
+ e->k = VRELOCABLE; /* can relocate its simple result */
+ }
+}
+
+
+void luaK_dischargevars (FuncState *fs, expdesc *e) {
+ switch (e->k) {
+ case VLOCAL: {
+ e->k = VNONRELOC;
+ break;
+ }
+ case VUPVAL: {
+ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VGLOBAL: {
+ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VINDEXED: {
+ freereg(fs, e->u.s.aux);
+ freereg(fs, e->u.s.info);
+ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
+ e->k = VRELOCABLE;
+ break;
+ }
+ case VVARARG:
+ case VCALL: {
+ luaK_setoneret(fs, e);
+ break;
+ }
+ default: break; /* there is one value available (somewhere) */
+ }
+}
+
+
+static int code_label (FuncState *fs, int A, int b, int jump) {
+ luaK_getlabel(fs); /* those instructions may be jump targets */
+ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
+}
+
+
+static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: {
+ luaK_nil(fs, reg, 1);
+ break;
+ }
+ case VFALSE: case VTRUE: {
+ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
+ break;
+ }
+ case VK: {
+ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
+ break;
+ }
+ case VKNUM: {
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+ break;
+ }
+ case VRELOCABLE: {
+ Instruction *pc = &getcode(fs, e);
+ SETARG_A(*pc, reg);
+ break;
+ }
+ case VNONRELOC: {
+ if (reg != e->u.s.info)
+ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
+ break;
+ }
+ default: {
+ lua_assert(e->k == VVOID || e->k == VJMP);
+ return; /* nothing to do... */
+ }
+ }
+ e->u.s.info = reg;
+ e->k = VNONRELOC;
+}
+
+
+static void discharge2anyreg (FuncState *fs, expdesc *e) {
+ if (e->k != VNONRELOC) {
+ luaK_reserveregs(fs, 1);
+ discharge2reg(fs, e, fs->freereg-1);
+ }
+}
+
+
+static void exp2reg (FuncState *fs, expdesc *e, int reg) {
+ discharge2reg(fs, e, reg);
+ if (e->k == VJMP)
+ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
+ if (hasjumps(e)) {
+ int final; /* position after whole expression */
+ int p_f = NO_JUMP; /* position of an eventual LOAD false */
+ int p_t = NO_JUMP; /* position of an eventual LOAD true */
+ if (need_value(fs, e->t) || need_value(fs, e->f)) {
+ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
+ p_f = code_label(fs, reg, 0, 1);
+ p_t = code_label(fs, reg, 1, 0);
+ luaK_patchtohere(fs, fj);
+ }
+ final = luaK_getlabel(fs);
+ patchlistaux(fs, e->f, final, reg, p_f);
+ patchlistaux(fs, e->t, final, reg, p_t);
+ }
+ e->f = e->t = NO_JUMP;
+ e->u.s.info = reg;
+ e->k = VNONRELOC;
+}
+
+
+void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ freeexp(fs, e);
+ luaK_reserveregs(fs, 1);
+ exp2reg(fs, e, fs->freereg - 1);
+}
+
+
+int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ if (e->k == VNONRELOC) {
+ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
+ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
+ exp2reg(fs, e, e->u.s.info); /* put value on it */
+ return e->u.s.info;
+ }
+ }
+ luaK_exp2nextreg(fs, e); /* default */
+ return e->u.s.info;
+}
+
+
+void luaK_exp2val (FuncState *fs, expdesc *e) {
+ if (hasjumps(e))
+ luaK_exp2anyreg(fs, e);
+ else
+ luaK_dischargevars(fs, e);
+}
+
+
+int luaK_exp2RK (FuncState *fs, expdesc *e) {
+ luaK_exp2val(fs, e);
+ switch (e->k) {
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
+ case VNIL: {
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
+ e->u.s.info = (e->k == VNIL) ? nilK(fs) :
+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
+ boolK(fs, (e->k == VTRUE));
+ e->k = VK;
+ return RKASK(e->u.s.info);
+ }
+ else break;
+ }
+ case VK: {
+ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
+ return RKASK(e->u.s.info);
+ else break;
+ }
+ default: break;
+ }
+ /* not a constant in the right range: put it in a register */
+ return luaK_exp2anyreg(fs, e);
+}
+
+
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
+ switch (var->k) {
+ case VLOCAL: {
+ freeexp(fs, ex);
+ exp2reg(fs, ex, var->u.s.info);
+ return;
+ }
+ case VUPVAL: {
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
+ break;
+ }
+ case VGLOBAL: {
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
+ break;
+ }
+ case VINDEXED: {
+ int e = luaK_exp2RK(fs, ex);
+ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
+ break;
+ }
+ default: {
+ lua_assert(0); /* invalid var kind to store */
+ break;
+ }
+ }
+ freeexp(fs, ex);
+}
+
+
+void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
+ int func;
+ luaK_exp2anyreg(fs, e);
+ freeexp(fs, e);
+ func = fs->freereg;
+ luaK_reserveregs(fs, 2);
+ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
+ freeexp(fs, key);
+ e->u.s.info = func;
+ e->k = VNONRELOC;
+}
+
+
+static void invertjump (FuncState *fs, expdesc *e) {
+ Instruction *pc = getjumpcontrol(fs, e->u.s.info);
+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
+ GET_OPCODE(*pc) != OP_TEST);
+ SETARG_A(*pc, !(GETARG_A(*pc)));
+}
+
+
+static int jumponcond (FuncState *fs, expdesc *e, int cond) {
+ if (e->k == VRELOCABLE) {
+ Instruction ie = getcode(fs, e);
+ if (GET_OPCODE(ie) == OP_NOT) {
+ fs->pc--; /* remove previous OP_NOT */
+ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
+ }
+ /* else go through */
+ }
+ discharge2anyreg(fs, e);
+ freeexp(fs, e);
+ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
+}
+
+
+void luaK_goiftrue (FuncState *fs, expdesc *e) {
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VK: case VKNUM: case VTRUE: {
+ pc = NO_JUMP; /* always true; do nothing */
+ break;
+ }
+ case VFALSE: {
+ pc = luaK_jump(fs); /* always jump */
+ break;
+ }
+ case VJMP: {
+ invertjump(fs, e);
+ pc = e->u.s.info;
+ break;
+ }
+ default: {
+ pc = jumponcond(fs, e, 0);
+ break;
+ }
+ }
+ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
+ luaK_patchtohere(fs, e->t);
+ e->t = NO_JUMP;
+}
+
+
+static void luaK_goiffalse (FuncState *fs, expdesc *e) {
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: case VFALSE: {
+ pc = NO_JUMP; /* always false; do nothing */
+ break;
+ }
+ case VTRUE: {
+ pc = luaK_jump(fs); /* always jump */
+ break;
+ }
+ case VJMP: {
+ pc = e->u.s.info;
+ break;
+ }
+ default: {
+ pc = jumponcond(fs, e, 1);
+ break;
+ }
+ }
+ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
+ luaK_patchtohere(fs, e->f);
+ e->f = NO_JUMP;
+}
+
+
+static void codenot (FuncState *fs, expdesc *e) {
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+ case VNIL: case VFALSE: {
+ e->k = VTRUE;
+ break;
+ }
+ case VK: case VKNUM: case VTRUE: {
+ e->k = VFALSE;
+ break;
+ }
+ case VJMP: {
+ invertjump(fs, e);
+ break;
+ }
+ case VRELOCABLE:
+ case VNONRELOC: {
+ discharge2anyreg(fs, e);
+ freeexp(fs, e);
+ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
+ e->k = VRELOCABLE;
+ break;
+ }
+ default: {
+ lua_assert(0); /* cannot happen */
+ break;
+ }
+ }
+ /* interchange true and false lists */
+ { int temp = e->f; e->f = e->t; e->t = temp; }
+ removevalues(fs, e->f);
+ removevalues(fs, e->t);
+}
+
+
+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
+ t->u.s.aux = luaK_exp2RK(fs, k);
+ t->k = VINDEXED;
+}
+
+
+static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+ v1 = e1->u.nval;
+ v2 = e2->u.nval;
+ switch (op) {
+ case OP_ADD: r = luai_numadd(v1, v2); break;
+ case OP_SUB: r = luai_numsub(v1, v2); break;
+ case OP_MUL: r = luai_nummul(v1, v2); break;
+ case OP_DIV:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_nummod(v1, v2); break;
+ case OP_POW: r = luai_numpow(v1, v2); break;
+ case OP_UNM: r = luai_numunm(v1); break;
+ case OP_LEN: return 0; /* no constant folding for 'len' */
+ default: lua_assert(0); r = 0; break;
+ }
+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
+ e1->u.nval = r;
+ return 1;
+}
+
+
+static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
+ if (constfolding(op, e1, e2))
+ return;
+ else {
+ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
+ int o1 = luaK_exp2RK(fs, e1);
+ if (o1 > o2) {
+ freeexp(fs, e1);
+ freeexp(fs, e2);
+ }
+ else {
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ }
+ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
+ e1->k = VRELOCABLE;
+ }
+}
+
+
+static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
+ expdesc *e2) {
+ int o1 = luaK_exp2RK(fs, e1);
+ int o2 = luaK_exp2RK(fs, e2);
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ if (cond == 0 && op != OP_EQ) {
+ int temp; /* exchange args to replace by `<' or `<=' */
+ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
+ cond = 1;
+ }
+ e1->u.s.info = condjump(fs, op, cond, o1, o2);
+ e1->k = VJMP;
+}
+
+
+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+ switch (op) {
+ case OPR_MINUS: {
+ if (!isnumeral(e))
+ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
+ codearith(fs, OP_UNM, e, &e2);
+ break;
+ }
+ case OPR_NOT: codenot(fs, e); break;
+ case OPR_LEN: {
+ luaK_exp2anyreg(fs, e); /* cannot operate on constants */
+ codearith(fs, OP_LEN, e, &e2);
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
+ switch (op) {
+ case OPR_AND: {
+ luaK_goiftrue(fs, v);
+ break;
+ }
+ case OPR_OR: {
+ luaK_goiffalse(fs, v);
+ break;
+ }
+ case OPR_CONCAT: {
+ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
+ break;
+ }
+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
+ case OPR_MOD: case OPR_POW: {
+ if (!isnumeral(v)) luaK_exp2RK(fs, v);
+ break;
+ }
+ default: {
+ luaK_exp2RK(fs, v);
+ break;
+ }
+ }
+}
+
+
+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
+ switch (op) {
+ case OPR_AND: {
+ lua_assert(e1->t == NO_JUMP); /* list must be closed */
+ luaK_dischargevars(fs, e2);
+ luaK_concat(fs, &e2->f, e1->f);
+#if 0
+ *e1 = *e2;
+#else
+ memcpy (e1, e2, sizeof (*e1));
+#endif
+ break;
+ }
+ case OPR_OR: {
+ lua_assert(e1->f == NO_JUMP); /* list must be closed */
+ luaK_dischargevars(fs, e2);
+ luaK_concat(fs, &e2->t, e1->t);
+#if 0
+ *e1 = *e2;
+#else
+ memcpy (e1, e2, sizeof (*e1));
+#endif
+ break;
+ }
+ case OPR_CONCAT: {
+ luaK_exp2val(fs, e2);
+ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
+ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
+ freeexp(fs, e1);
+ SETARG_B(getcode(fs, e2), e1->u.s.info);
+ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
+ }
+ else {
+ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
+ codearith(fs, OP_CONCAT, e1, e2);
+ }
+ break;
+ }
+ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
+ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
+ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
+ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
+ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
+ case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
+ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
+ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
+ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
+ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
+ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
+ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
+ default: lua_assert(0);
+ }
+}
+
+
+void luaK_fixline (FuncState *fs, int line) {
+ fs->f->lineinfo[fs->pc - 1] = line;
+}
+
+
+static int luaK_code (FuncState *fs, Instruction i, int line) {
+ Proto *f = fs->f;
+ dischargejpc(fs); /* `pc' will change */
+ /* put new instruction in code array */
+ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
+ MAX_INT, "code size overflow");
+ f->code[fs->pc] = i;
+ /* save corresponding line information */
+ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
+ MAX_INT, "code size overflow");
+ f->lineinfo[fs->pc] = line;
+ return fs->pc++;
+}
+
+
+int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
+ lua_assert(getOpMode(o) == iABC);
+ lua_assert(getBMode(o) != OpArgN || b == 0);
+ lua_assert(getCMode(o) != OpArgN || c == 0);
+ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
+}
+
+
+int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
+ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+ lua_assert(getCMode(o) == OpArgN);
+ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
+}
+
+
+void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
+ int c;
+ int b = (tostore == LUA_MULTRET) ? 0 : tostore;
+ if (nelems == 0)
+ c = 1;
+ else
+ c = ((unsigned) nelems + LFIELDS_PER_FLUSH - 1)/LFIELDS_PER_FLUSH;
+ lua_assert(tostore != 0);
+ if (c <= MAXARG_C)
+ luaK_codeABC(fs, OP_SETLIST, base, b, c);
+ else {
+ luaK_codeABC(fs, OP_SETLIST, base, b, 0);
+ luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
+ }
+ fs->freereg = base + 1; /* free registers with list values */
+}
+
diff --git a/debian/grub-extras/lua/lcode.h b/debian/grub-extras/lua/lcode.h
new file mode 100644
index 0000000..b941c60
--- /dev/null
+++ b/debian/grub-extras/lua/lcode.h
@@ -0,0 +1,76 @@
+/*
+** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $
+** Code generator for Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lcode_h
+#define lcode_h
+
+#include "llex.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+
+
+/*
+** Marks the end of a patch list. It is an invalid value both as an absolute
+** address, and as a list link (would link an element to itself).
+*/
+#define NO_JUMP (-1)
+
+
+/*
+** grep "ORDER OPR" if you change these enums
+*/
+typedef enum BinOpr {
+ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
+ OPR_CONCAT,
+ OPR_NE, OPR_EQ,
+ OPR_LT, OPR_LE, OPR_GT, OPR_GE,
+ OPR_AND, OPR_OR,
+ OPR_NOBINOPR
+} BinOpr;
+
+
+typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
+
+
+#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info])
+
+#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
+
+#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
+
+LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
+LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
+LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
+LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
+LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
+LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
+LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
+LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
+LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
+LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
+LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
+LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
+LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
+LUAI_FUNC int luaK_jump (FuncState *fs);
+LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
+LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
+LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
+LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
+LUAI_FUNC int luaK_getlabel (FuncState *fs);
+LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
+LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+
+
+#endif
diff --git a/debian/grub-extras/lua/ldblib.c b/debian/grub-extras/lua/ldblib.c
new file mode 100644
index 0000000..c1c2d89
--- /dev/null
+++ b/debian/grub-extras/lua/ldblib.c
@@ -0,0 +1,398 @@
+/*
+** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
+** Interface from Lua to its debug API
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define ldblib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+static int db_getregistry (lua_State *L) {
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+ return 1;
+}
+
+
+static int db_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L); /* no metatable */
+ }
+ return 1;
+}
+
+
+static int db_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ lua_settop(L, 2);
+ lua_pushboolean(L, lua_setmetatable(L, 1));
+ return 1;
+}
+
+
+static int db_getfenv (lua_State *L) {
+ lua_getfenv(L, 1);
+ return 1;
+}
+
+
+static int db_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_settop(L, 2);
+ if (lua_setfenv(L, 1) == 0)
+ luaL_error(L, LUA_QL("setfenv")
+ " cannot change environment of given object");
+ return 1;
+}
+
+
+static void settabss (lua_State *L, const char *i, const char *v) {
+ lua_pushstring(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static void settabsi (lua_State *L, const char *i, int v) {
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static lua_State *getthread (lua_State *L, int *arg) {
+ if (lua_isthread(L, 1)) {
+ *arg = 1;
+ return lua_tothread(L, 1);
+ }
+ else {
+ *arg = 0;
+ return L;
+ }
+}
+
+
+static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
+ if (L == L1) {
+ lua_pushvalue(L, -2);
+ lua_remove(L, -3);
+ }
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, fname);
+}
+
+
+static int db_getinfo (lua_State *L) {
+ lua_Debug ar;
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
+ lua_pushnil(L); /* level out of range */
+ return 1;
+ }
+ }
+ else if (lua_isfunction(L, arg+1)) {
+ lua_pushfstring(L, ">%s", options);
+ options = lua_tostring(L, -1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ }
+ else
+ return luaL_argerror(L, arg+1, "function or level expected");
+ if (!lua_getinfo(L1, options, &ar))
+ return luaL_argerror(L, arg+2, "invalid option");
+ lua_createtable(L, 0, 2);
+ if (strchr(options, 'S')) {
+ settabss(L, "source", ar.source);
+ settabss(L, "short_src", ar.short_src);
+ settabsi(L, "linedefined", ar.linedefined);
+ settabsi(L, "lastlinedefined", ar.lastlinedefined);
+ settabss(L, "what", ar.what);
+ }
+ if (strchr(options, 'l'))
+ settabsi(L, "currentline", ar.currentline);
+ if (strchr(options, 'u'))
+ settabsi(L, "nups", ar.nups);
+ if (strchr(options, 'n')) {
+ settabss(L, "name", ar.name);
+ settabss(L, "namewhat", ar.namewhat);
+ }
+ if (strchr(options, 'L'))
+ treatstackoption(L, L1, "activelines");
+ if (strchr(options, 'f'))
+ treatstackoption(L, L1, "func");
+ return 1; /* return table */
+}
+
+
+static int db_getlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ const char *name;
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
+ if (name) {
+ lua_xmove(L1, L, 1);
+ lua_pushstring(L, name);
+ lua_pushvalue(L, -2);
+ return 2;
+ }
+ else {
+ lua_pushnil(L);
+ return 1;
+ }
+}
+
+
+static int db_setlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ luaL_checkany(L, arg+3);
+ lua_settop(L, arg+3);
+ lua_xmove(L, L1, 1);
+ lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
+ return 1;
+}
+
+
+static int auxupvalue (lua_State *L, int get) {
+ const char *name;
+ int n = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
+ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
+ if (name == NULL) return 0;
+ lua_pushstring(L, name);
+ lua_insert(L, -(get+1));
+ return get + 1;
+}
+
+
+static int db_getupvalue (lua_State *L) {
+ return auxupvalue(L, 1);
+}
+
+
+static int db_setupvalue (lua_State *L) {
+ luaL_checkany(L, 3);
+ return auxupvalue(L, 0);
+}
+
+
+
+static const char KEY_HOOK = 'h';
+
+
+static void hookf (lua_State *L, lua_Debug *ar) {
+ static const char *const hooknames[] =
+ {"call", "return", "line", "count", "tail return"};
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, L);
+ lua_rawget(L, -2);
+ if (lua_isfunction(L, -1)) {
+ lua_pushstring(L, hooknames[(int)ar->event]);
+ if (ar->currentline >= 0)
+ lua_pushinteger(L, ar->currentline);
+ else lua_pushnil(L);
+ lua_assert(lua_getinfo(L, "lS", ar));
+ lua_call(L, 2, 0);
+ }
+}
+
+
+static int makemask (const char *smask, int count) {
+ int mask = 0;
+ if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
+ if (strchr(smask, 'r')) mask |= LUA_MASKRET;
+ if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
+ return mask;
+}
+
+
+static char *unmakemask (int mask, char *smask) {
+ int i = 0;
+ if (mask & LUA_MASKCALL) smask[i++] = 'c';
+ if (mask & LUA_MASKRET) smask[i++] = 'r';
+ if (mask & LUA_MASKLINE) smask[i++] = 'l';
+ smask[i] = '\0';
+ return smask;
+}
+
+
+static void gethooktable (lua_State *L) {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 1);
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+}
+
+
+static int db_sethook (lua_State *L) {
+ int arg, mask, count;
+ lua_Hook func;
+ lua_State *L1 = getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ func = NULL; mask = 0; count = 0; /* turn off hooks */
+ }
+ else {
+ const char *smask = luaL_checkstring(L, arg+2);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ count = luaL_optint(L, arg+3, 0);
+ func = hookf; mask = makemask(smask, count);
+ }
+ gethooktable(L);
+ lua_pushlightuserdata(L, L1);
+ lua_pushvalue(L, arg+1);
+ lua_rawset(L, -3); /* set new hook */
+ lua_pop(L, 1); /* remove hook table */
+ lua_sethook(L1, func, mask, count); /* set hooks */
+ return 0;
+}
+
+
+static int db_gethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ char buff[5];
+ int mask = lua_gethookmask(L1);
+ lua_Hook hook = lua_gethook(L1);
+ if (hook != NULL && hook != hookf) /* external hook? */
+ lua_pushliteral(L, "external hook");
+ else {
+ gethooktable(L);
+ lua_pushlightuserdata(L, L1);
+ lua_rawget(L, -2); /* get hook */
+ lua_remove(L, -2); /* remove hook table */
+ }
+ lua_pushstring(L, unmakemask(mask, buff));
+ lua_pushinteger(L, lua_gethookcount(L1));
+ return 3;
+}
+
+
+static int db_debug (lua_State *L) {
+ for (;;) {
+ char buffer[250];
+ fputs("lua_debug> ", stderr);
+ if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
+ strcmp(buffer, "cont\n") == 0)
+ return 0;
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
+ lua_settop(L, 0); /* remove eventual returns */
+ }
+}
+
+
+#define LEVELS1 12 /* size of the first part of the stack */
+#define LEVELS2 10 /* size of the second part of the stack */
+
+static int db_errorfb (lua_State *L) {
+ int level;
+ int firstpart = 1; /* still before eventual `...' */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ lua_Debug ar;
+ if (lua_isnumber(L, arg+2)) {
+ level = (int)lua_tointeger(L, arg+2);
+ lua_pop(L, 1);
+ }
+ else
+ level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
+ if (lua_gettop(L) == arg)
+ lua_pushliteral(L, "");
+ else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
+ else lua_pushliteral(L, "\n");
+ lua_pushliteral(L, "stack traceback:");
+ while (lua_getstack(L1, level++, &ar)) {
+ if (level > LEVELS1 && firstpart) {
+ /* no more than `LEVELS2' more levels? */
+ if (!lua_getstack(L1, level+LEVELS2, &ar))
+ level--; /* keep going */
+ else {
+ lua_pushliteral(L, "\n\t..."); /* too many levels */
+ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
+ level++;
+ }
+ firstpart = 0;
+ continue;
+ }
+ lua_pushliteral(L, "\n\t");
+ lua_getinfo(L1, "Snl", &ar);
+ lua_pushfstring(L, "%s:", ar.short_src);
+ if (ar.currentline > 0)
+ lua_pushfstring(L, "%d:", ar.currentline);
+ if (*ar.namewhat != '\0') /* is there a name? */
+ lua_pushfstring(L, " in function " LUA_QS, ar.name);
+ else {
+ if (*ar.what == 'm') /* main? */
+ lua_pushfstring(L, " in main chunk");
+ else if (*ar.what == 'C' || *ar.what == 't')
+ lua_pushliteral(L, " ?"); /* C function or tail call */
+ else
+ lua_pushfstring(L, " in function <%s:%d>",
+ ar.short_src, ar.linedefined);
+ }
+ lua_concat(L, lua_gettop(L) - arg);
+ }
+ lua_concat(L, lua_gettop(L) - arg);
+ return 1;
+}
+
+
+static const luaL_Reg dblib[] = {
+ {"debug", db_debug},
+ {"getfenv", db_getfenv},
+ {"gethook", db_gethook},
+ {"getinfo", db_getinfo},
+ {"getlocal", db_getlocal},
+ {"getregistry", db_getregistry},
+ {"getmetatable", db_getmetatable},
+ {"getupvalue", db_getupvalue},
+ {"setfenv", db_setfenv},
+ {"sethook", db_sethook},
+ {"setlocal", db_setlocal},
+ {"setmetatable", db_setmetatable},
+ {"setupvalue", db_setupvalue},
+ {"traceback", db_errorfb},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_debug (lua_State *L) {
+ luaL_register(L, LUA_DBLIBNAME, dblib);
+ return 1;
+}
+
diff --git a/debian/grub-extras/lua/ldebug.c b/debian/grub-extras/lua/ldebug.c
new file mode 100644
index 0000000..25e790c
--- /dev/null
+++ b/debian/grub-extras/lua/ldebug.c
@@ -0,0 +1,638 @@
+/*
+** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $
+** Debug Interface
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#endif
+
+#define ldebug_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
+
+
+static int currentpc (lua_State *L, CallInfo *ci) {
+ if (!isLua(ci)) return -1; /* function is not a Lua function? */
+ if (ci == L->ci)
+ ci->savedpc = L->savedpc;
+ return pcRel(ci->savedpc, ci_func(ci)->l.p);
+}
+
+
+static int currentline (lua_State *L, CallInfo *ci) {
+ int pc = currentpc(L, ci);
+ if (pc < 0)
+ return -1; /* only active lua functions have current-line information */
+ else
+ return getline(ci_func(ci)->l.p, pc);
+}
+
+
+/*
+** this function can be called asynchronous (e.g. during a signal)
+*/
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
+ if (func == NULL || mask == 0) { /* turn off hooks? */
+ mask = 0;
+ func = NULL;
+ }
+ L->hook = func;
+ L->basehookcount = count;
+ resethookcount(L);
+ L->hookmask = cast_byte(mask);
+ return 1;
+}
+
+
+LUA_API lua_Hook lua_gethook (lua_State *L) {
+ return L->hook;
+}
+
+
+LUA_API int lua_gethookmask (lua_State *L) {
+ return L->hookmask;
+}
+
+
+LUA_API int lua_gethookcount (lua_State *L) {
+ return L->basehookcount;
+}
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
+ int status;
+ CallInfo *ci;
+ lua_lock(L);
+ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
+ level--;
+ if (f_isLua(ci)) /* Lua function? */
+ level -= ci->tailcalls; /* skip lost tail calls */
+ }
+ if (level == 0 && ci > L->base_ci) { /* level found? */
+ status = 1;
+ ar->i_ci = cast_int(ci - L->base_ci);
+ }
+ else if (level < 0) { /* level is of a lost tail call? */
+ status = 1;
+ ar->i_ci = 0;
+ }
+ else status = 0; /* no such level */
+ lua_unlock(L);
+ return status;
+}
+
+
+static Proto *getluaproto (CallInfo *ci) {
+ return (isLua(ci) ? ci_func(ci)->l.p : NULL);
+}
+
+
+static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
+ const char *name;
+ Proto *fp = getluaproto(ci);
+ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
+ return name; /* is a local variable in a Lua function */
+ else {
+ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
+ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
+ return "(*temporary)";
+ else
+ return NULL;
+ }
+}
+
+
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ luaA_pushobject(L, ci->base + (n - 1));
+ lua_unlock(L);
+ return name;
+}
+
+
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ setobjs2s(L, ci->base + (n - 1), L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+ return name;
+}
+
+
+static void funcinfo (lua_Debug *ar, Closure *cl) {
+ if (cl->c.isC) {
+ ar->source = "=[C]";
+ ar->linedefined = -1;
+ ar->lastlinedefined = -1;
+ ar->what = "C";
+ }
+ else {
+ ar->source = getstr(cl->l.p->source);
+ ar->linedefined = cl->l.p->linedefined;
+ ar->lastlinedefined = cl->l.p->lastlinedefined;
+ ar->what = (ar->linedefined == 0) ? "main" : "Lua";
+ }
+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+}
+
+
+static void info_tailcall (lua_Debug *ar) {
+ ar->name = ar->namewhat = "";
+ ar->what = "tail";
+ ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
+ ar->source = "=(tail call)";
+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+ ar->nups = 0;
+}
+
+
+static void collectvalidlines (lua_State *L, Closure *f) {
+ if (f == NULL || f->c.isC) {
+ setnilvalue(L->top);
+ }
+ else {
+ Table *t = luaH_new(L, 0, 0);
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
+}
+
+
+static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
+ Closure *f, CallInfo *ci) {
+ int status = 1;
+ if (f == NULL) {
+ info_tailcall(ar);
+ return status;
+ }
+ for (; *what; what++) {
+ switch (*what) {
+ case 'S': {
+ funcinfo(ar, f);
+ break;
+ }
+ case 'l': {
+ ar->currentline = (ci) ? currentline(L, ci) : -1;
+ break;
+ }
+ case 'u': {
+ ar->nups = f->c.nupvalues;
+ break;
+ }
+ case 'n': {
+ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
+ if (ar->namewhat == NULL) {
+ ar->namewhat = ""; /* not found */
+ ar->name = NULL;
+ }
+ break;
+ }
+ case 'L':
+ case 'f': /* handled by lua_getinfo */
+ break;
+ default: status = 0; /* invalid option */
+ }
+ }
+ return status;
+}
+
+
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
+ int status;
+ Closure *f = NULL;
+ CallInfo *ci = NULL;
+ lua_lock(L);
+ if (*what == '>') {
+ StkId func = L->top - 1;
+ luai_apicheck(L, ttisfunction(func));
+ what++; /* skip the '>' */
+ f = clvalue(func);
+ L->top--; /* pop function */
+ }
+ else if (ar->i_ci != 0) { /* no tail call? */
+ ci = L->base_ci + ar->i_ci;
+ lua_assert(ttisfunction(ci->func));
+ f = clvalue(ci->func);
+ }
+ status = auxgetinfo(L, what, ar, f, ci);
+ if (strchr(what, 'f')) {
+ if (f == NULL) setnilvalue(L->top);
+ else setclvalue(L, L->top, f);
+ incr_top(L);
+ }
+ if (strchr(what, 'L'))
+ collectvalidlines(L, f);
+ lua_unlock(L);
+ return status;
+}
+
+
+/*
+** {======================================================
+** Symbolic Execution and code checker
+** =======================================================
+*/
+
+#define check(x) if (!(x)) return 0;
+
+#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode)
+
+#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize)
+
+
+
+static int precheck (const Proto *pt) {
+ check(pt->maxstacksize <= MAXSTACK);
+ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
+ check(!(pt->is_vararg & VARARG_NEEDSARG) ||
+ (pt->is_vararg & VARARG_HASARG));
+ check(pt->sizeupvalues <= pt->nups);
+ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
+ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
+ return 1;
+}
+
+
+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
+
+int luaG_checkopenop (Instruction i) {
+ switch (GET_OPCODE(i)) {
+ case OP_CALL:
+ case OP_TAILCALL:
+ case OP_RETURN:
+ case OP_SETLIST: {
+ check(GETARG_B(i) == 0);
+ return 1;
+ }
+ default: return 0; /* invalid instruction after an open call */
+ }
+}
+
+
+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
+ switch (mode) {
+ case OpArgN: check(r == 0); break;
+ case OpArgU: break;
+ case OpArgR: checkreg(pt, r); break;
+ case OpArgK:
+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
+ break;
+ }
+ return 1;
+}
+
+
+static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
+ int pc;
+ int last; /* stores position of last instruction that changed `reg' */
+ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
+ check(precheck(pt));
+ for (pc = 0; pc < lastpc; pc++) {
+ Instruction i = pt->code[pc];
+ OpCode op = GET_OPCODE(i);
+ int a = GETARG_A(i);
+ int b = 0;
+ int c = 0;
+ check(op < NUM_OPCODES);
+ checkreg(pt, a);
+ switch (getOpMode(op)) {
+ case iABC: {
+ b = GETARG_B(i);
+ c = GETARG_C(i);
+ check(checkArgMode(pt, b, getBMode(op)));
+ check(checkArgMode(pt, c, getCMode(op)));
+ break;
+ }
+ case iABx: {
+ b = GETARG_Bx(i);
+ if (getBMode(op) == OpArgK) check(b < pt->sizek);
+ break;
+ }
+ case iAsBx: {
+ b = GETARG_sBx(i);
+ if (getBMode(op) == OpArgR) {
+ int dest = pc+1+b;
+ check(0 <= dest && dest < pt->sizecode);
+ if (dest > 0) {
+ int j;
+ /* check that it does not jump to a setlist count; this
+ is tricky, because the count from a previous setlist may
+ have the same value of an invalid setlist; so, we must
+ go all the way back to the first of them (if any) */
+ for (j = 0; j < dest; j++) {
+ Instruction d = pt->code[dest-1-j];
+ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
+ }
+ /* if 'j' is even, previous value is not a setlist (even if
+ it looks like one) */
+ check((j&1) == 0);
+ }
+ }
+ break;
+ }
+ }
+ if (testAMode(op)) {
+ if (a == reg) last = pc; /* change register `a' */
+ }
+ if (testTMode(op)) {
+ check(pc+2 < pt->sizecode); /* check skip */
+ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
+ }
+ switch (op) {
+ case OP_LOADBOOL: {
+ if (c == 1) { /* does it jump? */
+ check(pc+2 < pt->sizecode); /* check its jump */
+ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
+ GETARG_C(pt->code[pc+1]) != 0);
+ }
+ break;
+ }
+ case OP_LOADNIL: {
+ if (a <= reg && reg <= b)
+ last = pc; /* set registers from `a' to `b' */
+ break;
+ }
+ case OP_GETUPVAL:
+ case OP_SETUPVAL: {
+ check(b < pt->nups);
+ break;
+ }
+ case OP_GETGLOBAL:
+ case OP_SETGLOBAL: {
+ check(ttisstring(&pt->k[b]));
+ break;
+ }
+ case OP_SELF: {
+ checkreg(pt, a+1);
+ if (reg == a+1) last = pc;
+ break;
+ }
+ case OP_CONCAT: {
+ check(b < c); /* at least two operands */
+ break;
+ }
+ case OP_TFORLOOP: {
+ check(c >= 1); /* at least one result (control variable) */
+ checkreg(pt, a+2+c); /* space for results */
+ if (reg >= a+2) last = pc; /* affect all regs above its base */
+ break;
+ }
+ case OP_FORLOOP:
+ case OP_FORPREP:
+ checkreg(pt, a+3);
+ /* go through */
+ case OP_JMP: {
+ int dest = pc+1+b;
+ /* not full check and jump is forward and do not skip `lastpc'? */
+ if (reg != NO_REG && pc < dest && dest <= lastpc)
+ pc += b; /* do the jump */
+ break;
+ }
+ case OP_CALL:
+ case OP_TAILCALL: {
+ if (b != 0) {
+ checkreg(pt, a+b-1);
+ }
+ c--; /* c = num. returns */
+ if (c == LUA_MULTRET) {
+ check(checkopenop(pt, pc));
+ }
+ else if (c != 0)
+ checkreg(pt, a+c-1);
+ if (reg >= a) last = pc; /* affect all registers above base */
+ break;
+ }
+ case OP_RETURN: {
+ b--; /* b = num. returns */
+ if (b > 0) checkreg(pt, a+b-1);
+ break;
+ }
+ case OP_SETLIST: {
+ if (b > 0) checkreg(pt, a + b);
+ if (c == 0) {
+ pc++;
+ check(pc < pt->sizecode - 1);
+ }
+ break;
+ }
+ case OP_CLOSURE: {
+ int nup, j;
+ check(b < pt->sizep);
+ nup = pt->p[b]->nups;
+ check(pc + nup < pt->sizecode);
+ for (j = 1; j <= nup; j++) {
+ OpCode op1 = GET_OPCODE(pt->code[pc + j]);
+ check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
+ }
+ if (reg != NO_REG) /* tracing? */
+ pc += nup; /* do not 'execute' these pseudo-instructions */
+ break;
+ }
+ case OP_VARARG: {
+ check((pt->is_vararg & VARARG_ISVARARG) &&
+ !(pt->is_vararg & VARARG_NEEDSARG));
+ b--;
+ if (b == LUA_MULTRET) check(checkopenop(pt, pc));
+ checkreg(pt, a+b-1);
+ break;
+ }
+ default: break;
+ }
+ }
+ return pt->code[last];
+}
+
+#undef check
+#undef checkjump
+#undef checkreg
+
+/* }====================================================== */
+
+
+int luaG_checkcode (const Proto *pt) {
+ return (symbexec(pt, pt->sizecode, NO_REG) != 0);
+}
+
+
+static const char *kname (Proto *p, int c) {
+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
+ return svalue(&p->k[INDEXK(c)]);
+ else
+ return "?";
+}
+
+
+static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
+ const char **name) {
+ if (isLua(ci)) { /* a Lua function? */
+ Proto *p = ci_func(ci)->l.p;
+ int pc = currentpc(L, ci);
+ Instruction i;
+ *name = luaF_getlocalname(p, stackpos+1, pc);
+ if (*name) /* is a local? */
+ return "local";
+ i = symbexec(p, pc, stackpos); /* try symbolic execution */
+ lua_assert(pc != -1);
+ switch (GET_OPCODE(i)) {
+ case OP_GETGLOBAL: {
+ int g = GETARG_Bx(i); /* global index */
+ lua_assert(ttisstring(&p->k[g]));
+ *name = svalue(&p->k[g]);
+ return "global";
+ }
+ case OP_MOVE: {
+ int a = GETARG_A(i);
+ int b = GETARG_B(i); /* move from `b' to `a' */
+ if (b < a)
+ return getobjname(L, ci, b, name); /* get name for `b' */
+ break;
+ }
+ case OP_GETTABLE: {
+ int k = GETARG_C(i); /* key index */
+ *name = kname(p, k);
+ return "field";
+ }
+ case OP_GETUPVAL: {
+ int u = GETARG_B(i); /* upvalue index */
+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
+ return "upvalue";
+ }
+ case OP_SELF: {
+ int k = GETARG_C(i); /* key index */
+ *name = kname(p, k);
+ return "method";
+ }
+ default: break;
+ }
+ }
+ return NULL; /* no useful name found */
+}
+
+
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
+ Instruction i;
+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
+ return NULL; /* calling function is not Lua (or is unknown) */
+ ci--; /* calling function */
+ i = ci_func(ci)->l.p->code[currentpc(L, ci)];
+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
+ GET_OPCODE(i) == OP_TFORLOOP)
+ return getobjname(L, ci, GETARG_A(i), name);
+ else
+ return NULL; /* no useful name can be found */
+}
+
+
+/* only ANSI way to check whether a pointer points to an array */
+static int isinstack (CallInfo *ci, const TValue *o) {
+ StkId p;
+ for (p = ci->base; p < ci->top; p++)
+ if (o == p) return 1;
+ return 0;
+}
+
+
+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+ const char *name = NULL;
+ const char *t = luaT_typenames[ttype(o)];
+ const char *kind = (isinstack(L->ci, o)) ?
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
+ if (kind)
+ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
+ op, kind, name, t);
+ else
+ luaG_runerror(L, "attempt to %s a %s value", op, t);
+}
+
+
+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
+ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
+ lua_assert(!ttisstring(p1) && !ttisnumber(p1));
+ luaG_typeerror(L, p1, "concatenate");
+}
+
+
+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
+ TValue temp;
+ if (luaV_tonumber(p1, &temp) == NULL)
+ p2 = p1; /* first operand is wrong */
+ luaG_typeerror(L, p2, "perform arithmetic on");
+}
+
+
+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+ const char *t1 = luaT_typenames[ttype(p1)];
+ const char *t2 = luaT_typenames[ttype(p2)];
+ if (t1[2] == t2[2])
+ luaG_runerror(L, "attempt to compare two %s values", t1);
+ else
+ luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
+ return 0;
+}
+
+
+static void addinfo (lua_State *L, const char *msg) {
+ CallInfo *ci = L->ci;
+ if (isLua(ci)) { /* is Lua code? */
+ char buff[LUA_IDSIZE]; /* add file:line information */
+ int line = currentline(L, ci);
+ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
+ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
+ }
+}
+
+
+void luaG_errormsg (lua_State *L) {
+ if (L->errfunc != 0) { /* is there an error handling function? */
+ StkId errfunc = restorestack(L, L->errfunc);
+ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
+ setobjs2s(L, L->top, L->top - 1); /* move argument */
+ setobjs2s(L, L->top - 1, errfunc); /* push function */
+ incr_top(L);
+ luaD_call(L, L->top - 2, 1); /* call it */
+ }
+ luaD_throw(L, LUA_ERRRUN);
+}
+
+
+void luaG_runerror (lua_State *L, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ addinfo(L, luaO_pushvfstring(L, fmt, argp));
+ va_end(argp);
+ luaG_errormsg(L);
+}
+
diff --git a/debian/grub-extras/lua/ldebug.h b/debian/grub-extras/lua/ldebug.h
new file mode 100644
index 0000000..ba28a97
--- /dev/null
+++ b/debian/grub-extras/lua/ldebug.h
@@ -0,0 +1,33 @@
+/*
+** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions from Debug Interface module
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldebug_h
+#define ldebug_h
+
+
+#include "lstate.h"
+
+
+#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
+
+#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
+
+#define resethookcount(L) (L->hookcount = L->basehookcount)
+
+
+LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,
+ const char *opname);
+LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
+LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,
+ const TValue *p2);
+LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,
+ const TValue *p2);
+LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaG_errormsg (lua_State *L);
+LUAI_FUNC int luaG_checkcode (const Proto *pt);
+LUAI_FUNC int luaG_checkopenop (Instruction i);
+
+#endif
diff --git a/debian/grub-extras/lua/ldo.c b/debian/grub-extras/lua/ldo.c
new file mode 100644
index 0000000..a267e7b
--- /dev/null
+++ b/debian/grub-extras/lua/ldo.c
@@ -0,0 +1,519 @@
+/*
+** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define ldo_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lundump.h"
+#include "lvm.h"
+#include "lzio.h"
+
+
+
+
+/*
+** {======================================================
+** Error-recovery functions
+** =======================================================
+*/
+
+
+/* chain list of long jump buffers */
+struct lua_longjmp {
+ struct lua_longjmp *previous;
+ luai_jmpbuf b;
+ volatile int status; /* error code */
+};
+
+
+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
+ switch (errcode) {
+ case LUA_ERRMEM: {
+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
+ break;
+ }
+ case LUA_ERRERR: {
+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
+ break;
+ }
+ case LUA_ERRSYNTAX:
+ case LUA_ERRRUN: {
+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
+ break;
+ }
+ }
+ L->top = oldtop + 1;
+}
+
+
+static void restore_stack_limit (lua_State *L) {
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
+ int inuse = cast_int(L->ci - L->base_ci);
+ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
+ luaD_reallocCI(L, LUAI_MAXCALLS);
+ }
+}
+
+
+static void resetstack (lua_State *L, int status) {
+ L->ci = L->base_ci;
+ L->base = L->ci->base;
+ luaF_close(L, L->base); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, L->base);
+ L->nCcalls = L->baseCcalls;
+ L->allowhook = 1;
+ restore_stack_limit(L);
+ L->errfunc = 0;
+ L->errorJmp = NULL;
+}
+
+
+void luaD_throw (lua_State *L, int errcode) {
+ if (L->errorJmp) {
+ L->errorJmp->status = errcode;
+ LUAI_THROW(L, L->errorJmp);
+ }
+ else {
+ L->status = cast_byte(errcode);
+ if (G(L)->panic) {
+ resetstack(L, errcode);
+ lua_unlock(L);
+ G(L)->panic(L);
+ }
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
+ struct lua_longjmp lj;
+ lj.status = 0;
+ lj.previous = L->errorJmp; /* chain new error handler */
+ L->errorJmp = &lj;
+ LUAI_TRY(L, &lj,
+ (*f)(L, ud);
+ );
+ L->errorJmp = lj.previous; /* restore old error handler */
+ return lj.status;
+}
+
+/* }====================================================== */
+
+
+static void correctstack (lua_State *L, TValue *oldstack) {
+ CallInfo *ci;
+ GCObject *up;
+ L->top = (L->top - oldstack) + L->stack;
+ for (up = L->openupval; up != NULL; up = up->gch.next)
+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
+ for (ci = L->base_ci; ci <= L->ci; ci++) {
+ ci->top = (ci->top - oldstack) + L->stack;
+ ci->base = (ci->base - oldstack) + L->stack;
+ ci->func = (ci->func - oldstack) + L->stack;
+ }
+ L->base = (L->base - oldstack) + L->stack;
+}
+
+
+void luaD_reallocstack (lua_State *L, int newsize) {
+ TValue *oldstack = L->stack;
+ int realsize = newsize + 1 + EXTRA_STACK;
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
+ L->stacksize = realsize;
+ L->stack_last = L->stack+newsize;
+ correctstack(L, oldstack);
+}
+
+
+void luaD_reallocCI (lua_State *L, int newsize) {
+ CallInfo *oldci = L->base_ci;
+ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
+ L->size_ci = newsize;
+ L->ci = (L->ci - oldci) + L->base_ci;
+ L->end_ci = L->base_ci + L->size_ci - 1;
+}
+
+
+void luaD_growstack (lua_State *L, int n) {
+ if (n <= L->stacksize) /* double size is enough? */
+ luaD_reallocstack(L, 2*L->stacksize);
+ else
+ luaD_reallocstack(L, L->stacksize + n);
+}
+
+
+static CallInfo *growCI (lua_State *L) {
+ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
+ luaD_throw(L, LUA_ERRERR);
+ else {
+ luaD_reallocCI(L, 2*L->size_ci);
+ if (L->size_ci > LUAI_MAXCALLS)
+ luaG_runerror(L, "stack overflow");
+ }
+ return ++L->ci;
+}
+
+
+void luaD_callhook (lua_State *L, int event, int line) {
+ lua_Hook hook = L->hook;
+ if (hook && L->allowhook) {
+ ptrdiff_t top = savestack(L, L->top);
+ ptrdiff_t ci_top = savestack(L, L->ci->top);
+ lua_Debug ar;
+ ar.event = event;
+ ar.currentline = line;
+ if (event == LUA_HOOKTAILRET)
+ ar.i_ci = 0; /* tail call; no debug information about it */
+ else
+ ar.i_ci = cast_int(L->ci - L->base_ci);
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ L->ci->top = L->top + LUA_MINSTACK;
+ lua_assert(L->ci->top <= L->stack_last);
+ L->allowhook = 0; /* cannot call hooks inside a hook */
+ lua_unlock(L);
+ (*hook)(L, &ar);
+ lua_lock(L);
+ lua_assert(!L->allowhook);
+ L->allowhook = 1;
+ L->ci->top = restorestack(L, ci_top);
+ L->top = restorestack(L, top);
+ }
+}
+
+
+static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
+ int i;
+ int nfixargs = p->numparams;
+ Table *htab = NULL;
+ StkId base, fixed;
+ for (; actual < nfixargs; ++actual)
+ setnilvalue(L->top++);
+#if defined(LUA_COMPAT_VARARG)
+ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
+ int nvar = actual - nfixargs; /* number of extra arguments */
+ lua_assert(p->is_vararg & VARARG_HASARG);
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+ setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
+ }
+#endif
+ /* move fixed parameters to final position */
+ fixed = L->top - actual; /* first fixed argument */
+ base = L->top; /* final position of first argument */
+ for (i=0; i<nfixargs; i++) {
+ setobjs2s(L, L->top++, fixed+i);
+ setnilvalue(fixed+i);
+ }
+ /* add `arg' parameter */
+ if (htab) {
+ sethvalue(L, L->top++, htab);
+ lua_assert(iswhite(obj2gco(htab)));
+ }
+ return base;
+}
+
+
+static StkId tryfuncTM (lua_State *L, StkId func) {
+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
+ StkId p;
+ ptrdiff_t funcr = savestack(L, func);
+ if (!ttisfunction(tm))
+ luaG_typeerror(L, func, "call");
+ /* Open a hole inside the stack at `func' */
+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
+ incr_top(L);
+ func = restorestack(L, funcr); /* previous call may change stack */
+ setobj2s(L, func, tm); /* tag method is the new function to be called */
+ return func;
+}
+
+
+
+#define inc_ci(L) \
+ ((L->ci == L->end_ci) ? growCI(L) : \
+ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
+
+
+int luaD_precall (lua_State *L, StkId func, int nresults) {
+ LClosure *cl;
+ ptrdiff_t funcr;
+ if (!ttisfunction(func)) /* `func' is not a function? */
+ func = tryfuncTM(L, func); /* check the `function' tag method */
+ funcr = savestack(L, func);
+ cl = &clvalue(func)->l;
+ L->ci->savedpc = L->savedpc;
+ if (!cl->isC) { /* Lua function? prepare its call */
+ CallInfo *ci;
+ StkId st, base;
+ Proto *p = cl->p;
+ luaD_checkstack(L, p->maxstacksize);
+ func = restorestack(L, funcr);
+ if (!p->is_vararg) { /* no varargs? */
+ base = func + 1;
+ if (L->top > base + p->numparams)
+ L->top = base + p->numparams;
+ }
+ else { /* vararg function */
+ int nargs = cast_int(L->top - func) - 1;
+ base = adjust_varargs(L, p, nargs);
+ func = restorestack(L, funcr); /* previous call may change the stack */
+ }
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = func;
+ L->base = ci->base = base;
+ ci->top = L->base + p->maxstacksize;
+ lua_assert(ci->top <= L->stack_last);
+ L->savedpc = p->code; /* starting point */
+ ci->tailcalls = 0;
+ ci->nresults = nresults;
+ for (st = L->top; st < ci->top; st++)
+ setnilvalue(st);
+ L->top = ci->top;
+ if (L->hookmask & LUA_MASKCALL) {
+ L->savedpc++; /* hooks assume 'pc' is already incremented */
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ L->savedpc--; /* correct 'pc' */
+ }
+ return PCRLUA;
+ }
+ else { /* if is a C function, call it */
+ CallInfo *ci;
+ int n;
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = restorestack(L, funcr);
+ L->base = ci->base = ci->func + 1;
+ ci->top = L->top + LUA_MINSTACK;
+ lua_assert(ci->top <= L->stack_last);
+ ci->nresults = nresults;
+ if (L->hookmask & LUA_MASKCALL)
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ lua_unlock(L);
+ n = (*curr_func(L)->c.f)(L); /* do the actual call */
+ lua_lock(L);
+ if (n < 0) /* yielding? */
+ return PCRYIELD;
+ else {
+ luaD_poscall(L, L->top - n);
+ return PCRC;
+ }
+ }
+}
+
+
+static StkId callrethooks (lua_State *L, StkId firstResult) {
+ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
+ luaD_callhook(L, LUA_HOOKRET, -1);
+ if (f_isLua(L->ci)) { /* Lua function? */
+ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
+ luaD_callhook(L, LUA_HOOKTAILRET, -1);
+ }
+ return restorestack(L, fr);
+}
+
+
+int luaD_poscall (lua_State *L, StkId firstResult) {
+ StkId res;
+ int wanted, i;
+ CallInfo *ci;
+ if (L->hookmask & LUA_MASKRET)
+ firstResult = callrethooks(L, firstResult);
+ ci = L->ci--;
+ res = ci->func; /* res == final position of 1st result */
+ wanted = ci->nresults;
+ L->base = (ci - 1)->base; /* restore base */
+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
+ /* move results to correct place */
+ for (i = wanted; i != 0 && firstResult < L->top; i--)
+ setobjs2s(L, res++, firstResult++);
+ while (i-- > 0)
+ setnilvalue(res++);
+ L->top = res;
+ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
+}
+
+
+/*
+** Call a function (C or Lua). The function to be called is at *func.
+** The arguments are on the stack, right after the function.
+** When returns, all the results are on the stack, starting at the original
+** function position.
+*/
+void luaD_call (lua_State *L, StkId func, int nResults) {
+ if (++L->nCcalls >= LUAI_MAXCCALLS) {
+ if (L->nCcalls == LUAI_MAXCCALLS)
+ luaG_runerror(L, "C stack overflow");
+ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
+ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
+ }
+ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
+ luaV_execute(L, 1); /* call it */
+ L->nCcalls--;
+ luaC_checkGC(L);
+}
+
+
+static void resume (lua_State *L, void *ud) {
+ StkId firstArg = cast(StkId, ud);
+ CallInfo *ci = L->ci;
+ if (L->status == 0) { /* start coroutine? */
+ lua_assert(ci == L->base_ci && firstArg > L->base);
+ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
+ return;
+ }
+ else { /* resuming from previous yield */
+ lua_assert(L->status == LUA_YIELD);
+ L->status = 0;
+ if (!f_isLua(ci)) { /* `common' yield? */
+ /* finish interrupted execution of `OP_CALL' */
+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
+ if (luaD_poscall(L, firstArg)) /* complete it... */
+ L->top = L->ci->top; /* and correct top if not multiple results */
+ }
+ else /* yielded inside a hook: just continue its execution */
+ L->base = L->ci->base;
+ }
+ luaV_execute(L, cast_int(L->ci - L->base_ci));
+}
+
+
+static int resume_error (lua_State *L, const char *msg) {
+ L->top = L->ci->base;
+ setsvalue2s(L, L->top, luaS_new(L, msg));
+ incr_top(L);
+ lua_unlock(L);
+ return LUA_ERRRUN;
+}
+
+
+LUA_API int lua_resume (lua_State *L, int nargs) {
+ int status;
+ lua_lock(L);
+ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
+ return resume_error(L, "cannot resume non-suspended coroutine");
+ if (L->nCcalls >= LUAI_MAXCCALLS)
+ return resume_error(L, "C stack overflow");
+ luai_userstateresume(L, nargs);
+ lua_assert(L->errfunc == 0);
+ L->baseCcalls = ++L->nCcalls;
+ status = luaD_rawrunprotected(L, resume, L->top - nargs);
+ if (status != 0) { /* error? */
+ L->status = cast_byte(status); /* mark thread as `dead' */
+ luaD_seterrorobj(L, status, L->top);
+ L->ci->top = L->top;
+ }
+ else {
+ lua_assert(L->nCcalls == L->baseCcalls);
+ status = L->status;
+ }
+ --L->nCcalls;
+ lua_unlock(L);
+ return status;
+}
+
+
+LUA_API int lua_yield (lua_State *L, int nresults) {
+ luai_userstateyield(L, nresults);
+ lua_lock(L);
+ if (L->nCcalls > L->baseCcalls)
+ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
+ L->base = L->top - nresults; /* protect stack slots below */
+ L->status = LUA_YIELD;
+ lua_unlock(L);
+ return -1;
+}
+
+
+int luaD_pcall (lua_State *L, Pfunc func, void *u,
+ ptrdiff_t old_top, ptrdiff_t ef) {
+ int status;
+ unsigned short oldnCcalls = L->nCcalls;
+ ptrdiff_t old_ci = saveci(L, L->ci);
+ lu_byte old_allowhooks = L->allowhook;
+ ptrdiff_t old_errfunc = L->errfunc;
+ L->errfunc = ef;
+ status = luaD_rawrunprotected(L, func, u);
+ if (status != 0) { /* an error occurred? */
+ StkId oldtop = restorestack(L, old_top);
+ luaF_close(L, oldtop); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, oldtop);
+ L->nCcalls = oldnCcalls;
+ L->ci = restoreci(L, old_ci);
+ L->base = L->ci->base;
+ L->savedpc = L->ci->savedpc;
+ L->allowhook = old_allowhooks;
+ restore_stack_limit(L);
+ }
+ L->errfunc = old_errfunc;
+ return status;
+}
+
+
+
+/*
+** Execute a protected parser.
+*/
+struct SParser { /* data to `f_parser' */
+ ZIO *z;
+ Mbuffer buff; /* buffer to be used by the scanner */
+ const char *name;
+};
+
+static void f_parser (lua_State *L, void *ud) {
+ int i;
+ Proto *tf;
+ Closure *cl;
+ struct SParser *p = cast(struct SParser *, ud);
+ int c = luaZ_lookahead(p->z);
+ luaC_checkGC(L);
+ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
+ &p->buff, p->name);
+ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
+ cl->l.p = tf;
+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
+ cl->l.upvals[i] = luaF_newupval(L);
+ setclvalue(L, L->top, cl);
+ incr_top(L);
+}
+
+
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
+ struct SParser p;
+ int status;
+ p.z = z; p.name = name;
+ luaZ_initbuffer(L, &p.buff);
+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
+ luaZ_freebuffer(L, &p.buff);
+ return status;
+}
+
+
diff --git a/debian/grub-extras/lua/ldo.h b/debian/grub-extras/lua/ldo.h
new file mode 100644
index 0000000..abd0b84
--- /dev/null
+++ b/debian/grub-extras/lua/ldo.h
@@ -0,0 +1,57 @@
+/*
+** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldo_h
+#define ldo_h
+
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+#define luaD_checkstack(L,n) \
+ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
+ luaD_growstack(L, n); \
+ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
+
+
+#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
+
+#define savestack(L,p) ((TValue *)(p) - (TValue *)L->stack)
+#define restorestack(L,n) ((TValue *)((TValue *)L->stack + (n)))
+
+#define saveci(L,p) ((CallInfo *)(p) - (CallInfo *)L->base_ci)
+#define restoreci(L,n) ((CallInfo *)((CallInfo *)L->base_ci + (n)))
+
+
+/* results from luaD_precall */
+#define PCRLUA 0 /* initiated a call to a Lua function */
+#define PCRC 1 /* did a call to a C function */
+#define PCRYIELD 2 /* C funtion yielded */
+
+
+/* type of protected functions, to be ran by `runprotected' */
+typedef void (*Pfunc) (lua_State *L, void *ud);
+
+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
+LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
+LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
+LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
+ ptrdiff_t oldtop, ptrdiff_t ef);
+LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
+LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
+LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+
+LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
+LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+
+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
+
+#endif
+
diff --git a/debian/grub-extras/lua/ldump.c b/debian/grub-extras/lua/ldump.c
new file mode 100644
index 0000000..c9d3d48
--- /dev/null
+++ b/debian/grub-extras/lua/ldump.c
@@ -0,0 +1,164 @@
+/*
+** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
+** save precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#include <stddef.h>
+
+#define ldump_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lundump.h"
+
+typedef struct {
+ lua_State* L;
+ lua_Writer writer;
+ void* data;
+ int strip;
+ int status;
+} DumpState;
+
+#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
+#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
+
+static void DumpBlock(const void* b, size_t size, DumpState* D)
+{
+ if (D->status==0)
+ {
+ lua_unlock(D->L);
+ D->status=(*D->writer)(D->L,b,size,D->data);
+ lua_lock(D->L);
+ }
+}
+
+static void DumpChar(int y, DumpState* D)
+{
+ char x=(char)y;
+ DumpVar(x,D);
+}
+
+static void DumpInt(int x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
+static void DumpNumber(lua_Number x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
+static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+{
+ DumpInt(n,D);
+ DumpMem(b,n,size,D);
+}
+
+static void DumpString(const TString* s, DumpState* D)
+{
+ if (s==NULL || getstr(s)==NULL)
+ {
+ size_t size=0;
+ DumpVar(size,D);
+ }
+ else
+ {
+ size_t size=s->tsv.len+1; /* include trailing '\0' */
+ DumpVar(size,D);
+ DumpBlock(getstr(s),size,D);
+ }
+}
+
+#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
+
+static void DumpConstants(const Proto* f, DumpState* D)
+{
+ int i,n=f->sizek;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ const TValue* o=&f->k[i];
+ DumpChar(ttype(o),D);
+ switch (ttype(o))
+ {
+ case LUA_TNIL:
+ break;
+ case LUA_TBOOLEAN:
+ DumpChar(bvalue(o),D);
+ break;
+ case LUA_TNUMBER:
+ DumpNumber(nvalue(o),D);
+ break;
+ case LUA_TSTRING:
+ DumpString(rawtsvalue(o),D);
+ break;
+ default:
+ lua_assert(0); /* cannot happen */
+ break;
+ }
+ }
+ n=f->sizep;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
+}
+
+static void DumpDebug(const Proto* f, DumpState* D)
+{
+ int i,n;
+ n= (D->strip) ? 0 : f->sizelineinfo;
+ DumpVector(f->lineinfo,n,sizeof(int),D);
+ n= (D->strip) ? 0 : f->sizelocvars;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ DumpString(f->locvars[i].varname,D);
+ DumpInt(f->locvars[i].startpc,D);
+ DumpInt(f->locvars[i].endpc,D);
+ }
+ n= (D->strip) ? 0 : f->sizeupvalues;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
+}
+
+static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
+{
+ DumpString((f->source==p || D->strip) ? NULL : f->source,D);
+ DumpInt(f->linedefined,D);
+ DumpInt(f->lastlinedefined,D);
+ DumpChar(f->nups,D);
+ DumpChar(f->numparams,D);
+ DumpChar(f->is_vararg,D);
+ DumpChar(f->maxstacksize,D);
+ DumpCode(f,D);
+ DumpConstants(f,D);
+ DumpDebug(f,D);
+}
+
+static void DumpHeader(DumpState* D)
+{
+ char h[LUAC_HEADERSIZE];
+ luaU_header(h);
+ DumpBlock(h,LUAC_HEADERSIZE,D);
+}
+
+/*
+** dump Lua function as precompiled chunk
+*/
+int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
+{
+ DumpState D;
+ D.L=L;
+ D.writer=w;
+ D.data=data;
+ D.strip=strip;
+ D.status=0;
+ DumpHeader(&D);
+ DumpFunction(f,NULL,&D);
+ return D.status;
+}
diff --git a/debian/grub-extras/lua/lfunc.c b/debian/grub-extras/lua/lfunc.c
new file mode 100644
index 0000000..813e88f
--- /dev/null
+++ b/debian/grub-extras/lua/lfunc.c
@@ -0,0 +1,174 @@
+/*
+** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lfunc_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
+ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
+ c->c.isC = 1;
+ c->c.env = e;
+ c->c.nupvalues = cast_byte(nelems);
+ return c;
+}
+
+
+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
+ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
+ c->l.isC = 0;
+ c->l.env = e;
+ c->l.nupvalues = cast_byte(nelems);
+ while (nelems--) c->l.upvals[nelems] = NULL;
+ return c;
+}
+
+
+UpVal *luaF_newupval (lua_State *L) {
+ UpVal *uv = luaM_new(L, UpVal);
+ luaC_link(L, obj2gco(uv), LUA_TUPVAL);
+ uv->v = &uv->u.value;
+ setnilvalue(uv->v);
+ return uv;
+}
+
+
+UpVal *luaF_findupval (lua_State *L, StkId level) {
+ global_State *g = G(L);
+ GCObject **pp = &L->openupval;
+ UpVal *p;
+ UpVal *uv;
+ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
+ lua_assert(p->v != &p->u.value);
+ if (p->v == level) { /* found a corresponding upvalue? */
+ if (isdead(g, obj2gco(p))) /* is it dead? */
+ changewhite(obj2gco(p)); /* ressurect it */
+ return p;
+ }
+ pp = &p->next;
+ }
+ uv = luaM_new(L, UpVal); /* not found: create a new one */
+ uv->tt = LUA_TUPVAL;
+ uv->marked = luaC_white(g);
+ uv->v = level; /* current value lives in the stack */
+ uv->next = *pp; /* chain it in the proper position */
+ *pp = obj2gco(uv);
+ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
+ uv->u.l.next = g->uvhead.u.l.next;
+ uv->u.l.next->u.l.prev = uv;
+ g->uvhead.u.l.next = uv;
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ return uv;
+}
+
+
+static void unlinkupval (UpVal *uv) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
+ uv->u.l.prev->u.l.next = uv->u.l.next;
+}
+
+
+void luaF_freeupval (lua_State *L, UpVal *uv) {
+ if (uv->v != &uv->u.value) /* is it open? */
+ unlinkupval(uv); /* remove from open list */
+ luaM_free(L, uv); /* free upvalue */
+}
+
+
+void luaF_close (lua_State *L, StkId level) {
+ UpVal *uv;
+ global_State *g = G(L);
+ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
+ GCObject *o = obj2gco(uv);
+ lua_assert(!isblack(o) && uv->v != &uv->u.value);
+ L->openupval = uv->next; /* remove from `open' list */
+ if (isdead(g, o))
+ luaF_freeupval(L, uv); /* free upvalue */
+ else {
+ unlinkupval(uv);
+ setobj(L, &uv->u.value, uv->v);
+ uv->v = &uv->u.value; /* now current value lives here */
+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
+ }
+ }
+}
+
+
+Proto *luaF_newproto (lua_State *L) {
+ Proto *f = luaM_new(L, Proto);
+ luaC_link(L, obj2gco(f), LUA_TPROTO);
+ f->k = NULL;
+ f->sizek = 0;
+ f->p = NULL;
+ f->sizep = 0;
+ f->code = NULL;
+ f->sizecode = 0;
+ f->sizelineinfo = 0;
+ f->sizeupvalues = 0;
+ f->nups = 0;
+ f->upvalues = NULL;
+ f->numparams = 0;
+ f->is_vararg = 0;
+ f->maxstacksize = 0;
+ f->lineinfo = NULL;
+ f->sizelocvars = 0;
+ f->locvars = NULL;
+ f->linedefined = 0;
+ f->lastlinedefined = 0;
+ f->source = NULL;
+ return f;
+}
+
+
+void luaF_freeproto (lua_State *L, Proto *f) {
+ luaM_freearray(L, f->code, f->sizecode, Instruction);
+ luaM_freearray(L, f->p, f->sizep, Proto *);
+ luaM_freearray(L, f->k, f->sizek, TValue);
+ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
+ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
+ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
+ luaM_free(L, f);
+}
+
+
+void luaF_freeclosure (lua_State *L, Closure *c) {
+ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
+ sizeLclosure(c->l.nupvalues);
+ luaM_freemem(L, c, size);
+}
+
+
+/*
+** Look for n-th local variable at line `line' in function `func'.
+** Returns NULL if not found.
+*/
+const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
+ int i;
+ for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
+ if (pc < f->locvars[i].endpc) { /* is variable active? */
+ local_number--;
+ if (local_number == 0)
+ return getstr(f->locvars[i].varname);
+ }
+ }
+ return NULL; /* not found */
+}
+
diff --git a/debian/grub-extras/lua/lfunc.h b/debian/grub-extras/lua/lfunc.h
new file mode 100644
index 0000000..a68cf51
--- /dev/null
+++ b/debian/grub-extras/lua/lfunc.h
@@ -0,0 +1,34 @@
+/*
+** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lfunc_h
+#define lfunc_h
+
+
+#include "lobject.h"
+
+
+#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
+ cast(int, sizeof(TValue)*((n)-1)))
+
+#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
+ cast(int, sizeof(TValue *)*((n)-1)))
+
+
+LUAI_FUNC Proto *luaF_newproto (lua_State *L);
+LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
+LUAI_FUNC void luaF_close (lua_State *L, StkId level);
+LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
+LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
+LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
+LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
+ int pc);
+
+
+#endif
diff --git a/debian/grub-extras/lua/lgc.c b/debian/grub-extras/lua/lgc.c
new file mode 100644
index 0000000..1d62975
--- /dev/null
+++ b/debian/grub-extras/lua/lgc.c
@@ -0,0 +1,713 @@
+/*
+** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <string.h>
+#endif
+
+#define lgc_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+#define GCSTEPSIZE 1024u
+#define GCSWEEPMAX 40
+#define GCSWEEPCOST 10
+#define GCFINALIZECOST 100
+
+
+#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
+
+#define makewhite(g,x) \
+ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
+
+#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
+
+#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
+
+
+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
+#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
+
+
+#define KEYWEAK bitmask(KEYWEAKBIT)
+#define VALUEWEAK bitmask(VALUEWEAKBIT)
+
+
+
+#define markvalue(g,o) { checkconsistency(o); \
+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
+
+#define markobject(g,t) { if (iswhite(obj2gco(t))) \
+ reallymarkobject(g, obj2gco(t)); }
+
+
+#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
+
+
+static void removeentry (Node *n) {
+ lua_assert(ttisnil(gval(n)));
+ if (iscollectable(gkey(n)))
+ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
+}
+
+
+static void reallymarkobject (global_State *g, GCObject *o) {
+ lua_assert(iswhite(o) && !isdead(g, o));
+ white2gray(o);
+ switch (o->gch.tt) {
+ case LUA_TSTRING: {
+ return;
+ }
+ case LUA_TUSERDATA: {
+ Table *mt = gco2u(o)->metatable;
+ gray2black(o); /* udata are never gray */
+ if (mt) markobject(g, mt);
+ markobject(g, gco2u(o)->env);
+ return;
+ }
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ markvalue(g, uv->v);
+ if (uv->v == &uv->u.value) /* closed? */
+ gray2black(o); /* open upvalues are never black */
+ return;
+ }
+ case LUA_TFUNCTION: {
+ gco2cl(o)->c.gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TTABLE: {
+ gco2h(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TTHREAD: {
+ gco2th(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ case LUA_TPROTO: {
+ gco2p(o)->gclist = g->gray;
+ g->gray = o;
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+static void marktmu (global_State *g) {
+ GCObject *u = g->tmudata;
+ if (u) {
+ do {
+ u = u->gch.next;
+ makewhite(g, u); /* may be marked, if left from previous GC */
+ reallymarkobject(g, u);
+ } while (u != g->tmudata);
+ }
+}
+
+
+/* move `dead' udata that need finalization to list `tmudata' */
+size_t luaC_separateudata (lua_State *L, int all) {
+ global_State *g = G(L);
+ size_t deadmem = 0;
+ GCObject **p = &g->mainthread->next;
+ GCObject *curr;
+ while ((curr = *p) != NULL) {
+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
+ p = &curr->gch.next; /* don't bother with them */
+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
+ markfinalized(gco2u(curr)); /* don't need finalization */
+ p = &curr->gch.next;
+ }
+ else { /* must call its gc method */
+ deadmem += sizeudata(gco2u(curr));
+ markfinalized(gco2u(curr));
+ *p = curr->gch.next;
+ /* link `curr' at the end of `tmudata' list */
+ if (g->tmudata == NULL) /* list is empty? */
+ g->tmudata = curr->gch.next = curr; /* creates a circular list */
+ else {
+ curr->gch.next = g->tmudata->gch.next;
+ g->tmudata->gch.next = curr;
+ g->tmudata = curr;
+ }
+ }
+ }
+ return deadmem;
+}
+
+
+static int traversetable (global_State *g, Table *h) {
+ int i;
+ int weakkey = 0;
+ int weakvalue = 0;
+ const TValue *mode;
+ if (h->metatable)
+ markobject(g, h->metatable);
+ mode = gfasttm(g, h->metatable, TM_MODE);
+ if (mode && ttisstring(mode)) { /* is there a weak mode? */
+ weakkey = (strchr(svalue(mode), 'k') != NULL);
+ weakvalue = (strchr(svalue(mode), 'v') != NULL);
+ if (weakkey || weakvalue) { /* is really weak? */
+ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
+ h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
+ (weakvalue << VALUEWEAKBIT));
+ h->gclist = g->weak; /* must be cleared after GC, ... */
+ g->weak = obj2gco(h); /* ... so put in the appropriate list */
+ }
+ }
+ if (weakkey && weakvalue) return 1;
+ if (!weakvalue) {
+ i = h->sizearray;
+ while (i--)
+ markvalue(g, &h->array[i]);
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
+ if (ttisnil(gval(n)))
+ removeentry(n); /* remove empty entries */
+ else {
+ lua_assert(!ttisnil(gkey(n)));
+ if (!weakkey) markvalue(g, gkey(n));
+ if (!weakvalue) markvalue(g, gval(n));
+ }
+ }
+ return weakkey || weakvalue;
+}
+
+
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void traverseproto (global_State *g, Proto *f) {
+ int i;
+ if (f->source) stringmark(f->source);
+ for (i=0; i<f->sizek; i++) /* mark literals */
+ markvalue(g, &f->k[i]);
+ for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
+ if (f->upvalues[i])
+ stringmark(f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) { /* mark nested protos */
+ if (f->p[i])
+ markobject(g, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
+ if (f->locvars[i].varname)
+ stringmark(f->locvars[i].varname);
+ }
+}
+
+
+
+static void traverseclosure (global_State *g, Closure *cl) {
+ markobject(g, cl->c.env);
+ if (cl->c.isC) {
+ int i;
+ for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
+ markvalue(g, &cl->c.upvalue[i]);
+ }
+ else {
+ int i;
+ lua_assert(cl->l.nupvalues == cl->l.p->nups);
+ markobject(g, cl->l.p);
+ for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
+ markobject(g, cl->l.upvals[i]);
+ }
+}
+
+
+static void checkstacksizes (lua_State *L, StkId max) {
+ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */
+ int s_used = cast_int(max - L->stack); /* part of stack in use */
+ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */
+ return; /* do not touch the stacks */
+ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
+ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
+ condhardstacktests(luaD_reallocCI(L, ci_used + 1));
+ if (4*s_used < L->stacksize &&
+ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
+ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
+ condhardstacktests(luaD_reallocstack(L, s_used));
+}
+
+
+static void traversestack (global_State *g, lua_State *l) {
+ StkId o, lim;
+ CallInfo *ci;
+ markvalue(g, gt(l));
+ lim = l->top;
+ for (ci = l->base_ci; ci <= l->ci; ci++) {
+ lua_assert(ci->top <= l->stack_last);
+ if (lim < ci->top) lim = ci->top;
+ }
+ for (o = l->stack; o < l->top; o++)
+ markvalue(g, o);
+ for (; o <= lim; o++)
+ setnilvalue(o);
+ checkstacksizes(l, lim);
+}
+
+
+/*
+** traverse one gray object, turning it to black.
+** Returns `quantity' traversed.
+*/
+static l_mem propagatemark (global_State *g) {
+ GCObject *o = g->gray;
+ lua_assert(isgray(o));
+ gray2black(o);
+ switch (o->gch.tt) {
+ case LUA_TTABLE: {
+ Table *h = gco2h(o);
+ g->gray = h->gclist;
+ if (traversetable(g, h)) /* table is weak? */
+ black2gray(o); /* keep it gray */
+ return sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
+ }
+ case LUA_TFUNCTION: {
+ Closure *cl = gco2cl(o);
+ g->gray = cl->c.gclist;
+ traverseclosure(g, cl);
+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+ sizeLclosure(cl->l.nupvalues);
+ }
+ case LUA_TTHREAD: {
+ lua_State *th = gco2th(o);
+ g->gray = th->gclist;
+ th->gclist = g->grayagain;
+ g->grayagain = o;
+ black2gray(o);
+ traversestack(g, th);
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->size_ci;
+ }
+ case LUA_TPROTO: {
+ Proto *p = gco2p(o);
+ g->gray = p->gclist;
+ traverseproto(g, p);
+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+ sizeof(Proto *) * p->sizep +
+ sizeof(TValue) * p->sizek +
+ sizeof(int) * p->sizelineinfo +
+ sizeof(LocVar) * p->sizelocvars +
+ sizeof(TString *) * p->sizeupvalues;
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+static size_t propagateall (global_State *g) {
+ size_t m = 0;
+ while (g->gray) m += propagatemark(g);
+ return m;
+}
+
+
+/*
+** The next function tells whether a key or value can be cleared from
+** a weak table. Non-collectable objects are never removed from weak
+** tables. Strings behave as `values', so are never removed too. for
+** other objects: if really collected, cannot keep them; for userdata
+** being finalized, keep them in keys, but not in values
+*/
+static int iscleared (const TValue *o, int iskey) {
+ if (!iscollectable(o)) return 0;
+ if (ttisstring(o)) {
+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
+ return 0;
+ }
+ return iswhite(gcvalue(o)) ||
+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
+}
+
+
+/*
+** clear collected entries from weaktables
+*/
+static void cleartable (GCObject *l) {
+ while (l) {
+ Table *h = gco2h(l);
+ int i = h->sizearray;
+ lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
+ testbit(h->marked, KEYWEAKBIT));
+ if (testbit(h->marked, VALUEWEAKBIT)) {
+ while (i--) {
+ TValue *o = &h->array[i];
+ if (iscleared(o, 0)) /* value was collected? */
+ setnilvalue(o); /* remove value */
+ }
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ if (!ttisnil(gval(n)) && /* non-empty entry? */
+ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
+ setnilvalue(gval(n)); /* remove value ... */
+ removeentry(n); /* remove entry from table */
+ }
+ }
+ l = h->gclist;
+ }
+}
+
+
+static void freeobj (lua_State *L, GCObject *o) {
+ switch (o->gch.tt) {
+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
+ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
+ case LUA_TTHREAD: {
+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
+ luaE_freethread(L, gco2th(o));
+ break;
+ }
+ case LUA_TSTRING: {
+ G(L)->strt.nuse--;
+ luaM_freemem(L, o, sizestring(gco2ts(o)));
+ break;
+ }
+ case LUA_TUSERDATA: {
+ luaM_freemem(L, o, sizeudata(gco2u(o)));
+ break;
+ }
+ default: lua_assert(0);
+ }
+}
+
+
+
+#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
+
+
+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
+ GCObject *curr;
+ global_State *g = G(L);
+ int deadmask = otherwhite(g);
+ while ((curr = *p) != NULL && count-- > 0) {
+ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
+ sweepwholelist(L, &gco2th(curr)->openupval);
+ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
+ makewhite(g, curr); /* make it white (for next cycle) */
+ p = &curr->gch.next;
+ }
+ else { /* must erase `curr' */
+ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
+ *p = curr->gch.next;
+ if (curr == g->rootgc) /* is the first element of the list? */
+ g->rootgc = curr->gch.next; /* adjust first */
+ freeobj(L, curr);
+ }
+ }
+ return p;
+}
+
+
+static void checkSizes (lua_State *L) {
+ global_State *g = G(L);
+ /* check size of string hash */
+ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
+ g->strt.size > MINSTRTABSIZE*2)
+ luaS_resize(L, g->strt.size/2); /* table is too big */
+ /* check size of buffer */
+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
+ luaZ_resizebuffer(L, &g->buff, newsize);
+ }
+}
+
+
+static void GCTM (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o = g->tmudata->gch.next; /* get first element */
+ Udata *udata = rawgco2u(o);
+ const TValue *tm;
+ /* remove udata from `tmudata' */
+ if (o == g->tmudata) /* last element? */
+ g->tmudata = NULL;
+ else
+ g->tmudata->gch.next = udata->uv.next;
+ udata->uv.next = g->mainthread->next; /* return it to `root' list */
+ g->mainthread->next = o;
+ makewhite(g, o);
+ tm = fasttm(L, udata->uv.metatable, TM_GC);
+ if (tm != NULL) {
+ lu_byte oldah = L->allowhook;
+ lu_mem oldt = g->GCthreshold;
+ L->allowhook = 0; /* stop debug hooks during GC tag method */
+ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */
+ setobj2s(L, L->top, tm);
+ setuvalue(L, L->top+1, udata);
+ L->top += 2;
+ luaD_call(L, L->top - 2, 0);
+ L->allowhook = oldah; /* restore hooks */
+ g->GCthreshold = oldt; /* restore threshold */
+ }
+}
+
+
+/*
+** Call all GC tag methods
+*/
+void luaC_callGCTM (lua_State *L) {
+ while (G(L)->tmudata)
+ GCTM(L);
+}
+
+
+void luaC_freeall (lua_State *L) {
+ global_State *g = G(L);
+ int i;
+ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */
+ sweepwholelist(L, &g->rootgc);
+ for (i = 0; i < g->strt.size; i++) /* free all string lists */
+ sweepwholelist(L, &g->strt.hash[i]);
+}
+
+
+static void markmt (global_State *g) {
+ int i;
+ for (i=0; i<NUM_TAGS; i++)
+ if (g->mt[i]) markobject(g, g->mt[i]);
+}
+
+
+/* mark root set */
+static void markroot (lua_State *L) {
+ global_State *g = G(L);
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ markobject(g, g->mainthread);
+ /* make global table be traversed before main stack */
+ markvalue(g, gt(g->mainthread));
+ markvalue(g, registry(L));
+ markmt(g);
+ g->gcstate = GCSpropagate;
+}
+
+
+static void remarkupvals (global_State *g) {
+ UpVal *uv;
+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ if (isgray(obj2gco(uv)))
+ markvalue(g, uv->v);
+ }
+}
+
+
+static void atomic (lua_State *L) {
+ global_State *g = G(L);
+ size_t udsize; /* total size of userdata to be finalized */
+ /* remark occasional upvalues of (maybe) dead threads */
+ remarkupvals(g);
+ /* traverse objects cautch by write barrier and by 'remarkupvals' */
+ propagateall(g);
+ /* remark weak tables */
+ g->gray = g->weak;
+ g->weak = NULL;
+ lua_assert(!iswhite(obj2gco(g->mainthread)));
+ markobject(g, L); /* mark running thread */
+ markmt(g); /* mark basic metatables (again) */
+ propagateall(g);
+ /* remark gray again */
+ g->gray = g->grayagain;
+ g->grayagain = NULL;
+ propagateall(g);
+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
+ marktmu(g); /* mark `preserved' userdata */
+ udsize += propagateall(g); /* remark, to propagate `preserveness' */
+ cleartable(g->weak); /* remove collected objects from weak tables */
+ /* flip current white */
+ g->currentwhite = cast_byte(otherwhite(g));
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gcstate = GCSsweepstring;
+ g->estimate = g->totalbytes - udsize; /* first estimate */
+}
+
+
+static l_mem singlestep (lua_State *L) {
+ global_State *g = G(L);
+ /*lua_checkmemory(L);*/
+ switch (g->gcstate) {
+ case GCSpause: {
+ markroot(L); /* start a new collection */
+ return 0;
+ }
+ case GCSpropagate: {
+ if (g->gray)
+ return propagatemark(g);
+ else { /* no more `gray' objects */
+ atomic(L); /* finish mark phase */
+ return 0;
+ }
+ }
+ case GCSsweepstring: {
+ lu_mem old = g->totalbytes;
+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
+ g->gcstate = GCSsweep; /* end sweep-string phase */
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPCOST;
+ }
+ case GCSsweep: {
+ lu_mem old = g->totalbytes;
+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */
+ checkSizes(L);
+ g->gcstate = GCSfinalize; /* end sweep phase */
+ }
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPMAX*GCSWEEPCOST;
+ }
+ case GCSfinalize: {
+ if (g->tmudata) {
+ GCTM(L);
+ if (g->estimate > GCFINALIZECOST)
+ g->estimate -= GCFINALIZECOST;
+ return GCFINALIZECOST;
+ }
+ else {
+ g->gcstate = GCSpause; /* end collection */
+ g->gcdept = 0;
+ return 0;
+ }
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+void luaC_step (lua_State *L) {
+ global_State *g = G(L);
+ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+ if (lim == 0)
+ lim = (MAX_LUMEM-1)/2; /* no limit */
+ g->gcdept += g->totalbytes - g->GCthreshold;
+ do {
+ lim -= singlestep(L);
+ if (g->gcstate == GCSpause)
+ break;
+ } while (lim > 0);
+ if (g->gcstate != GCSpause) {
+ if (g->gcdept < GCSTEPSIZE)
+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/
+ else {
+ g->gcdept -= GCSTEPSIZE;
+ g->GCthreshold = g->totalbytes;
+ }
+ }
+ else {
+ lua_assert(g->totalbytes >= g->estimate);
+ setthreshold(g);
+ }
+}
+
+
+void luaC_fullgc (lua_State *L) {
+ global_State *g = G(L);
+ if (g->gcstate <= GCSpropagate) {
+ /* reset sweep marks to sweep all elements (returning them to white) */
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ /* reset other collector lists */
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->gcstate = GCSsweepstring;
+ }
+ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
+ /* finish any pending sweep phase */
+ while (g->gcstate != GCSfinalize) {
+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
+ singlestep(L);
+ }
+ markroot(L);
+ while (g->gcstate != GCSpause) {
+ singlestep(L);
+ }
+ setthreshold(g);
+}
+
+
+void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
+ global_State *g = G(L);
+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ lua_assert(ttype(&o->gch) != LUA_TTABLE);
+ /* must keep invariant? */
+ if (g->gcstate == GCSpropagate)
+ reallymarkobject(g, v); /* restore invariant */
+ else /* don't mind */
+ makewhite(g, o); /* mark as white just to avoid other barriers */
+}
+
+
+void luaC_barrierback (lua_State *L, Table *t) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(t);
+ lua_assert(isblack(o) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ black2gray(o); /* make table gray (again) */
+ t->gclist = g->grayagain;
+ g->grayagain = o;
+}
+
+
+void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
+ global_State *g = G(L);
+ o->gch.next = g->rootgc;
+ g->rootgc = o;
+ o->gch.marked = luaC_white(g);
+ o->gch.tt = tt;
+}
+
+
+void luaC_linkupval (lua_State *L, UpVal *uv) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(uv);
+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
+ g->rootgc = o;
+ if (isgray(o)) {
+ if (g->gcstate == GCSpropagate) {
+ gray2black(o); /* closed upvalues need barrier */
+ luaC_barrier(L, uv, uv->v);
+ }
+ else { /* sweep phase: sweep it (turning it into white) */
+ makewhite(g, o);
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ }
+ }
+}
+
diff --git a/debian/grub-extras/lua/lgc.h b/debian/grub-extras/lua/lgc.h
new file mode 100644
index 0000000..5a8dc60
--- /dev/null
+++ b/debian/grub-extras/lua/lgc.h
@@ -0,0 +1,110 @@
+/*
+** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lgc_h
+#define lgc_h
+
+
+#include "lobject.h"
+
+
+/*
+** Possible states of the Garbage Collector
+*/
+#define GCSpause 0
+#define GCSpropagate 1
+#define GCSsweepstring 2
+#define GCSsweep 3
+#define GCSfinalize 4
+
+
+/*
+** some userful bit tricks
+*/
+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
+#define setbits(x,m) ((x) |= (m))
+#define testbits(x,m) ((x) & (m))
+#define bitmask(b) (1<<(b))
+#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
+#define l_setbit(x,b) setbits(x, bitmask(b))
+#define resetbit(x,b) resetbits(x, bitmask(b))
+#define testbit(x,b) testbits(x, bitmask(b))
+#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
+#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
+#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
+
+
+
+/*
+** Layout for bit use in `marked' field:
+** bit 0 - object is white (type 0)
+** bit 1 - object is white (type 1)
+** bit 2 - object is black
+** bit 3 - for userdata: has been finalized
+** bit 3 - for tables: has weak keys
+** bit 4 - for tables: has weak values
+** bit 5 - object is fixed (should not be collected)
+** bit 6 - object is "super" fixed (only the main thread)
+*/
+
+
+#define WHITE0BIT 0
+#define WHITE1BIT 1
+#define BLACKBIT 2
+#define FINALIZEDBIT 3
+#define KEYWEAKBIT 3
+#define VALUEWEAKBIT 4
+#define FIXEDBIT 5
+#define SFIXEDBIT 6
+#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
+
+
+#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
+#define isgray(x) (!isblack(x) && !iswhite(x))
+
+#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
+#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS)
+
+#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
+#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
+
+#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
+
+#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
+
+
+#define luaC_checkGC(L) { \
+ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
+ if (G(L)->totalbytes >= G(L)->GCthreshold) \
+ luaC_step(L); }
+
+
+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
+
+#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \
+ luaC_barrierback(L,t); }
+
+#define luaC_objbarrier(L,p,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
+
+#define luaC_objbarriert(L,t,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
+
+LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
+LUAI_FUNC void luaC_callGCTM (lua_State *L);
+LUAI_FUNC void luaC_freeall (lua_State *L);
+LUAI_FUNC void luaC_step (lua_State *L);
+LUAI_FUNC void luaC_fullgc (lua_State *L);
+LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
+LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
+LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
+LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
+
+
+#endif
diff --git a/debian/grub-extras/lua/linit.c b/debian/grub-extras/lua/linit.c
new file mode 100644
index 0000000..f920a0b
--- /dev/null
+++ b/debian/grub-extras/lua/linit.c
@@ -0,0 +1,38 @@
+/*
+** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
+** Initialization of libraries for lua.c
+** See Copyright Notice in lua.h
+*/
+
+
+#define linit_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lualib.h"
+#include "lauxlib.h"
+
+
+static const luaL_Reg lualibs[] = {
+ {"", luaopen_base},
+// {LUA_LOADLIBNAME, luaopen_package},
+ {LUA_TABLIBNAME, luaopen_table},
+// {LUA_IOLIBNAME, luaopen_io},
+// {LUA_OSLIBNAME, luaopen_os},
+ {LUA_STRLIBNAME, luaopen_string},
+// {LUA_MATHLIBNAME, luaopen_math},
+// {LUA_DBLIBNAME, luaopen_debug},
+ {NULL, NULL}
+};
+
+
+LUALIB_API void luaL_openlibs (lua_State *L) {
+ const luaL_Reg *lib = lualibs;
+ for (; lib->func; lib++) {
+ lua_pushcfunction(L, lib->func);
+ lua_pushstring(L, lib->name);
+ lua_call(L, 1, 0);
+ }
+}
+
diff --git a/debian/grub-extras/lua/liolib.c b/debian/grub-extras/lua/liolib.c
new file mode 100644
index 0000000..e79ed1c
--- /dev/null
+++ b/debian/grub-extras/lua/liolib.c
@@ -0,0 +1,553 @@
+/*
+** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
+** Standard I/O (and system) library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define liolib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+
+#define IO_INPUT 1
+#define IO_OUTPUT 2
+
+
+static const char *const fnames[] = {"input", "output"};
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ if (filename)
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ else
+ lua_pushfstring(L, "%s", strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static void fileerror (lua_State *L, int arg, const char *filename) {
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ luaL_argerror(L, arg, lua_tostring(L, -1));
+}
+
+
+#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
+
+
+static int io_type (lua_State *L) {
+ void *ud;
+ luaL_checkany(L, 1);
+ ud = lua_touserdata(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+ if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
+ lua_pushnil(L); /* not a file */
+ else if (*((FILE **)ud) == NULL)
+ lua_pushliteral(L, "closed file");
+ else
+ lua_pushliteral(L, "file");
+ return 1;
+}
+
+
+static FILE *tofile (lua_State *L) {
+ FILE **f = tofilep(L);
+ if (*f == NULL)
+ luaL_error(L, "attempt to use a closed file");
+ return *f;
+}
+
+
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static FILE **newfile (lua_State *L) {
+ FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, LUA_FILEHANDLE);
+ lua_setmetatable(L, -2);
+ return pf;
+}
+
+
+/*
+** function to (not) close the standard files stdin, stdout, and stderr
+*/
+static int io_noclose (lua_State *L) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "cannot close standard file");
+ return 2;
+}
+
+
+/*
+** function to close 'popen' files
+*/
+static int io_pclose (lua_State *L) {
+ FILE **p = tofilep(L);
+ int ok = lua_pclose(L, *p);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+/*
+** function to close regular files
+*/
+static int io_fclose (lua_State *L) {
+ FILE **p = tofilep(L);
+ int ok = (fclose(*p) == 0);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+static int aux_close (lua_State *L) {
+ lua_getfenv(L, 1);
+ lua_getfield(L, -1, "__close");
+ return (lua_tocfunction(L, -1))(L);
+}
+
+
+static int io_close (lua_State *L) {
+ if (lua_isnone(L, 1))
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
+ tofile(L); /* make sure argument is a file */
+ return aux_close(L);
+}
+
+
+static int io_gc (lua_State *L) {
+ FILE *f = *tofilep(L);
+ /* ignore closed files */
+ if (f != NULL)
+ aux_close(L);
+ return 0;
+}
+
+
+static int io_tostring (lua_State *L) {
+ FILE *f = *tofilep(L);
+ if (f == NULL)
+ lua_pushliteral(L, "file (closed)");
+ else
+ lua_pushfstring(L, "file (%p)", f);
+ return 1;
+}
+
+
+static int io_open (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+/*
+** this function has a separated environment, which defines the
+** correct __close for 'popen' files
+*/
+static int io_popen (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = lua_popen(L, filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
+static int io_tmpfile (lua_State *L) {
+ FILE **pf = newfile(L);
+ *pf = tmpfile();
+ return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
+}
+
+
+static FILE *getiofile (lua_State *L, int findex) {
+ FILE *f;
+ lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
+ f = *(FILE **)lua_touserdata(L, -1);
+ if (f == NULL)
+ luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
+ return f;
+}
+
+
+static int g_iofile (lua_State *L, int f, const char *mode) {
+ if (!lua_isnoneornil(L, 1)) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename) {
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, mode);
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
+ }
+ else {
+ tofile(L); /* check that it's a valid file handle */
+ lua_pushvalue(L, 1);
+ }
+ lua_rawseti(L, LUA_ENVIRONINDEX, f);
+ }
+ /* return current value */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, f);
+ return 1;
+}
+
+
+static int io_input (lua_State *L) {
+ return g_iofile(L, IO_INPUT, "r");
+}
+
+
+static int io_output (lua_State *L) {
+ return g_iofile(L, IO_OUTPUT, "w");
+}
+
+
+static int io_readline (lua_State *L);
+
+
+static void aux_lines (lua_State *L, int idx, int toclose) {
+ lua_pushvalue(L, idx);
+ lua_pushboolean(L, toclose); /* close/not close file when finished */
+ lua_pushcclosure(L, io_readline, 2);
+}
+
+
+static int f_lines (lua_State *L) {
+ tofile(L); /* check that it's a valid file handle */
+ aux_lines(L, 1, 0);
+ return 1;
+}
+
+
+static int io_lines (lua_State *L) {
+ if (lua_isnoneornil(L, 1)) { /* no arguments? */
+ /* will iterate over default input */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
+ return f_lines(L);
+ }
+ else {
+ const char *filename = luaL_checkstring(L, 1);
+ FILE **pf = newfile(L);
+ *pf = fopen(filename, "r");
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
+ aux_lines(L, lua_gettop(L), 1);
+ return 1;
+ }
+}
+
+
+/*
+** {======================================================
+** READ
+** =======================================================
+*/
+
+
+static int read_number (lua_State *L, FILE *f) {
+ lua_Number d;
+ if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+ lua_pushnumber(L, d);
+ return 1;
+ }
+ else return 0; /* read fails */
+}
+
+
+static int test_eof (lua_State *L, FILE *f) {
+ int c = getc(f);
+ ungetc(c, f);
+ lua_pushlstring(L, NULL, 0);
+ return (c != EOF);
+}
+
+
+static int read_line (lua_State *L, FILE *f) {
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (;;) {
+ size_t l;
+ char *p = luaL_prepbuffer(&b);
+ if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
+ luaL_pushresult(&b); /* close buffer */
+ return (lua_objlen(L, -1) > 0); /* check whether read something */
+ }
+ l = strlen(p);
+ if (l == 0 || p[l-1] != '\n')
+ luaL_addsize(&b, l);
+ else {
+ luaL_addsize(&b, l - 1); /* do not include `eol' */
+ luaL_pushresult(&b); /* close buffer */
+ return 1; /* read at least an `eol' */
+ }
+ }
+}
+
+
+static int read_chars (lua_State *L, FILE *f, size_t n) {
+ size_t rlen; /* how much to read */
+ size_t nr; /* number of chars actually read */
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
+ do {
+ char *p = luaL_prepbuffer(&b);
+ if (rlen > n) rlen = n; /* cannot read more than asked */
+ nr = fread(p, sizeof(char), rlen, f);
+ luaL_addsize(&b, nr);
+ n -= nr; /* still have to read `n' chars */
+ } while (n > 0 && nr == rlen); /* until end of count or eof */
+ luaL_pushresult(&b); /* close buffer */
+ return (n == 0 || lua_objlen(L, -1) > 0);
+}
+
+
+static int g_read (lua_State *L, FILE *f, int first) {
+ int nargs = lua_gettop(L) - 1;
+ int success;
+ int n;
+ clearerr(f);
+ if (nargs == 0) { /* no arguments? */
+ success = read_line(L, f);
+ n = first+1; /* to return 1 result */
+ }
+ else { /* ensure stack space for all results and for auxlib's buffer */
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+ success = 1;
+ for (n = first; nargs-- && success; n++) {
+ if (lua_type(L, n) == LUA_TNUMBER) {
+ size_t l = (size_t)lua_tointeger(L, n);
+ success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+ }
+ else {
+ const char *p = lua_tostring(L, n);
+ luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+ switch (p[1]) {
+ case 'n': /* number */
+ success = read_number(L, f);
+ break;
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+ case 'a': /* file */
+ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
+ success = 1; /* always success */
+ break;
+ default:
+ return luaL_argerror(L, n, "invalid format");
+ }
+ }
+ }
+ }
+ if (ferror(f))
+ return pushresult(L, 0, NULL);
+ if (!success) {
+ lua_pop(L, 1); /* remove last result */
+ lua_pushnil(L); /* push nil instead */
+ }
+ return n - first;
+}
+
+
+static int io_read (lua_State *L) {
+ return g_read(L, getiofile(L, IO_INPUT), 1);
+}
+
+
+static int f_read (lua_State *L) {
+ return g_read(L, tofile(L), 2);
+}
+
+
+static int io_readline (lua_State *L) {
+ FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
+ int sucess;
+ if (f == NULL) /* file is already closed? */
+ luaL_error(L, "file is already closed");
+ sucess = read_line(L, f);
+ if (ferror(f))
+ return luaL_error(L, "%s", strerror(errno));
+ if (sucess) return 1;
+ else { /* EOF */
+ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
+ lua_settop(L, 0);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ aux_close(L); /* close it */
+ }
+ return 0;
+ }
+}
+
+/* }====================================================== */
+
+
+static int g_write (lua_State *L, FILE *f, int arg) {
+ int nargs = lua_gettop(L) - 1;
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+ /* optimization: could be done exactly as for strings */
+ status = status &&
+ fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ status = status && (fwrite(s, sizeof(char), l, f) == l);
+ }
+ }
+ return pushresult(L, status, NULL);
+}
+
+
+static int io_write (lua_State *L) {
+ return g_write(L, getiofile(L, IO_OUTPUT), 1);
+}
+
+
+static int f_write (lua_State *L) {
+ return g_write(L, tofile(L), 2);
+}
+
+
+static int f_seek (lua_State *L) {
+ static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+ static const char *const modenames[] = {"set", "cur", "end", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
+ long offset = luaL_optlong(L, 3, 0);
+ op = fseek(f, offset, mode[op]);
+ if (op)
+ return pushresult(L, 0, NULL); /* error */
+ else {
+ lua_pushinteger(L, ftell(f));
+ return 1;
+ }
+}
+
+
+static int f_setvbuf (lua_State *L) {
+ static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+ lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+}
+
+
+
+static int io_flush (lua_State *L) {
+ return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
+}
+
+
+static int f_flush (lua_State *L) {
+ return pushresult(L, fflush(tofile(L)) == 0, NULL);
+}
+
+
+static const luaL_Reg iolib[] = {
+ {"close", io_close},
+ {"flush", io_flush},
+ {"input", io_input},
+ {"lines", io_lines},
+ {"open", io_open},
+ {"output", io_output},
+ {"popen", io_popen},
+ {"read", io_read},
+ {"tmpfile", io_tmpfile},
+ {"type", io_type},
+ {"write", io_write},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg flib[] = {
+ {"close", io_close},
+ {"flush", f_flush},
+ {"lines", f_lines},
+ {"read", f_read},
+ {"seek", f_seek},
+ {"setvbuf", f_setvbuf},
+ {"write", f_write},
+ {"__gc", io_gc},
+ {"__tostring", io_tostring},
+ {NULL, NULL}
+};
+
+
+static void createmeta (lua_State *L) {
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, flib); /* file methods */
+}
+
+
+static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
+ *newfile(L) = f;
+ if (k > 0) {
+ lua_pushvalue(L, -1);
+ lua_rawseti(L, LUA_ENVIRONINDEX, k);
+ }
+ lua_pushvalue(L, -2); /* copy environment */
+ lua_setfenv(L, -2); /* set it */
+ lua_setfield(L, -3, fname);
+}
+
+
+static void newfenv (lua_State *L, lua_CFunction cls) {
+ lua_createtable(L, 0, 1);
+ lua_pushcfunction(L, cls);
+ lua_setfield(L, -2, "__close");
+}
+
+
+LUALIB_API int luaopen_io (lua_State *L) {
+ createmeta(L);
+ /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
+ newfenv(L, io_fclose);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* open library */
+ luaL_register(L, LUA_IOLIBNAME, iolib);
+ /* create (and set) default files */
+ newfenv(L, io_noclose); /* close function for default files */
+ createstdfile(L, stdin, IO_INPUT, "stdin");
+ createstdfile(L, stdout, IO_OUTPUT, "stdout");
+ createstdfile(L, stderr, 0, "stderr");
+ lua_pop(L, 1); /* pop environment for default files */
+ lua_getfield(L, -1, "popen");
+ newfenv(L, io_pclose); /* create environment for 'popen' */
+ lua_setfenv(L, -2); /* set fenv for 'popen' */
+ lua_pop(L, 1); /* pop 'popen' */
+ return 1;
+}
+
diff --git a/debian/grub-extras/lua/llex.c b/debian/grub-extras/lua/llex.c
new file mode 100644
index 0000000..cb08e89
--- /dev/null
+++ b/debian/grub-extras/lua/llex.c
@@ -0,0 +1,467 @@
+/*
+** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <ctype.h>
+#include <locale.h>
+#include <string.h>
+#endif
+
+#define llex_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "llex.h"
+#include "lobject.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "lzio.h"
+
+
+
+#define next(ls) (ls->current = zgetc(ls->z))
+
+
+
+
+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
+
+
+/* ORDER RESERVED */
+const char *const luaX_tokens [] = {
+ "and", "break", "do", "else", "elseif",
+ "end", "false", "for", "function", "if",
+ "in", "local", "nil", "not", "or", "repeat",
+ "return", "then", "true", "until", "while",
+ "..", "...", "==", ">=", "<=", "~=",
+ "<number>", "<name>", "<string>", "<eof>",
+ NULL
+};
+
+
+#define save_and_next(ls) (save(ls, ls->current), next(ls))
+
+
+static void save (LexState *ls, int c) {
+ Mbuffer *b = ls->buff;
+ if (b->n + 1 > b->buffsize) {
+ size_t newsize;
+ if (b->buffsize >= MAX_SIZET/2)
+ luaX_lexerror(ls, "lexical element too long", 0);
+ newsize = b->buffsize * 2;
+ luaZ_resizebuffer(ls->L, b, newsize);
+ }
+ b->buffer[b->n++] = cast(char, c);
+}
+
+
+void luaX_init (lua_State *L) {
+ int i;
+ for (i=0; i<NUM_RESERVED; i++) {
+ TString *ts = luaS_new(L, luaX_tokens[i]);
+ luaS_fix(ts); /* reserved words are never collected */
+ lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
+ ts->tsv.reserved = cast_byte(i+1); /* reserved word */
+ }
+}
+
+
+#define MAXSRC 80
+
+
+const char *luaX_token2str (LexState *ls, int token) {
+ if (token < FIRST_RESERVED) {
+ lua_assert(token == cast(unsigned char, token));
+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) :
+ luaO_pushfstring(ls->L, "%c", token);
+ }
+ else
+ return luaX_tokens[token-FIRST_RESERVED];
+}
+
+
+static const char *txtToken (LexState *ls, int token) {
+ switch (token) {
+ case TK_NAME:
+ case TK_STRING:
+ case TK_NUMBER:
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
+ default:
+ return luaX_token2str(ls, token);
+ }
+}
+
+
+void luaX_lexerror (LexState *ls, const char *msg, int token) {
+ char buff[MAXSRC];
+ luaO_chunkid(buff, getstr(ls->source), MAXSRC);
+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
+ if (token)
+ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token));
+ luaD_throw(ls->L, LUA_ERRSYNTAX);
+}
+
+
+void luaX_syntaxerror (LexState *ls, const char *msg) {
+ luaX_lexerror(ls, msg, ls->t.token);
+}
+
+
+TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
+ lua_State *L = ls->L;
+ TString *ts = luaS_newlstr(L, str, l);
+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
+ if (ttisnil(o))
+ setbvalue(o, 1); /* make sure `str' will not be collected */
+ return ts;
+}
+
+
+static void inclinenumber (LexState *ls) {
+ int old = ls->current;
+ lua_assert(currIsNewline(ls));
+ next(ls); /* skip `\n' or `\r' */
+ if (currIsNewline(ls) && ls->current != old)
+ next(ls); /* skip `\n\r' or `\r\n' */
+ if (++ls->linenumber >= MAX_INT)
+ luaX_syntaxerror(ls, "chunk has too many lines");
+}
+
+
+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
+ ls->decpoint = '.';
+ ls->L = L;
+ ls->lookahead.token = TK_EOS; /* no look-ahead token */
+ ls->z = z;
+ ls->fs = NULL;
+ ls->linenumber = 1;
+ ls->lastline = 1;
+ ls->source = source;
+ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
+ next(ls); /* read first char */
+}
+
+
+
+/*
+** =======================================================
+** LEXICAL ANALYZER
+** =======================================================
+*/
+
+
+
+static int check_next (LexState *ls, const char *set) {
+ if (!strchr(set, ls->current))
+ return 0;
+ save_and_next(ls);
+ return 1;
+}
+
+
+static void buffreplace (LexState *ls, char from, char to) {
+ size_t n = luaZ_bufflen(ls->buff);
+ char *p = luaZ_buffer(ls->buff);
+ while (n--)
+ if (p[n] == from) p[n] = to;
+}
+
+
+static void trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+#if 0
+ struct lconv *cv = localeconv();
+ char old = ls->decpoint;
+ ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+#else
+ char old = ls->decpoint;
+ ls->decpoint = '.';
+#endif
+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
+ /* format error with correct decimal point: no more options */
+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
+ }
+}
+
+
+/* LUA_NUMBER */
+static void read_numeral (LexState *ls, SemInfo *seminfo) {
+ lua_assert(isdigit(ls->current));
+ do {
+ save_and_next(ls);
+ } while (isdigit(ls->current) || ls->current == '.');
+ if (check_next(ls, "Ee")) /* `E'? */
+ check_next(ls, "+-"); /* optional exponent sign */
+ while (isalnum(ls->current) || ls->current == '_')
+ save_and_next(ls);
+ save(ls, '\0');
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
+ trydecpoint(ls, seminfo); /* try to update decimal point separator */
+}
+
+
+static int skip_sep (LexState *ls) {
+ int count = 0;
+ int s = ls->current;
+ lua_assert(s == '[' || s == ']');
+ save_and_next(ls);
+ while (ls->current == '=') {
+ save_and_next(ls);
+ count++;
+ }
+ return (ls->current == s) ? count : (-count) - 1;
+}
+
+
+static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
+ int cont = 0;
+ (void)(cont); /* avoid warnings when `cont' is not used */
+ save_and_next(ls); /* skip 2nd `[' */
+ if (currIsNewline(ls)) /* string starts with a newline? */
+ inclinenumber(ls); /* skip it */
+ for (;;) {
+ switch (ls->current) {
+ case EOZ:
+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
+ "unfinished long comment", TK_EOS);
+ break; /* to avoid warnings */
+#if defined(LUA_COMPAT_LSTR)
+ case '[': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `[' */
+ cont++;
+#if LUA_COMPAT_LSTR == 1
+ if (sep == 0)
+ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
+#endif
+ }
+ break;
+ }
+#endif
+ case ']': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `]' */
+#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
+ cont--;
+ if (sep == 0 && cont >= 0) break;
+#endif
+ goto endloop;
+ }
+ break;
+ }
+ case '\n':
+ case '\r': {
+ save(ls, '\n');
+ inclinenumber(ls);
+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
+ break;
+ }
+ default: {
+ if (seminfo) save_and_next(ls);
+ else next(ls);
+ }
+ }
+ } endloop:
+ if (seminfo)
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
+ luaZ_bufflen(ls->buff) - 2*(2 + sep));
+}
+
+
+static void read_string (LexState *ls, int del, SemInfo *seminfo) {
+ save_and_next(ls);
+ while (ls->current != del) {
+ switch (ls->current) {
+ case EOZ:
+ luaX_lexerror(ls, "unfinished string", TK_EOS);
+ continue; /* to avoid warnings */
+ case '\n':
+ case '\r':
+ luaX_lexerror(ls, "unfinished string", TK_STRING);
+ continue; /* to avoid warnings */
+ case '\\': {
+ int c;
+ next(ls); /* do not save the `\' */
+ switch (ls->current) {
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\n': /* go through */
+ case '\r': save(ls, '\n'); inclinenumber(ls); continue;
+ case EOZ: continue; /* will raise an error next loop */
+ default: {
+ if (!isdigit(ls->current))
+ save_and_next(ls); /* handles \\, \", \', and \? */
+ else { /* \xxx */
+ int i = 0;
+ c = 0;
+ do {
+ c = 10*c + (ls->current-'0');
+ next(ls);
+ } while (++i<3 && isdigit(ls->current));
+ if (c > UCHAR_MAX)
+ luaX_lexerror(ls, "escape sequence too large", TK_STRING);
+ save(ls, c);
+ }
+ continue;
+ }
+ }
+ save(ls, c);
+ next(ls);
+ continue;
+ }
+ default:
+ save_and_next(ls);
+ }
+ }
+ save_and_next(ls); /* skip delimiter */
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
+ luaZ_bufflen(ls->buff) - 2);
+}
+
+
+static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
+ for (;;) {
+ switch (ls->current) {
+ case '\n':
+ case '\r': {
+ inclinenumber(ls);
+ continue;
+ }
+ case '-': {
+ next(ls);
+ if (ls->current != '-') return '-';
+ /* else is a comment */
+ next(ls);
+ if (ls->current == '[') {
+ int sep = skip_sep(ls);
+ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */
+ if (sep >= 0) {
+ read_long_string(ls, NULL, sep); /* long comment */
+ luaZ_resetbuffer(ls->buff);
+ continue;
+ }
+ }
+ /* else short comment */
+ while (!currIsNewline(ls) && ls->current != EOZ)
+ next(ls);
+ continue;
+ }
+ case '[': {
+ int sep = skip_sep(ls);
+ if (sep >= 0) {
+ read_long_string(ls, seminfo, sep);
+ return TK_STRING;
+ }
+ else if (sep == -1) return '[';
+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
+ }
+ case '=': {
+ next(ls);
+ if (ls->current != '=') return '=';
+ else { next(ls); return TK_EQ; }
+ }
+ case '<': {
+ next(ls);
+ if (ls->current != '=') return '<';
+ else { next(ls); return TK_LE; }
+ }
+ case '>': {
+ next(ls);
+ if (ls->current != '=') return '>';
+ else { next(ls); return TK_GE; }
+ }
+ case '~': {
+ next(ls);
+ if (ls->current != '=') return '~';
+ else { next(ls); return TK_NE; }
+ }
+ case '"':
+ case '\'': {
+ read_string(ls, ls->current, seminfo);
+ return TK_STRING;
+ }
+ case '.': {
+ save_and_next(ls);
+ if (check_next(ls, ".")) {
+ if (check_next(ls, "."))
+ return TK_DOTS; /* ... */
+ else return TK_CONCAT; /* .. */
+ }
+ else if (!isdigit(ls->current)) return '.';
+ else {
+ read_numeral(ls, seminfo);
+ return TK_NUMBER;
+ }
+ }
+ case EOZ: {
+ return TK_EOS;
+ }
+ default: {
+ if (isspace(ls->current)) {
+ lua_assert(!currIsNewline(ls));
+ next(ls);
+ continue;
+ }
+ else if (isdigit(ls->current)) {
+ read_numeral(ls, seminfo);
+ return TK_NUMBER;
+ }
+ else if (isalpha(ls->current) || ls->current == '_') {
+ /* identifier or reserved word */
+ TString *ts;
+ do {
+ save_and_next(ls);
+ } while (isalnum(ls->current) || ls->current == '_');
+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
+ luaZ_bufflen(ls->buff));
+ if (ts->tsv.reserved > 0) /* reserved word? */
+ return ts->tsv.reserved - 1 + FIRST_RESERVED;
+ else {
+ seminfo->ts = ts;
+ return TK_NAME;
+ }
+ }
+ else {
+ int c = ls->current;
+ next(ls);
+ return c; /* single-char tokens (+ - / ...) */
+ }
+ }
+ }
+ }
+}
+
+
+void luaX_next (LexState *ls) {
+ ls->lastline = ls->linenumber;
+ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
+ ls->t = ls->lookahead; /* use this one */
+ ls->lookahead.token = TK_EOS; /* and discharge it */
+ }
+ else
+ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
+}
+
+
+void luaX_lookahead (LexState *ls) {
+ lua_assert(ls->lookahead.token == TK_EOS);
+ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
+}
+
diff --git a/debian/grub-extras/lua/llex.h b/debian/grub-extras/lua/llex.h
new file mode 100644
index 0000000..a9201ce
--- /dev/null
+++ b/debian/grub-extras/lua/llex.h
@@ -0,0 +1,81 @@
+/*
+** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lexical Analyzer
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llex_h
+#define llex_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+
+#define FIRST_RESERVED 257
+
+/* maximum length of a reserved word */
+#define TOKEN_LEN (sizeof("function")/sizeof(char))
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER RESERVED"
+*/
+enum RESERVED {
+ /* terminal symbols denoted by reserved words */
+ TK_AND = FIRST_RESERVED, TK_BREAK,
+ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
+ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+ /* other terminal symbols */
+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+ TK_NAME, TK_STRING, TK_EOS
+};
+
+/* number of reserved words */
+#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
+
+
+/* array with token `names' */
+LUAI_DATA const char *const luaX_tokens [];
+
+
+typedef union {
+ lua_Number r;
+ TString *ts;
+} SemInfo; /* semantics information */
+
+
+typedef struct Token {
+ int token;
+ SemInfo seminfo;
+} Token;
+
+
+typedef struct LexState {
+ int current; /* current character (charint) */
+ int linenumber; /* input line counter */
+ int lastline; /* line of last token `consumed' */
+ Token t; /* current token */
+ Token lookahead; /* look ahead token */
+ struct FuncState *fs; /* `FuncState' is private to the parser */
+ struct lua_State *L;
+ ZIO *z; /* input stream */
+ Mbuffer *buff; /* buffer for tokens */
+ TString *source; /* current source name */
+ char decpoint; /* locale decimal point */
+} LexState;
+
+
+LUAI_FUNC void luaX_init (lua_State *L);
+LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
+ TString *source);
+LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
+LUAI_FUNC void luaX_next (LexState *ls);
+LUAI_FUNC void luaX_lookahead (LexState *ls);
+LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);
+LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);
+LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
+
+
+#endif
diff --git a/debian/grub-extras/lua/llimits.h b/debian/grub-extras/lua/llimits.h
new file mode 100644
index 0000000..5612e8a
--- /dev/null
+++ b/debian/grub-extras/lua/llimits.h
@@ -0,0 +1,128 @@
+/*
+** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $
+** Limits, basic types, and some other `installation-dependent' definitions
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llimits_h
+#define llimits_h
+
+#if 0
+#include <limits.h>
+#include <stddef.h>
+#endif
+
+#include "lua.h"
+
+
+typedef LUAI_UINT32 lu_int32;
+
+typedef LUAI_UMEM lu_mem;
+
+typedef LUAI_MEM l_mem;
+
+
+
+/* chars used as small naturals (so that `char' is reserved for characters) */
+typedef unsigned char lu_byte;
+
+
+#define MAX_SIZET ((size_t)(~(size_t)0)-2)
+
+#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2)
+
+
+#define MAX_INT (int)(INT_MAX-2) /* maximum value of an int (-2 for safety) */
+
+/*
+** conversion of pointer to integer
+** this is for hashing only; there is no problem if the integer
+** cannot hold the whole pointer value
+*/
+#define IntPoint(p) ((unsigned int)(lu_mem)(p))
+
+
+
+/* type to ensure maximum alignment */
+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
+
+
+/* result of a `usual argument conversion' over lua_Number */
+typedef LUAI_UACNUMBER l_uacNumber;
+
+
+/* internal assertions for in-house debugging */
+#ifdef lua_assert
+
+#define check_exp(c,e) (lua_assert(c), (e))
+#define api_check(l,e) lua_assert(e)
+
+#else
+
+#define lua_assert(c) ((void)0)
+#define check_exp(c,e) (e)
+#define api_check luai_apicheck
+
+#endif
+
+
+#ifndef UNUSED
+#define UNUSED(x) ((void)(x)) /* to avoid warnings */
+#endif
+
+
+#ifndef cast
+#define cast(t, exp) ((t)(exp))
+#endif
+
+#define cast_byte(i) cast(lu_byte, (i))
+#define cast_num(i) cast(lua_Number, (i))
+#define cast_int(i) cast(int, (i))
+
+
+
+/*
+** type for virtual-machine instructions
+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+*/
+typedef lu_int32 Instruction;
+
+
+
+/* maximum stack for a Lua function */
+#define MAXSTACK 250
+
+
+
+/* minimum size for the string table (must be power of 2) */
+#ifndef MINSTRTABSIZE
+#define MINSTRTABSIZE 32
+#endif
+
+
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER 32
+#endif
+
+
+#ifndef lua_lock
+#define lua_lock(L) ((void) 0)
+#define lua_unlock(L) ((void) 0)
+#endif
+
+#ifndef luai_threadyield
+#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
+#endif
+
+
+/*
+** macro to control inclusion of some hard tests on stack reallocation
+*/
+#ifndef HARDSTACKTESTS
+#define condhardstacktests(x) ((void)0)
+#else
+#define condhardstacktests(x) x
+#endif
+
+#endif
diff --git a/debian/grub-extras/lua/lmathlib.c b/debian/grub-extras/lua/lmathlib.c
new file mode 100644
index 0000000..441fbf7
--- /dev/null
+++ b/debian/grub-extras/lua/lmathlib.c
@@ -0,0 +1,263 @@
+/*
+** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $
+** Standard mathematical library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stdlib.h>
+#include <math.h>
+
+#define lmathlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#undef PI
+#define PI (3.14159265358979323846)
+#define RADIANS_PER_DEGREE (PI/180.0)
+
+
+
+static int math_abs (lua_State *L) {
+ lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sin (lua_State *L) {
+ lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sinh (lua_State *L) {
+ lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cos (lua_State *L) {
+ lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cosh (lua_State *L) {
+ lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tan (lua_State *L) {
+ lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tanh (lua_State *L) {
+ lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_asin (lua_State *L) {
+ lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_acos (lua_State *L) {
+ lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_atan (lua_State *L) {
+ lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_atan2 (lua_State *L) {
+ lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_ceil (lua_State *L) {
+ lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_floor (lua_State *L) {
+ lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_fmod (lua_State *L) {
+ lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_modf (lua_State *L) {
+ double ip;
+ double fp = modf(luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+}
+
+static int math_sqrt (lua_State *L) {
+ lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_pow (lua_State *L) {
+ lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+}
+
+static int math_log (lua_State *L) {
+ lua_pushnumber(L, log(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_log10 (lua_State *L) {
+ lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_exp (lua_State *L) {
+ lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_deg (lua_State *L) {
+ lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
+ return 1;
+}
+
+static int math_rad (lua_State *L) {
+ lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
+ return 1;
+}
+
+static int math_frexp (lua_State *L) {
+ int e;
+ lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+}
+
+static int math_ldexp (lua_State *L) {
+ lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ return 1;
+}
+
+
+
+static int math_min (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmin = luaL_checknumber(L, 1);
+ int i;
+ for (i=2; i<=n; i++) {
+ lua_Number d = luaL_checknumber(L, i);
+ if (d < dmin)
+ dmin = d;
+ }
+ lua_pushnumber(L, dmin);
+ return 1;
+}
+
+
+static int math_max (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmax = luaL_checknumber(L, 1);
+ int i;
+ for (i=2; i<=n; i++) {
+ lua_Number d = luaL_checknumber(L, i);
+ if (d > dmax)
+ dmax = d;
+ }
+ lua_pushnumber(L, dmax);
+ return 1;
+}
+
+
+static int math_random (lua_State *L) {
+ /* the `%' avoids the (rare) case of r==1, and is needed also because on
+ some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+ switch (lua_gettop(L)) { /* check number of arguments */
+ case 0: { /* no arguments */
+ lua_pushnumber(L, r); /* Number between 0 and 1 */
+ break;
+ }
+ case 1: { /* only upper limit */
+ int u = luaL_checkint(L, 1);
+ luaL_argcheck(L, 1<=u, 1, "interval is empty");
+ lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
+ break;
+ }
+ case 2: { /* lower and upper limits */
+ int l = luaL_checkint(L, 1);
+ int u = luaL_checkint(L, 2);
+ luaL_argcheck(L, l<=u, 2, "interval is empty");
+ lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
+ break;
+ }
+ default: return luaL_error(L, "wrong number of arguments");
+ }
+ return 1;
+}
+
+
+static int math_randomseed (lua_State *L) {
+ srand(luaL_checkint(L, 1));
+ return 0;
+}
+
+
+static const luaL_Reg mathlib[] = {
+ {"abs", math_abs},
+ {"acos", math_acos},
+ {"asin", math_asin},
+ {"atan2", math_atan2},
+ {"atan", math_atan},
+ {"ceil", math_ceil},
+ {"cosh", math_cosh},
+ {"cos", math_cos},
+ {"deg", math_deg},
+ {"exp", math_exp},
+ {"floor", math_floor},
+ {"fmod", math_fmod},
+ {"frexp", math_frexp},
+ {"ldexp", math_ldexp},
+ {"log10", math_log10},
+ {"log", math_log},
+ {"max", math_max},
+ {"min", math_min},
+ {"modf", math_modf},
+ {"pow", math_pow},
+ {"rad", math_rad},
+ {"random", math_random},
+ {"randomseed", math_randomseed},
+ {"sinh", math_sinh},
+ {"sin", math_sin},
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
+ {NULL, NULL}
+};
+
+
+/*
+** Open math library
+*/
+LUALIB_API int luaopen_math (lua_State *L) {
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
+ lua_pushnumber(L, PI);
+ lua_setfield(L, -2, "pi");
+ lua_pushnumber(L, HUGE_VAL);
+ lua_setfield(L, -2, "huge");
+#if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+#endif
+ return 1;
+}
+
diff --git a/debian/grub-extras/lua/lmem.c b/debian/grub-extras/lua/lmem.c
new file mode 100644
index 0000000..ae7d8c9
--- /dev/null
+++ b/debian/grub-extras/lua/lmem.c
@@ -0,0 +1,86 @@
+/*
+** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lmem_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+
+/*
+** About the realloc function:
+** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
+** (`osize' is the old size, `nsize' is the new size)
+**
+** Lua ensures that (ptr == NULL) iff (osize == 0).
+**
+** * frealloc(ud, NULL, 0, x) creates a new block of size `x'
+**
+** * frealloc(ud, p, x, 0) frees the block `p'
+** (in this specific case, frealloc must return NULL).
+** particularly, frealloc(ud, NULL, 0, 0) does nothing
+** (which is equivalent to free(NULL) in ANSI C)
+**
+** frealloc returns NULL if it cannot create or reallocate the area
+** (any reallocation to an equal or smaller size cannot fail!)
+*/
+
+
+
+#define MINSIZEARRAY 4
+
+
+void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
+ int limit, const char *errormsg) {
+ void *newblock;
+ int newsize;
+ if (*size >= limit/2) { /* cannot double it? */
+ if (*size >= limit) /* cannot grow even a little? */
+ luaG_runerror(L, errormsg);
+ newsize = limit; /* still have at least one free place */
+ }
+ else {
+ newsize = (*size)*2;
+ if (newsize < MINSIZEARRAY)
+ newsize = MINSIZEARRAY; /* minimum size */
+ }
+ newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
+ *size = newsize; /* update only when everything else is OK */
+ return newblock;
+}
+
+
+void *luaM_toobig (lua_State *L) {
+ luaG_runerror(L, "memory allocation error: block too big");
+ return NULL; /* to avoid warnings */
+}
+
+
+
+/*
+** generic allocation routine.
+*/
+void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
+ global_State *g = G(L);
+ lua_assert((osize == 0) == (block == NULL));
+ block = (*g->frealloc)(g->ud, block, osize, nsize);
+ if (block == NULL && nsize > 0)
+ luaD_throw(L, LUA_ERRMEM);
+ lua_assert((nsize == 0) == (block == NULL));
+ g->totalbytes = (g->totalbytes - osize) + nsize;
+ return block;
+}
+
diff --git a/debian/grub-extras/lua/lmem.h b/debian/grub-extras/lua/lmem.h
new file mode 100644
index 0000000..d33084d
--- /dev/null
+++ b/debian/grub-extras/lua/lmem.h
@@ -0,0 +1,50 @@
+/*
+** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
+** Interface to Memory Manager
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lmem_h
+#define lmem_h
+
+#if 0
+#include <stddef.h>
+#endif
+
+#include "llimits.h"
+#include "lua.h"
+
+#define MEMERRMSG "not enough memory"
+
+
+#define luaM_reallocv(L,b,on,n,e) \
+ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \
+ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \
+ luaM_toobig(L))
+
+#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
+#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)
+#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t))
+
+#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t))
+#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t)))
+#define luaM_newvector(L,n,t) \
+ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))
+
+#define luaM_growvector(L,v,nelems,size,t,limit,e) \
+ if ((nelems)+1 > (size)) \
+ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))
+
+#define luaM_reallocvector(L, v,oldn,n,t) \
+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+
+
+LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+ size_t size);
+LUAI_FUNC void *luaM_toobig (lua_State *L);
+LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
+ size_t size_elem, int limit,
+ const char *errormsg);
+
+#endif
+
diff --git a/debian/grub-extras/lua/loadlib.c b/debian/grub-extras/lua/loadlib.c
new file mode 100644
index 0000000..25e07d1
--- /dev/null
+++ b/debian/grub-extras/lua/loadlib.c
@@ -0,0 +1,665 @@
+/*
+** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $
+** Dynamic library loader for Lua
+** See Copyright Notice in lua.h
+**
+** This module contains an implementation of loadlib for Unix systems
+** that have dlfcn, an implementation for Darwin (Mac OS X), an
+** implementation for Windows, and a stub for other systems.
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#define loadlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* prefix for open functions in C libraries */
+#define LUA_POF "luaopen_"
+
+/* separator for open functions in C libraries */
+#define LUA_OFSEP "_"
+
+
+#define LIBPREFIX "LOADLIB: "
+
+#define POF LUA_POF
+#define LIB_FAIL "open"
+
+
+/* error codes for ll_loadfunc */
+#define ERRLIB 1
+#define ERRFUNC 2
+
+#define setprogdir(L) ((void)0)
+
+
+static void ll_unloadlib (void *lib);
+static void *ll_load (lua_State *L, const char *path);
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
+
+
+
+#if defined(LUA_DL_DLOPEN)
+/*
+** {========================================================================
+** This is an implementation of loadlib based on the dlfcn interface.
+** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
+** as an emulation layer on top of native functions.
+** =========================================================================
+*/
+
+#include <dlfcn.h>
+
+static void ll_unloadlib (void *lib) {
+ dlclose(lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ void *lib = dlopen(path, RTLD_NOW);
+ if (lib == NULL) lua_pushstring(L, dlerror());
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
+ if (f == NULL) lua_pushstring(L, dlerror());
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DLL)
+/*
+** {======================================================================
+** This is an implementation of loadlib for Windows using native functions.
+** =======================================================================
+*/
+
+#include <windows.h>
+
+
+#undef setprogdir
+
+static void setprogdir (lua_State *L) {
+ char buff[MAX_PATH + 1];
+ char *lb;
+ DWORD nsize = sizeof(buff)/sizeof(char);
+ DWORD n = GetModuleFileNameA(NULL, buff, nsize);
+ if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
+ luaL_error(L, "unable to get ModuleFileName");
+ else {
+ *lb = '\0';
+ luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
+ lua_remove(L, -2); /* remove original string */
+ }
+}
+
+
+static void pusherror (lua_State *L) {
+ int error = GetLastError();
+ char buffer[128];
+ if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error, 0, buffer, sizeof(buffer), NULL))
+ lua_pushstring(L, buffer);
+ else
+ lua_pushfstring(L, "system error %d\n", error);
+}
+
+static void ll_unloadlib (void *lib) {
+ FreeLibrary((HINSTANCE)lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ HINSTANCE lib = LoadLibraryA(path);
+ if (lib == NULL) pusherror(L);
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
+ if (f == NULL) pusherror(L);
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DYLD)
+/*
+** {======================================================================
+** Native Mac OS X / Darwin Implementation
+** =======================================================================
+*/
+
+#include <mach-o/dyld.h>
+
+
+/* Mac appends a `_' before C function names */
+#undef POF
+#define POF "_" LUA_POF
+
+
+static void pusherror (lua_State *L) {
+ const char *err_str;
+ const char *err_file;
+ NSLinkEditErrors err;
+ int err_num;
+ NSLinkEditError(&err, &err_num, &err_file, &err_str);
+ lua_pushstring(L, err_str);
+}
+
+
+static const char *errorfromcode (NSObjectFileImageReturnCode ret) {
+ switch (ret) {
+ case NSObjectFileImageInappropriateFile:
+ return "file is not a bundle";
+ case NSObjectFileImageArch:
+ return "library is for wrong CPU type";
+ case NSObjectFileImageFormat:
+ return "bad format";
+ case NSObjectFileImageAccess:
+ return "cannot access file";
+ case NSObjectFileImageFailure:
+ default:
+ return "unable to load library";
+ }
+}
+
+
+static void ll_unloadlib (void *lib) {
+ NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ NSObjectFileImage img;
+ NSObjectFileImageReturnCode ret;
+ /* this would be a rare case, but prevents crashing if it happens */
+ if(!_dyld_present()) {
+ lua_pushliteral(L, "dyld not present");
+ return NULL;
+ }
+ ret = NSCreateObjectFileImageFromFile(path, &img);
+ if (ret == NSObjectFileImageSuccess) {
+ NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ NSDestroyObjectFileImage(img);
+ if (mod == NULL) pusherror(L);
+ return mod;
+ }
+ lua_pushstring(L, errorfromcode(ret));
+ return NULL;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);
+ if (nss == NULL) {
+ lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
+ return NULL;
+ }
+ return (lua_CFunction)NSAddressOfSymbol(nss);
+}
+
+/* }====================================================== */
+
+
+
+#else
+/*
+** {======================================================
+** Fallback for other systems
+** =======================================================
+*/
+
+#undef LIB_FAIL
+#define LIB_FAIL "absent"
+
+
+#define DLMSG "dynamic libraries not enabled; check your Lua installation"
+
+
+static void ll_unloadlib (void *lib) {
+ (void)lib; /* to avoid warnings */
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ (void)path; /* to avoid warnings */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ (void)lib; (void)sym; /* to avoid warnings */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+/* }====================================================== */
+#endif
+
+
+
+static void **ll_register (lua_State *L, const char *path) {
+ void **plib;
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
+ if (!lua_isnil(L, -1)) /* is there an entry? */
+ plib = (void **)lua_touserdata(L, -1);
+ else { /* no entry yet; create one */
+ lua_pop(L, 1);
+ plib = (void **)lua_newuserdata(L, sizeof(const void *));
+ *plib = NULL;
+ luaL_getmetatable(L, "_LOADLIB");
+ lua_setmetatable(L, -2);
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_pushvalue(L, -2);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ }
+ return plib;
+}
+
+
+/*
+** __gc tag method: calls library's `ll_unloadlib' function with the lib
+** handle
+*/
+static int gctm (lua_State *L) {
+ void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
+ if (*lib) ll_unloadlib(*lib);
+ *lib = NULL; /* mark library as closed */
+ return 0;
+}
+
+
+static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
+ void **reg = ll_register(L, path);
+ if (*reg == NULL) *reg = ll_load(L, path);
+ if (*reg == NULL)
+ return ERRLIB; /* unable to load library */
+ else {
+ lua_CFunction f = ll_sym(L, *reg, sym);
+ if (f == NULL)
+ return ERRFUNC; /* unable to find function */
+ lua_pushcfunction(L, f);
+ return 0; /* return function */
+ }
+}
+
+
+static int ll_loadlib (lua_State *L) {
+ const char *path = luaL_checkstring(L, 1);
+ const char *init = luaL_checkstring(L, 2);
+ int stat = ll_loadfunc(L, path, init);
+ if (stat == 0) /* no errors? */
+ return 1; /* return the loaded function */
+ else { /* error; error message is on stack top */
+ lua_pushnil(L);
+ lua_insert(L, -2);
+ lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
+ return 3; /* return nil, error message, and where */
+ }
+}
+
+
+
+/*
+** {======================================================
+** 'require' function
+** =======================================================
+*/
+
+
+static int readable (const char *filename) {
+ FILE *f = fopen(filename, "r"); /* try to open file */
+ if (f == NULL) return 0; /* open failed */
+ fclose(f);
+ return 1;
+}
+
+
+static const char *pushnexttemplate (lua_State *L, const char *path) {
+ const char *l;
+ while (*path == *LUA_PATHSEP) path++; /* skip separators */
+ if (*path == '\0') return NULL; /* no more templates */
+ l = strchr(path, *LUA_PATHSEP); /* find next separator */
+ if (l == NULL) l = path + strlen(path);
+ lua_pushlstring(L, path, l - path); /* template */
+ return l;
+}
+
+
+static const char *findfile (lua_State *L, const char *name,
+ const char *pname) {
+ const char *path;
+ name = luaL_gsub(L, name, ".", LUA_DIRSEP);
+ lua_getfield(L, LUA_ENVIRONINDEX, pname);
+ path = lua_tostring(L, -1);
+ if (path == NULL)
+ luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
+ lua_pushliteral(L, ""); /* error accumulator */
+ while ((path = pushnexttemplate(L, path)) != NULL) {
+ const char *filename;
+ filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
+ lua_remove(L, -2); /* remove path template */
+ if (readable(filename)) /* does file exist and is readable? */
+ return filename; /* return that file name */
+ lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
+ lua_remove(L, -2); /* remove file name */
+ lua_concat(L, 2); /* add entry to possible error message */
+ }
+ return NULL; /* not found */
+}
+
+
+static void loaderror (lua_State *L, const char *filename) {
+ luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
+ lua_tostring(L, 1), filename, lua_tostring(L, -1));
+}
+
+
+static int loader_Lua (lua_State *L) {
+ const char *filename;
+ const char *name = luaL_checkstring(L, 1);
+ filename = findfile(L, name, "path");
+ if (filename == NULL) return 1; /* library not found in this path */
+ if (luaL_loadfile(L, filename) != 0)
+ loaderror(L, filename);
+ return 1; /* library loaded successfully */
+}
+
+
+static const char *mkfuncname (lua_State *L, const char *modname) {
+ const char *funcname;
+ const char *mark = strchr(modname, *LUA_IGMARK);
+ if (mark) modname = mark + 1;
+ funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
+ funcname = lua_pushfstring(L, POF"%s", funcname);
+ lua_remove(L, -2); /* remove 'gsub' result */
+ return funcname;
+}
+
+
+static int loader_C (lua_State *L) {
+ const char *funcname;
+ const char *name = luaL_checkstring(L, 1);
+ const char *filename = findfile(L, name, "cpath");
+ if (filename == NULL) return 1; /* library not found in this path */
+ funcname = mkfuncname(L, name);
+ if (ll_loadfunc(L, filename, funcname) != 0)
+ loaderror(L, filename);
+ return 1; /* library loaded successfully */
+}
+
+
+static int loader_Croot (lua_State *L) {
+ const char *funcname;
+ const char *filename;
+ const char *name = luaL_checkstring(L, 1);
+ const char *p = strchr(name, '.');
+ int stat;
+ if (p == NULL) return 0; /* is root */
+ lua_pushlstring(L, name, p - name);
+ filename = findfile(L, lua_tostring(L, -1), "cpath");
+ if (filename == NULL) return 1; /* root not found */
+ funcname = mkfuncname(L, name);
+ if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
+ if (stat != ERRFUNC) loaderror(L, filename); /* real error */
+ lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
+ name, filename);
+ return 1; /* function not found */
+ }
+ return 1;
+}
+
+
+static int loader_preload (lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ lua_getfield(L, LUA_ENVIRONINDEX, "preload");
+ if (!lua_istable(L, -1))
+ luaL_error(L, LUA_QL("package.preload") " must be a table");
+ lua_getfield(L, -1, name);
+ if (lua_isnil(L, -1)) /* not found? */
+ lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
+ return 1;
+}
+
+
+static const int sentinel_ = 0;
+#define sentinel ((void *)&sentinel_)
+
+
+static int ll_require (lua_State *L) {
+ const char *name = luaL_checkstring(L, 1);
+ int i;
+ lua_settop(L, 1); /* _LOADED table will be at index 2 */
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, 2, name);
+ if (lua_toboolean(L, -1)) { /* is it there? */
+ if (lua_touserdata(L, -1) == sentinel) /* check loops */
+ luaL_error(L, "loop or previous error loading module " LUA_QS, name);
+ return 1; /* package is already loaded */
+ }
+ /* else must load it; iterate over available loaders */
+ lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
+ if (!lua_istable(L, -1))
+ luaL_error(L, LUA_QL("package.loaders") " must be a table");
+ lua_pushliteral(L, ""); /* error message accumulator */
+ for (i=1; ; i++) {
+ lua_rawgeti(L, -2, i); /* get a loader */
+ if (lua_isnil(L, -1))
+ luaL_error(L, "module " LUA_QS " not found:%s",
+ name, lua_tostring(L, -2));
+ lua_pushstring(L, name);
+ lua_call(L, 1, 1); /* call it */
+ if (lua_isfunction(L, -1)) /* did it find module? */
+ break; /* module loaded successfully */
+ else if (lua_isstring(L, -1)) /* loader returned error message? */
+ lua_concat(L, 2); /* accumulate it */
+ else
+ lua_pop(L, 1);
+ }
+ lua_pushlightuserdata(L, sentinel);
+ lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
+ lua_pushstring(L, name); /* pass name as argument to module */
+ lua_call(L, 1, 1); /* run loaded module */
+ if (!lua_isnil(L, -1)) /* non-nil return? */
+ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
+ lua_getfield(L, 2, name);
+ if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */
+ lua_pushboolean(L, 1); /* use true as result */
+ lua_pushvalue(L, -1); /* extra copy to be returned */
+ lua_setfield(L, 2, name); /* _LOADED[name] = true */
+ }
+ return 1;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** 'module' function
+** =======================================================
+*/
+
+
+static void setfenv (lua_State *L) {
+ lua_Debug ar;
+ if (lua_getstack(L, 1, &ar) == 0 ||
+ lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
+ lua_iscfunction(L, -1))
+ luaL_error(L, LUA_QL("module") " not called from a Lua function");
+ lua_pushvalue(L, -2);
+ lua_setfenv(L, -2);
+ lua_pop(L, 1);
+}
+
+
+static void dooptions (lua_State *L, int n) {
+ int i;
+ for (i = 2; i <= n; i++) {
+ lua_pushvalue(L, i); /* get option (a function) */
+ lua_pushvalue(L, -2); /* module */
+ lua_call(L, 1, 0);
+ }
+}
+
+
+static void modinit (lua_State *L, const char *modname) {
+ const char *dot;
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "_M"); /* module._M = module */
+ lua_pushstring(L, modname);
+ lua_setfield(L, -2, "_NAME");
+ dot = strrchr(modname, '.'); /* look for last dot in module name */
+ if (dot == NULL) dot = modname;
+ else dot++;
+ /* set _PACKAGE as package name (full module name minus last part) */
+ lua_pushlstring(L, modname, dot - modname);
+ lua_setfield(L, -2, "_PACKAGE");
+}
+
+
+static int ll_module (lua_State *L) {
+ const char *modname = luaL_checkstring(L, 1);
+ int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
+ if (!lua_istable(L, -1)) { /* not found? */
+ lua_pop(L, 1); /* remove previous result */
+ /* try global variable (and create one if it does not exist) */
+ if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
+ return luaL_error(L, "name conflict for module " LUA_QS, modname);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
+ }
+ /* check whether table already has a _NAME field */
+ lua_getfield(L, -1, "_NAME");
+ if (!lua_isnil(L, -1)) /* is table an initialized module? */
+ lua_pop(L, 1);
+ else { /* no; initialize it */
+ lua_pop(L, 1);
+ modinit(L, modname);
+ }
+ lua_pushvalue(L, -1);
+ setfenv(L);
+ dooptions(L, loaded - 1);
+ return 0;
+}
+
+
+static int ll_seeall (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ if (!lua_getmetatable(L, 1)) {
+ lua_createtable(L, 0, 1); /* create new metatable */
+ lua_pushvalue(L, -1);
+ lua_setmetatable(L, 1);
+ }
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, -2, "__index"); /* mt.__index = _G */
+ return 0;
+}
+
+
+/* }====================================================== */
+
+
+
+/* auxiliary mark (for internal use) */
+#define AUXMARK "\1"
+
+static void setpath (lua_State *L, const char *fieldname, const char *envname,
+ const char *def) {
+ const char *path = getenv(envname);
+ if (path == NULL) /* no environment variable? */
+ lua_pushstring(L, def); /* use default */
+ else {
+ /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
+ path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
+ LUA_PATHSEP AUXMARK LUA_PATHSEP);
+ luaL_gsub(L, path, AUXMARK, def);
+ lua_remove(L, -2);
+ }
+ setprogdir(L);
+ lua_setfield(L, -2, fieldname);
+}
+
+
+static const luaL_Reg pk_funcs[] = {
+ {"loadlib", ll_loadlib},
+ {"seeall", ll_seeall},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg ll_funcs[] = {
+ {"module", ll_module},
+ {"require", ll_require},
+ {NULL, NULL}
+};
+
+
+static const lua_CFunction loaders[] =
+ {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
+
+
+LUALIB_API int luaopen_package (lua_State *L) {
+ int i;
+ /* create new type _LOADLIB */
+ luaL_newmetatable(L, "_LOADLIB");
+ lua_pushcfunction(L, gctm);
+ lua_setfield(L, -2, "__gc");
+ /* create `package' table */
+ luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
+#if defined(LUA_COMPAT_LOADLIB)
+ lua_getfield(L, -1, "loadlib");
+ lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
+#endif
+ lua_pushvalue(L, -1);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* create `loaders' table */
+ lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);
+ /* fill it with pre-defined loaders */
+ for (i=0; loaders[i] != NULL; i++) {
+ lua_pushcfunction(L, loaders[i]);
+ lua_rawseti(L, -2, i+1);
+ }
+ lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */
+ setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */
+ setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */
+ /* store config information */
+ lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
+ LUA_EXECDIR "\n" LUA_IGMARK);
+ lua_setfield(L, -2, "config");
+ /* set field `loaded' */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
+ lua_setfield(L, -2, "loaded");
+ /* set field `preload' */
+ lua_newtable(L);
+ lua_setfield(L, -2, "preload");
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ luaL_register(L, NULL, ll_funcs); /* open lib into global table */
+ lua_pop(L, 1);
+ return 1; /* return 'package' table */
+}
diff --git a/debian/grub-extras/lua/lobject.c b/debian/grub-extras/lua/lobject.c
new file mode 100644
index 0000000..432cfde
--- /dev/null
+++ b/debian/grub-extras/lua/lobject.c
@@ -0,0 +1,221 @@
+/*
+** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
+** Some generic functions over Lua objects
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define lobject_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldo.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lvm.h"
+
+
+
+const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+
+
+/*
+** converts an integer to a "floating point byte", represented as
+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
+** eeeee != 0 and (xxx) otherwise.
+*/
+int luaO_int2fb (unsigned int x) {
+ int e = 0; /* expoent */
+ while (x >= 16) {
+ x = (x+1) >> 1;
+ e++;
+ }
+ if (x < 8) return x;
+ else return ((e+1) << 3) | (cast_int(x) - 8);
+}
+
+
+/* converts back */
+int luaO_fb2int (int x) {
+ int e = (x >> 3) & 31;
+ if (e == 0) return x;
+ else return ((x & 7)+8) << (e - 1);
+}
+
+
+int luaO_log2 (unsigned int x) {
+ static const lu_byte log_2[256] = {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ };
+ int l = -1;
+ while (x >= 256) { l += 8; x >>= 8; }
+ return l + log_2[x];
+
+}
+
+
+int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+ if (ttype(t1) != ttype(t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
+ case LUA_TNUMBER:
+ return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
+ case LUA_TLIGHTUSERDATA:
+ return pvalue(t1) == pvalue(t2);
+ default:
+ lua_assert(iscollectable(t1));
+ return gcvalue(t1) == gcvalue(t2);
+ }
+}
+
+
+int luaO_str2d (const char *s, lua_Number *result) {
+ char *endptr;
+ *result = lua_str2number(s, &endptr);
+ if (endptr == s) return 0; /* conversion failed */
+ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
+ *result = cast_num(strtoul(s, &endptr, 16));
+ if (*endptr == '\0') return 1; /* most common case */
+ while (isspace(cast(unsigned char, *endptr))) endptr++;
+ if (*endptr != '\0') return 0; /* invalid trailing characters? */
+ return 1;
+}
+
+
+
+static void pushstr (lua_State *L, const char *str) {
+ setsvalue2s(L, L->top, luaS_new(L, str));
+ incr_top(L);
+}
+
+
+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
+ int n = 1;
+ pushstr(L, "");
+ for (;;) {
+ const char *e = strchr(fmt, '%');
+ if (e == NULL) break;
+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
+ incr_top(L);
+ switch (*(e+1)) {
+ case 's': {
+ const char *s = va_arg(argp, char *);
+ if (s == NULL) s = "(null)";
+ pushstr(L, s);
+ break;
+ }
+ case 'c': {
+ char buff[2];
+ buff[0] = cast(char, va_arg(argp, int));
+ buff[1] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ case 'd': {
+ setnvalue(L->top, cast_num(va_arg(argp, int)));
+ incr_top(L);
+ break;
+ }
+ case 'f': {
+ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
+ incr_top(L);
+ break;
+ }
+ case 'p': {
+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ snprintf(buff, sizeof (buff), "%p", va_arg(argp, void *));
+ pushstr(L, buff);
+ break;
+ }
+ case '%': {
+ pushstr(L, "%");
+ break;
+ }
+ default: {
+ char buff[3];
+ buff[0] = '%';
+ buff[1] = *(e+1);
+ buff[2] = '\0';
+ pushstr(L, buff);
+ break;
+ }
+ }
+ n += 2;
+ fmt = e+2;
+ }
+ pushstr(L, fmt);
+ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);
+ L->top -= n;
+ return svalue(L->top - 1);
+}
+
+
+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
+ const char *msg;
+ va_list argp;
+ va_start(argp, fmt);
+ msg = luaO_pushvfstring(L, fmt, argp);
+ va_end(argp);
+ return msg;
+}
+
+
+void luaO_chunkid (char *out, const char *source, size_t bufflen) {
+ if (*source == '=') {
+ strncpy(out, source+1, bufflen); /* remove first char */
+ out[bufflen-1] = '\0'; /* ensures null termination */
+ }
+ else { /* out = "source", or "...source" */
+ if (*source == '@') {
+ size_t l;
+ char *ptr;
+ source++; /* skip the `@' */
+ bufflen -= sizeof(" '...' ");
+ l = strlen(source);
+ ptr = out;
+ if (l > bufflen) {
+ source += (l-bufflen); /* get last part of file name */
+ ptr = grub_stpcpy (ptr, "...");
+ }
+ ptr = grub_stpcpy(ptr, source);
+ *ptr = '\0';
+ }
+ else { /* out = [string "string"] */
+ size_t len = strcspn(source, "\n\r"); /* stop at first newline */
+ char *ptr;
+ bufflen -= sizeof(" [string \"...\"] ");
+ if (len > bufflen) len = bufflen;
+ ptr = grub_stpcpy(out, "[string \"");
+ if (source[len] != '\0') { /* must truncate? */
+ memcpy(ptr, source, len);
+ ptr += len;
+ ptr = grub_stpcpy(ptr, "...");
+ }
+ else
+ ptr = grub_stpcpy(ptr, source);
+ ptr = grub_stpcpy(ptr, "\"]");
+ *ptr = '\0';
+ }
+ }
+}
diff --git a/debian/grub-extras/lua/lobject.h b/debian/grub-extras/lua/lobject.h
new file mode 100644
index 0000000..8dd3600
--- /dev/null
+++ b/debian/grub-extras/lua/lobject.h
@@ -0,0 +1,380 @@
+/*
+** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $
+** Type definitions for Lua objects
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lobject_h
+#define lobject_h
+
+
+#include <stdarg.h>
+
+
+#include "llimits.h"
+#include "lua.h"
+
+
+/* tags for values visible from Lua */
+#define LAST_TAG LUA_TTHREAD
+
+#define NUM_TAGS (LAST_TAG+1)
+
+
+/*
+** Extra tags for non-values
+*/
+#define LUA_TPROTO (LAST_TAG+1)
+#define LUA_TUPVAL (LAST_TAG+2)
+#define LUA_TDEADKEY (LAST_TAG+3)
+
+
+/*
+** Union of all collectable objects
+*/
+typedef union GCObject GCObject;
+
+
+/*
+** Common Header for all collectable objects (in macro form, to be
+** included in other objects)
+*/
+#define CommonHeader GCObject __attribute__ ((aligned)) *next; lu_byte tt; lu_byte marked
+
+
+/*
+** Common header in struct form
+*/
+typedef struct GCheader {
+ CommonHeader;
+} GCheader;
+
+
+
+
+/*
+** Union of all Lua values
+*/
+typedef union {
+ GCObject *gc;
+ void *p;
+ lua_Number n;
+ int b;
+} Value;
+
+
+/*
+** Tagged Values
+*/
+
+#define TValuefields Value value; int tt
+
+typedef struct lua_TValue {
+ TValuefields;
+} TValue;
+
+
+/* Macros to test type */
+#define ttisnil(o) (ttype(o) == LUA_TNIL)
+#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
+#define ttisstring(o) (ttype(o) == LUA_TSTRING)
+#define ttistable(o) (ttype(o) == LUA_TTABLE)
+#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
+#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
+#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
+#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
+#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
+
+/* Macros to access values */
+#define ttype(o) ((o)->tt)
+#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
+#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
+#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
+#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
+#define tsvalue(o) (&rawtsvalue(o)->tsv)
+#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define uvalue(o) (&rawuvalue(o)->uv)
+#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
+#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
+#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
+#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
+
+#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
+
+/*
+** for internal debug only
+*/
+#define checkconsistency(obj) \
+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
+
+#define checkliveness(g,obj) \
+ lua_assert(!iscollectable(obj) || \
+ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
+
+
+/* Macros to set values */
+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+#define setnvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
+
+#define setpvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+
+#define setbvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
+
+#define setsvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
+ checkliveness(G(L),i_o); }
+
+#define setuvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
+ checkliveness(G(L),i_o); }
+
+#define setthvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
+ checkliveness(G(L),i_o); }
+
+#define setclvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
+ checkliveness(G(L),i_o); }
+
+#define sethvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
+ checkliveness(G(L),i_o); }
+
+#define setptvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+ checkliveness(G(L),i_o); }
+
+
+
+
+#define setobj(L,obj1,obj2) \
+ { const TValue *o2=(obj2); TValue *o1=(obj1); \
+ o1->value = o2->value; o1->tt=o2->tt; \
+ checkliveness(G(L),o1); }
+
+
+/*
+** different types of sets, according to destination
+*/
+
+/* from stack to (same) stack */
+#define setobjs2s setobj
+/* to stack (not from same stack) */
+#define setobj2s setobj
+#define setsvalue2s setsvalue
+#define sethvalue2s sethvalue
+#define setptvalue2s setptvalue
+/* from table to same table */
+#define setobjt2t setobj
+/* to table */
+#define setobj2t setobj
+/* to new object */
+#define setobj2n setobj
+#define setsvalue2n setsvalue
+
+#define setttype(obj, tt) (ttype(obj) = (tt))
+
+
+#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
+
+
+
+typedef TValue *StkId; /* index to stack elements */
+
+
+/*
+** String headers for string table
+*/
+typedef union TString {
+ L_Umaxalign dummy; /* ensures maximum alignment for strings */
+ struct {
+ CommonHeader;
+ lu_byte reserved;
+ unsigned int hash;
+ size_t len;
+ } tsv;
+} TString;
+
+
+#define getstr(ts) cast(const char *, (ts) + 1)
+#define svalue(o) getstr(rawtsvalue(o))
+
+
+
+typedef union Udata {
+ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
+ struct {
+ CommonHeader;
+ struct Table *metatable;
+ struct Table *env;
+ size_t len;
+ } uv;
+} Udata;
+
+
+
+
+/*
+** Function Prototypes
+*/
+typedef struct Proto {
+ CommonHeader;
+ TValue *k; /* constants used by the function */
+ Instruction *code;
+ struct Proto **p; /* functions defined inside the function */
+ int *lineinfo; /* map from opcodes to source lines */
+ struct LocVar *locvars; /* information about local variables */
+ TString **upvalues; /* upvalue names */
+ TString *source;
+ int sizeupvalues;
+ int sizek; /* size of `k' */
+ int sizecode;
+ int sizelineinfo;
+ int sizep; /* size of `p' */
+ int sizelocvars;
+ int linedefined;
+ int lastlinedefined;
+ GCObject *gclist;
+ lu_byte nups; /* number of upvalues */
+ lu_byte numparams;
+ lu_byte is_vararg;
+ lu_byte maxstacksize;
+} Proto;
+
+
+/* masks for new-style vararg */
+#define VARARG_HASARG 1
+#define VARARG_ISVARARG 2
+#define VARARG_NEEDSARG 4
+
+
+typedef struct LocVar {
+ TString *varname;
+ int startpc; /* first point where variable is active */
+ int endpc; /* first point where variable is dead */
+} LocVar;
+
+
+
+/*
+** Upvalues
+*/
+
+typedef struct UpVal {
+ CommonHeader;
+ TValue *v; /* points to stack or to its own value */
+ union {
+ TValue value; /* the value (when closed) */
+ struct { /* double linked list (when open) */
+ struct UpVal *prev;
+ struct UpVal *next;
+ } l;
+ } u;
+} UpVal;
+
+
+/*
+** Closures
+*/
+
+#define ClosureHeader \
+ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
+ struct Table *env
+
+typedef struct CClosure {
+ ClosureHeader;
+ lua_CFunction f;
+ TValue upvalue[1];
+} CClosure;
+
+
+typedef struct LClosure {
+ ClosureHeader;
+ struct Proto *p;
+ UpVal *upvals[1];
+} LClosure;
+
+
+typedef union Closure {
+ CClosure c;
+ LClosure l;
+} Closure;
+
+
+#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
+#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
+
+
+/*
+** Tables
+*/
+
+typedef union TKey {
+ struct {
+ TValuefields;
+ struct Node *next; /* for chaining */
+ } nk;
+ TValue tvk;
+} TKey;
+
+
+typedef struct Node {
+ TValue i_val;
+ TKey i_key;
+} Node;
+
+
+typedef struct Table {
+ CommonHeader;
+ lu_byte flags; /* 1<<p means tagmethod(p) is not present */
+ lu_byte lsizenode; /* log2 of size of `node' array */
+ struct Table *metatable;
+ TValue *array; /* array part */
+ Node *node;
+ Node *lastfree; /* any free position is before this position */
+ GCObject *gclist;
+ int sizearray; /* size of `array' array */
+} Table;
+
+
+
+/*
+** `module' operation for hashing (size is always a power of 2)
+*/
+#define lmod(s,size) \
+ (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
+
+
+#define twoto(x) (1<<(x))
+#define sizenode(t) (twoto((t)->lsizenode))
+
+
+#define luaO_nilobject (&luaO_nilobject_)
+
+LUAI_DATA const TValue luaO_nilobject_;
+
+#define ceillog2(x) (luaO_log2((x)-1) + 1)
+
+LUAI_FUNC int luaO_log2 (unsigned int x);
+LUAI_FUNC int luaO_int2fb (unsigned int x);
+LUAI_FUNC int luaO_fb2int (int x);
+LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp);
+LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+
+
+#endif
diff --git a/debian/grub-extras/lua/lopcodes.c b/debian/grub-extras/lua/lopcodes.c
new file mode 100644
index 0000000..4cc7452
--- /dev/null
+++ b/debian/grub-extras/lua/lopcodes.c
@@ -0,0 +1,102 @@
+/*
+** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
+** See Copyright Notice in lua.h
+*/
+
+
+#define lopcodes_c
+#define LUA_CORE
+
+
+#include "lopcodes.h"
+
+
+/* ORDER OP */
+
+const char *const luaP_opnames[NUM_OPCODES+1] = {
+ "MOVE",
+ "LOADK",
+ "LOADBOOL",
+ "LOADNIL",
+ "GETUPVAL",
+ "GETGLOBAL",
+ "GETTABLE",
+ "SETGLOBAL",
+ "SETUPVAL",
+ "SETTABLE",
+ "NEWTABLE",
+ "SELF",
+ "ADD",
+ "SUB",
+ "MUL",
+ "DIV",
+ "MOD",
+ "POW",
+ "UNM",
+ "NOT",
+ "LEN",
+ "CONCAT",
+ "JMP",
+ "EQ",
+ "LT",
+ "LE",
+ "TEST",
+ "TESTSET",
+ "CALL",
+ "TAILCALL",
+ "RETURN",
+ "FORLOOP",
+ "FORPREP",
+ "TFORLOOP",
+ "SETLIST",
+ "CLOSE",
+ "CLOSURE",
+ "VARARG",
+ NULL
+};
+
+
+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
+
+const lu_byte luaP_opmodes[NUM_OPCODES] = {
+/* T A B C mode opcode */
+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
+};
+
diff --git a/debian/grub-extras/lua/lopcodes.h b/debian/grub-extras/lua/lopcodes.h
new file mode 100644
index 0000000..ad66eea
--- /dev/null
+++ b/debian/grub-extras/lua/lopcodes.h
@@ -0,0 +1,268 @@
+/*
+** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
+** Opcodes for Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lopcodes_h
+#define lopcodes_h
+
+#include "llimits.h"
+
+
+/*===========================================================================
+ We assume that instructions are unsigned numbers.
+ All instructions have an opcode in the first 6 bits.
+ Instructions can have the following fields:
+ `A' : 8 bits
+ `B' : 9 bits
+ `C' : 9 bits
+ `Bx' : 18 bits (`B' and `C' together)
+ `sBx' : signed Bx
+
+ A signed argument is represented in excess K; that is, the number
+ value is the unsigned value minus K. K is exactly the maximum value
+ for that argument (so that -max is represented by 0, and +max is
+ represented by 2*max), which is half the maximum for the corresponding
+ unsigned argument.
+===========================================================================*/
+
+
+enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
+
+
+/*
+** size and position of opcode arguments.
+*/
+#define SIZE_C 9
+#define SIZE_B 9
+#define SIZE_Bx (SIZE_C + SIZE_B)
+#define SIZE_A 8
+
+#define SIZE_OP 6
+
+#define POS_OP 0
+#define POS_A (POS_OP + SIZE_OP)
+#define POS_C (POS_A + SIZE_A)
+#define POS_B (POS_C + SIZE_C)
+#define POS_Bx POS_C
+
+
+/*
+** limits for opcode arguments.
+** we use (signed) int to manipulate most arguments,
+** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
+*/
+#if SIZE_Bx < LUAI_BITSINT-1
+#define MAXARG_Bx ((1<<SIZE_Bx)-1)
+#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
+#else
+#define MAXARG_Bx MAX_INT
+#define MAXARG_sBx MAX_INT
+#endif
+
+
+#define MAXARG_A ((1<<SIZE_A)-1)
+#define MAXARG_B ((1<<SIZE_B)-1)
+#define MAXARG_C ((1<<SIZE_C)-1)
+
+
+/* creates a mask with `n' 1 bits at position `p' */
+#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p)
+
+/* creates a mask with `n' 0 bits at position `p' */
+#define MASK0(n,p) (~MASK1(n,p))
+
+/*
+** the following macros help to manipulate instructions
+*/
+
+#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
+ ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
+
+#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
+#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
+ ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
+
+#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
+#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
+ ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
+
+#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
+#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
+ ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
+
+#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
+#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
+ ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
+
+#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
+#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
+
+
+#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \
+ | (cast(Instruction, a)<<POS_A) \
+ | (cast(Instruction, b)<<POS_B) \
+ | (cast(Instruction, c)<<POS_C))
+
+#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
+ | (cast(Instruction, a)<<POS_A) \
+ | (cast(Instruction, bc)<<POS_Bx))
+
+
+/*
+** Macros to operate RK indices
+*/
+
+/* this bit 1 means constant (0 means register) */
+#define BITRK (1 << (SIZE_B - 1))
+
+/* test whether value is a constant */
+#define ISK(x) ((x) & BITRK)
+
+/* gets the index of the constant */
+#define INDEXK(r) ((int)(r) & ~BITRK)
+
+#define MAXINDEXRK (BITRK - 1)
+
+/* code a constant index as a RK value */
+#define RKASK(x) ((x) | BITRK)
+
+
+/*
+** invalid register that fits in 8 bits
+*/
+#define NO_REG MAXARG_A
+
+
+/*
+** R(x) - register
+** Kst(x) - constant (in constant table)
+** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
+*/
+
+
+/*
+** grep "ORDER OP" if you change these enums
+*/
+
+typedef enum {
+/*----------------------------------------------------------------------
+name args description
+------------------------------------------------------------------------*/
+OP_MOVE,/* A B R(A) := R(B) */
+OP_LOADK,/* A Bx R(A) := Kst(Bx) */
+OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
+OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
+OP_GETUPVAL,/* A B R(A) := UpValue[B] */
+
+OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
+OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
+
+OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
+OP_SETUPVAL,/* A B UpValue[B] := R(A) */
+OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
+
+OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
+
+OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
+
+OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
+OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
+OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
+OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
+OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
+OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
+OP_UNM,/* A B R(A) := -R(B) */
+OP_NOT,/* A B R(A) := not R(B) */
+OP_LEN,/* A B R(A) := length of R(B) */
+
+OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
+
+OP_JMP,/* sBx pc+=sBx */
+
+OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
+OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
+OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
+
+OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
+OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
+
+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
+
+OP_FORLOOP,/* A sBx R(A)+=R(A+2);
+ if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
+
+OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
+ if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
+OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
+
+OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
+
+OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
+} OpCode;
+
+
+#define NUM_OPCODES (cast(int, OP_VARARG) + 1)
+
+
+
+/*===========================================================================
+ Notes:
+ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+ and can be 0: OP_CALL then sets `top' to last_result+1, so
+ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
+
+ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
+ set top (like in OP_CALL with C == 0).
+
+ (*) In OP_RETURN, if (B == 0) then return up to `top'
+
+ (*) In OP_SETLIST, if (B == 0) then B = `top';
+ if (C == 0) then next `instruction' is real C
+
+ (*) For comparisons, A specifies what condition the test should accept
+ (true or false).
+
+ (*) All `skips' (pc++) assume that next instruction is a jump
+===========================================================================*/
+
+
+/*
+** masks for instruction properties. The format is:
+** bits 0-1: op mode
+** bits 2-3: C arg mode
+** bits 4-5: B arg mode
+** bit 6: instruction set register A
+** bit 7: operator is a test
+*/
+
+enum OpArgMask {
+ OpArgN, /* argument is not used */
+ OpArgU, /* argument is used */
+ OpArgR, /* argument is a register or a jump offset */
+ OpArgK /* argument is a constant or register/constant */
+};
+
+LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
+
+#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
+#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
+#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
+#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
+#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
+
+
+LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
+
+
+/* number of list items to accumulate before a SETLIST instruction */
+#define LFIELDS_PER_FLUSH 50
+
+
+#endif
diff --git a/debian/grub-extras/lua/loslib.c b/debian/grub-extras/lua/loslib.c
new file mode 100644
index 0000000..da06a57
--- /dev/null
+++ b/debian/grub-extras/lua/loslib.c
@@ -0,0 +1,243 @@
+/*
+** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
+** Standard Operating System library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define loslib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+static int os_pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
+ if (i) {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ else {
+ lua_pushnil(L);
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static int os_execute (lua_State *L) {
+ lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
+ return 1;
+}
+
+
+static int os_remove (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ return os_pushresult(L, remove(filename) == 0, filename);
+}
+
+
+static int os_rename (lua_State *L) {
+ const char *fromname = luaL_checkstring(L, 1);
+ const char *toname = luaL_checkstring(L, 2);
+ return os_pushresult(L, rename(fromname, toname) == 0, fromname);
+}
+
+
+static int os_tmpname (lua_State *L) {
+ char buff[LUA_TMPNAMBUFSIZE];
+ int err;
+ lua_tmpnam(buff, err);
+ if (err)
+ return luaL_error(L, "unable to generate a unique filename");
+ lua_pushstring(L, buff);
+ return 1;
+}
+
+
+static int os_getenv (lua_State *L) {
+ lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
+ return 1;
+}
+
+
+static int os_clock (lua_State *L) {
+ lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
+ return 1;
+}
+
+
+/*
+** {======================================================
+** Time/Date operations
+** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+** wday=%w+1, yday=%j, isdst=? }
+** =======================================================
+*/
+
+static void setfield (lua_State *L, const char *key, int value) {
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static void setboolfield (lua_State *L, const char *key, int value) {
+ if (value < 0) /* undefined? */
+ return; /* does not set field */
+ lua_pushboolean(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static int getboolfield (lua_State *L, const char *key) {
+ int res;
+ lua_getfield(L, -1, key);
+ res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int getfield (lua_State *L, const char *key, int d) {
+ int res;
+ lua_getfield(L, -1, key);
+ if (lua_isnumber(L, -1))
+ res = (int)lua_tointeger(L, -1);
+ else {
+ if (d < 0)
+ return luaL_error(L, "field " LUA_QS " missing in date table", key);
+ res = d;
+ }
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int os_date (lua_State *L) {
+ const char *s = luaL_optstring(L, 1, "%c");
+ time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
+ struct tm *stm;
+ if (*s == '!') { /* UTC? */
+ stm = gmtime(&t);
+ s++; /* skip `!' */
+ }
+ else
+ stm = localtime(&t);
+ if (stm == NULL) /* invalid date? */
+ lua_pushnil(L);
+ else if (strcmp(s, "*t") == 0) {
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
+ setfield(L, "sec", stm->tm_sec);
+ setfield(L, "min", stm->tm_min);
+ setfield(L, "hour", stm->tm_hour);
+ setfield(L, "day", stm->tm_mday);
+ setfield(L, "month", stm->tm_mon+1);
+ setfield(L, "year", stm->tm_year+1900);
+ setfield(L, "wday", stm->tm_wday+1);
+ setfield(L, "yday", stm->tm_yday+1);
+ setboolfield(L, "isdst", stm->tm_isdst);
+ }
+ else {
+ char cc[3];
+ luaL_Buffer b;
+ cc[0] = '%'; cc[2] = '\0';
+ luaL_buffinit(L, &b);
+ for (; *s; s++) {
+ if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
+ luaL_addchar(&b, *s);
+ else {
+ size_t reslen;
+ char buff[200]; /* should be big enough for any conversion result */
+ cc[1] = *(++s);
+ reslen = strftime(buff, sizeof(buff), cc, stm);
+ luaL_addlstring(&b, buff, reslen);
+ }
+ }
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+
+static int os_time (lua_State *L) {
+ time_t t;
+ if (lua_isnoneornil(L, 1)) /* called without args? */
+ t = time(NULL); /* get current time */
+ else {
+ struct tm ts;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1); /* make sure table is at the top */
+ ts.tm_sec = getfield(L, "sec", 0);
+ ts.tm_min = getfield(L, "min", 0);
+ ts.tm_hour = getfield(L, "hour", 12);
+ ts.tm_mday = getfield(L, "day", -1);
+ ts.tm_mon = getfield(L, "month", -1) - 1;
+ ts.tm_year = getfield(L, "year", -1) - 1900;
+ ts.tm_isdst = getboolfield(L, "isdst");
+ t = mktime(&ts);
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+ else
+ lua_pushnumber(L, (lua_Number)t);
+ return 1;
+}
+
+
+static int os_difftime (lua_State *L) {
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
+ return 1;
+}
+
+/* }====================================================== */
+
+
+static int os_setlocale (lua_State *L) {
+ static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
+ LC_NUMERIC, LC_TIME};
+ static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
+ "numeric", "time", NULL};
+ const char *l = luaL_optstring(L, 1, NULL);
+ int op = luaL_checkoption(L, 2, "all", catnames);
+ lua_pushstring(L, setlocale(cat[op], l));
+ return 1;
+}
+
+
+static int os_exit (lua_State *L) {
+ exit(luaL_optint(L, 1, EXIT_SUCCESS));
+}
+
+static const luaL_Reg syslib[] = {
+ {"clock", os_clock},
+ {"date", os_date},
+ {"difftime", os_difftime},
+ {"execute", os_execute},
+ {"exit", os_exit},
+ {"getenv", os_getenv},
+ {"remove", os_remove},
+ {"rename", os_rename},
+ {"setlocale", os_setlocale},
+ {"time", os_time},
+ {"tmpname", os_tmpname},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_os (lua_State *L) {
+ luaL_register(L, LUA_OSLIBNAME, syslib);
+ return 1;
+}
+
diff --git a/debian/grub-extras/lua/lparser.c b/debian/grub-extras/lua/lparser.c
new file mode 100644
index 0000000..309f518
--- /dev/null
+++ b/debian/grub-extras/lua/lparser.c
@@ -0,0 +1,1340 @@
+/*
+** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <string.h>
+#endif
+
+#define lparser_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lparser.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+
+
+
+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
+
+#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
+
+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
+
+
+/*
+** nodes for block list (list of active blocks)
+*/
+typedef struct BlockCnt {
+ struct BlockCnt *previous; /* chain */
+ int breaklist; /* list of jumps out of this loop */
+ lu_byte nactvar; /* # active locals outside the breakable structure */
+ lu_byte upval; /* true if some variable in the block is an upvalue */
+ lu_byte isbreakable; /* true if `block' is a loop */
+} BlockCnt;
+
+
+
+/*
+** prototypes for recursive non-terminal functions
+*/
+static void chunk (LexState *ls);
+static void expr (LexState *ls, expdesc *v);
+
+
+static void anchor_token (LexState *ls) {
+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
+ TString *ts = ls->t.seminfo.ts;
+ luaX_newstring(ls, getstr(ts), ts->tsv.len);
+ }
+}
+
+
+static void error_expected (LexState *ls, int token) {
+ luaX_syntaxerror(ls,
+ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
+}
+
+
+static void errorlimit (FuncState *fs, int limit, const char *what) {
+ const char *msg = (fs->f->linedefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+ fs->f->linedefined, limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+}
+
+
+static int testnext (LexState *ls, int c) {
+ if (ls->t.token == c) {
+ luaX_next(ls);
+ return 1;
+ }
+ else return 0;
+}
+
+
+static void check (LexState *ls, int c) {
+ if (ls->t.token != c)
+ error_expected(ls, c);
+}
+
+static void checknext (LexState *ls, int c) {
+ check(ls, c);
+ luaX_next(ls);
+}
+
+
+#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
+
+
+
+static void check_match (LexState *ls, int what, int who, int where) {
+ if (!testnext(ls, what)) {
+ if (where == ls->linenumber)
+ error_expected(ls, what);
+ else {
+ luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
+ LUA_QS " expected (to close " LUA_QS " at line %d)",
+ luaX_token2str(ls, what), luaX_token2str(ls, who), where));
+ }
+ }
+}
+
+
+static TString *str_checkname (LexState *ls) {
+ TString *ts;
+ check(ls, TK_NAME);
+ ts = ls->t.seminfo.ts;
+ luaX_next(ls);
+ return ts;
+}
+
+
+static void init_exp (expdesc *e, expkind k, int i) {
+ e->f = e->t = NO_JUMP;
+ e->k = k;
+ e->u.s.info = i;
+}
+
+
+static void codestring (LexState *ls, expdesc *e, TString *s) {
+ init_exp(e, VK, luaK_stringK(ls->fs, s));
+}
+
+
+static void checkname(LexState *ls, expdesc *e) {
+ codestring(ls, e, str_checkname(ls));
+}
+
+
+static int registerlocalvar (LexState *ls, TString *varname) {
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int oldsize = f->sizelocvars;
+ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
+ LocVar, SHRT_MAX, "too many local variables");
+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
+ f->locvars[fs->nlocvars].varname = varname;
+ luaC_objbarrier(ls->L, f, varname);
+ return fs->nlocvars++;
+}
+
+
+#define new_localvarliteral(ls,v,n) \
+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
+
+
+static void new_localvar (LexState *ls, TString *name, int n) {
+ FuncState *fs = ls->fs;
+ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
+ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
+}
+
+
+static void adjustlocalvars (LexState *ls, int nvars) {
+ FuncState *fs = ls->fs;
+ fs->nactvar = cast_byte(fs->nactvar + nvars);
+ for (; nvars; nvars--) {
+ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
+ }
+}
+
+
+static void removevars (LexState *ls, int tolevel) {
+ FuncState *fs = ls->fs;
+ while (fs->nactvar > tolevel)
+ getlocvar(fs, --fs->nactvar).endpc = fs->pc;
+}
+
+
+static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
+ int i;
+ Proto *f = fs->f;
+ int oldsize = f->sizeupvalues;
+ for (i=0; i<f->nups; i++) {
+ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
+ lua_assert(f->upvalues[i] == name);
+ return i;
+ }
+ }
+ /* new one */
+ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
+ TString *, MAX_INT, "");
+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
+ f->upvalues[f->nups] = name;
+ luaC_objbarrier(fs->L, f, name);
+ lua_assert(v->k == VLOCAL || v->k == VUPVAL);
+ fs->upvalues[f->nups].k = cast_byte(v->k);
+ fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
+ return f->nups++;
+}
+
+
+static int searchvar (FuncState *fs, TString *n) {
+ int i;
+ for (i=fs->nactvar-1; i >= 0; i--) {
+ if (n == getlocvar(fs, i).varname)
+ return i;
+ }
+ return -1; /* not found */
+}
+
+
+static void markupval (FuncState *fs, int level) {
+ BlockCnt *bl = fs->bl;
+ while (bl && bl->nactvar > level) bl = bl->previous;
+ if (bl) bl->upval = 1;
+}
+
+
+static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
+ if (fs == NULL) { /* no more levels? */
+ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
+ return VGLOBAL;
+ }
+ else {
+ int v = searchvar(fs, n); /* look up at current level */
+ if (v >= 0) {
+ init_exp(var, VLOCAL, v);
+ if (!base)
+ markupval(fs, v); /* local will be used as an upval */
+ return VLOCAL;
+ }
+ else { /* not found at current level; try upper one */
+ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
+ return VGLOBAL;
+ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
+ var->k = VUPVAL; /* upvalue in this level */
+ return VUPVAL;
+ }
+ }
+}
+
+
+static void singlevar (LexState *ls, expdesc *var) {
+ TString *varname = str_checkname(ls);
+ FuncState *fs = ls->fs;
+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
+ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
+}
+
+
+static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
+ FuncState *fs = ls->fs;
+ int extra = nvars - nexps;
+ if (hasmultret(e->k)) {
+ extra++; /* includes call itself */
+ if (extra < 0) extra = 0;
+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
+ if (extra > 1) luaK_reserveregs(fs, extra-1);
+ }
+ else {
+ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
+ if (extra > 0) {
+ int reg = fs->freereg;
+ luaK_reserveregs(fs, extra);
+ luaK_nil(fs, reg, extra);
+ }
+ }
+}
+
+
+static void enterlevel (LexState *ls) {
+ if (++ls->L->nCcalls > LUAI_MAXCCALLS)
+ luaX_lexerror(ls, "chunk has too many syntax levels", 0);
+}
+
+
+#define leavelevel(ls) ((ls)->L->nCcalls--)
+
+
+static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
+ bl->breaklist = NO_JUMP;
+ bl->isbreakable = isbreakable;
+ bl->nactvar = fs->nactvar;
+ bl->upval = 0;
+ bl->previous = fs->bl;
+ fs->bl = bl;
+ lua_assert(fs->freereg == fs->nactvar);
+}
+
+
+static void leaveblock (FuncState *fs) {
+ BlockCnt *bl = fs->bl;
+ fs->bl = bl->previous;
+ removevars(fs->ls, bl->nactvar);
+ if (bl->upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ /* a block either controls scope or breaks (never both) */
+ lua_assert(!bl->isbreakable || !bl->upval);
+ lua_assert(bl->nactvar == fs->nactvar);
+ fs->freereg = fs->nactvar; /* free registers */
+ luaK_patchtohere(fs, bl->breaklist);
+}
+
+
+static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int oldsize = f->sizep;
+ int i;
+ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizep) f->p[oldsize++] = NULL;
+ f->p[fs->np++] = func->f;
+ luaC_objbarrier(ls->L, f, func->f);
+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+ for (i=0; i<func->f->nups; i++) {
+ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
+ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
+ }
+}
+
+
+static void open_func (LexState *ls, FuncState *fs) {
+ lua_State *L = ls->L;
+ Proto *f = luaF_newproto(L);
+ fs->f = f;
+ fs->prev = ls->fs; /* linked list of funcstates */
+ fs->ls = ls;
+ fs->L = L;
+ ls->fs = fs;
+ fs->pc = 0;
+ fs->lasttarget = -1;
+ fs->jpc = NO_JUMP;
+ fs->freereg = 0;
+ fs->nk = 0;
+ fs->np = 0;
+ fs->nlocvars = 0;
+ fs->nactvar = 0;
+ fs->bl = NULL;
+ f->source = ls->source;
+ f->maxstacksize = 2; /* registers 0/1 are always valid */
+ fs->h = luaH_new(L, 0, 0);
+ /* anchor table of constants and prototype (to avoid being collected) */
+ sethvalue2s(L, L->top, fs->h);
+ incr_top(L);
+ setptvalue2s(L, L->top, f);
+ incr_top(L);
+}
+
+
+static void close_func (LexState *ls) {
+ lua_State *L = ls->L;
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ removevars(ls, 0);
+ luaK_ret(fs, 0, 0); /* final return */
+ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
+ f->sizecode = fs->pc;
+ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
+ f->sizelineinfo = fs->pc;
+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
+ f->sizek = fs->nk;
+ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
+ f->sizep = fs->np;
+ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
+ f->sizelocvars = fs->nlocvars;
+ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
+ f->sizeupvalues = f->nups;
+ lua_assert(luaG_checkcode(f));
+ lua_assert(fs->bl == NULL);
+ ls->fs = fs->prev;
+ L->top -= 2; /* remove table and prototype from the stack */
+ /* last token read was anchored in defunct function; must reanchor it */
+ if (fs) anchor_token(ls);
+}
+
+
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
+ struct LexState lexstate;
+ struct FuncState funcstate;
+ lexstate.buff = buff;
+ luaX_setinput(L, &lexstate, z, luaS_new(L, name));
+ open_func(&lexstate, &funcstate);
+ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
+ luaX_next(&lexstate); /* read first token */
+ chunk(&lexstate);
+ check(&lexstate, TK_EOS);
+ close_func(&lexstate);
+ lua_assert(funcstate.prev == NULL);
+ lua_assert(funcstate.f->nups == 0);
+ lua_assert(lexstate.fs == NULL);
+ return funcstate.f;
+}
+
+
+
+/*============================================================*/
+/* GRAMMAR RULES */
+/*============================================================*/
+
+
+static void field (LexState *ls, expdesc *v) {
+ /* field -> ['.' | ':'] NAME */
+ FuncState *fs = ls->fs;
+ expdesc key;
+ luaK_exp2anyreg(fs, v);
+ luaX_next(ls); /* skip the dot or colon */
+ checkname(ls, &key);
+ luaK_indexed(fs, v, &key);
+}
+
+
+static void yindex (LexState *ls, expdesc *v) {
+ /* index -> '[' expr ']' */
+ luaX_next(ls); /* skip the '[' */
+ expr(ls, v);
+ luaK_exp2val(ls->fs, v);
+ checknext(ls, ']');
+}
+
+
+/*
+** {======================================================================
+** Rules for Constructors
+** =======================================================================
+*/
+
+
+struct ConsControl {
+ expdesc v; /* last list item read */
+ expdesc *t; /* table descriptor */
+ int nh; /* total number of `record' elements */
+ int na; /* total number of array elements */
+ int tostore; /* number of array elements pending to be stored */
+};
+
+
+static void recfield (LexState *ls, struct ConsControl *cc) {
+ /* recfield -> (NAME | `['exp1`]') = exp1 */
+ FuncState *fs = ls->fs;
+ int reg = ls->fs->freereg;
+ expdesc key, val;
+ int rkkey;
+ if (ls->t.token == TK_NAME) {
+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
+ checkname(ls, &key);
+ }
+ else /* ls->t.token == '[' */
+ yindex(ls, &key);
+ cc->nh++;
+ checknext(ls, '=');
+ rkkey = luaK_exp2RK(fs, &key);
+ expr(ls, &val);
+ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));
+ fs->freereg = reg; /* free registers */
+}
+
+
+static void closelistfield (FuncState *fs, struct ConsControl *cc) {
+ if (cc->v.k == VVOID) return; /* there is no list item */
+ luaK_exp2nextreg(fs, &cc->v);
+ cc->v.k = VVOID;
+ if (cc->tostore == LFIELDS_PER_FLUSH) {
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */
+ cc->tostore = 0; /* no more items pending */
+ }
+}
+
+
+static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
+ if (cc->tostore == 0) return;
+ if (hasmultret(cc->v.k)) {
+ luaK_setmultret(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
+ cc->na--; /* do not count last expression (unknown number of elements) */
+ }
+ else {
+ if (cc->v.k != VVOID)
+ luaK_exp2nextreg(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
+ }
+}
+
+
+static void listfield (LexState *ls, struct ConsControl *cc) {
+ expr(ls, &cc->v);
+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
+ cc->na++;
+ cc->tostore++;
+}
+
+
+static void constructor (LexState *ls, expdesc *t) {
+ /* constructor -> ?? */
+ FuncState *fs = ls->fs;
+ int line = ls->linenumber;
+ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
+ struct ConsControl cc;
+ cc.na = cc.nh = cc.tostore = 0;
+ cc.t = t;
+ init_exp(t, VRELOCABLE, pc);
+ init_exp(&cc.v, VVOID, 0); /* no value (yet) */
+ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */
+ checknext(ls, '{');
+ do {
+ lua_assert(cc.v.k == VVOID || cc.tostore > 0);
+ if (ls->t.token == '}') break;
+ closelistfield(fs, &cc);
+ switch(ls->t.token) {
+ case TK_NAME: { /* may be listfields or recfields */
+ luaX_lookahead(ls);
+ if (ls->lookahead.token != '=') /* expression? */
+ listfield(ls, &cc);
+ else
+ recfield(ls, &cc);
+ break;
+ }
+ case '[': { /* constructor_item -> recfield */
+ recfield(ls, &cc);
+ break;
+ }
+ default: { /* constructor_part -> listfield */
+ listfield(ls, &cc);
+ break;
+ }
+ }
+ } while (testnext(ls, ',') || testnext(ls, ';'));
+ check_match(ls, '}', '{', line);
+ lastlistfield(fs, &cc);
+ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
+ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
+}
+
+/* }====================================================================== */
+
+
+
+static void parlist (LexState *ls) {
+ /* parlist -> [ param { `,' param } ] */
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
+ int nparams = 0;
+ f->is_vararg = 0;
+ if (ls->t.token != ')') { /* is `parlist' not empty? */
+ do {
+ switch (ls->t.token) {
+ case TK_NAME: { /* param -> NAME */
+ new_localvar(ls, str_checkname(ls), nparams++);
+ break;
+ }
+ case TK_DOTS: { /* param -> `...' */
+ luaX_next(ls);
+#if defined(LUA_COMPAT_VARARG)
+ /* use `arg' as default name */
+ new_localvarliteral(ls, "arg", nparams++);
+ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
+#endif
+ f->is_vararg |= VARARG_ISVARARG;
+ break;
+ }
+ default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
+ }
+ } while (!f->is_vararg && testnext(ls, ','));
+ }
+ adjustlocalvars(ls, nparams);
+ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
+}
+
+
+static void body (LexState *ls, expdesc *e, int needself, int line) {
+ /* body -> `(' parlist `)' chunk END */
+ FuncState new_fs;
+ open_func(ls, &new_fs);
+ new_fs.f->linedefined = line;
+ checknext(ls, '(');
+ if (needself) {
+ new_localvarliteral(ls, "self", 0);
+ adjustlocalvars(ls, 1);
+ }
+ parlist(ls);
+ checknext(ls, ')');
+ chunk(ls);
+ new_fs.f->lastlinedefined = ls->linenumber;
+ check_match(ls, TK_END, TK_FUNCTION, line);
+ close_func(ls);
+ pushclosure(ls, &new_fs, e);
+}
+
+
+static int explist1 (LexState *ls, expdesc *v) {
+ /* explist1 -> expr { `,' expr } */
+ int n = 1; /* at least one expression */
+ expr(ls, v);
+ while (testnext(ls, ',')) {
+ luaK_exp2nextreg(ls->fs, v);
+ expr(ls, v);
+ n++;
+ }
+ return n;
+}
+
+
+static void funcargs (LexState *ls, expdesc *f) {
+ FuncState *fs = ls->fs;
+ expdesc args;
+ int base, nparams;
+ int line = ls->linenumber;
+ switch (ls->t.token) {
+ case '(': { /* funcargs -> `(' [ explist1 ] `)' */
+ if (line != ls->lastline)
+ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
+ luaX_next(ls);
+ if (ls->t.token == ')') /* arg list is empty? */
+ args.k = VVOID;
+ else {
+ explist1(ls, &args);
+ luaK_setmultret(fs, &args);
+ }
+ check_match(ls, ')', '(', line);
+ break;
+ }
+ case '{': { /* funcargs -> constructor */
+ constructor(ls, &args);
+ break;
+ }
+ case TK_STRING: { /* funcargs -> STRING */
+ codestring(ls, &args, ls->t.seminfo.ts);
+ luaX_next(ls); /* must use `seminfo' before `next' */
+ break;
+ }
+ default: {
+ luaX_syntaxerror(ls, "function arguments expected");
+ return;
+ }
+ }
+ lua_assert(f->k == VNONRELOC);
+ base = f->u.s.info; /* base register for call */
+ if (hasmultret(args.k))
+ nparams = LUA_MULTRET; /* open call */
+ else {
+ if (args.k != VVOID)
+ luaK_exp2nextreg(fs, &args); /* close last argument */
+ nparams = fs->freereg - (base+1);
+ }
+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+ luaK_fixline(fs, line);
+ fs->freereg = base+1; /* call remove function and arguments and leaves
+ (unless changed) one result */
+}
+
+
+
+
+/*
+** {======================================================================
+** Expression parsing
+** =======================================================================
+*/
+
+
+static void prefixexp (LexState *ls, expdesc *v) {
+ /* prefixexp -> NAME | '(' expr ')' */
+ switch (ls->t.token) {
+ case '(': {
+ int line = ls->linenumber;
+ luaX_next(ls);
+ expr(ls, v);
+ check_match(ls, ')', '(', line);
+ luaK_dischargevars(ls->fs, v);
+ return;
+ }
+ case TK_NAME: {
+ singlevar(ls, v);
+ return;
+ }
+ default: {
+ luaX_syntaxerror(ls, "unexpected symbol");
+ return;
+ }
+ }
+}
+
+
+static void primaryexp (LexState *ls, expdesc *v) {
+ /* primaryexp ->
+ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+ FuncState *fs = ls->fs;
+ prefixexp(ls, v);
+ for (;;) {
+ switch (ls->t.token) {
+ case '.': { /* field */
+ field(ls, v);
+ break;
+ }
+ case '[': { /* `[' exp1 `]' */
+ expdesc key;
+ luaK_exp2anyreg(fs, v);
+ yindex(ls, &key);
+ luaK_indexed(fs, v, &key);
+ break;
+ }
+ case ':': { /* `:' NAME funcargs */
+ expdesc key;
+ luaX_next(ls);
+ checkname(ls, &key);
+ luaK_self(fs, v, &key);
+ funcargs(ls, v);
+ break;
+ }
+ case '(': case TK_STRING: case '{': { /* funcargs */
+ luaK_exp2nextreg(fs, v);
+ funcargs(ls, v);
+ break;
+ }
+ default: return;
+ }
+ }
+}
+
+
+static void simpleexp (LexState *ls, expdesc *v) {
+ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
+ constructor | FUNCTION body | primaryexp */
+ switch (ls->t.token) {
+ case TK_NUMBER: {
+ init_exp(v, VKNUM, 0);
+ v->u.nval = ls->t.seminfo.r;
+ break;
+ }
+ case TK_STRING: {
+ codestring(ls, v, ls->t.seminfo.ts);
+ break;
+ }
+ case TK_NIL: {
+ init_exp(v, VNIL, 0);
+ break;
+ }
+ case TK_TRUE: {
+ init_exp(v, VTRUE, 0);
+ break;
+ }
+ case TK_FALSE: {
+ init_exp(v, VFALSE, 0);
+ break;
+ }
+ case TK_DOTS: { /* vararg */
+ FuncState *fs = ls->fs;
+ check_condition(ls, fs->f->is_vararg,
+ "cannot use " LUA_QL("...") " outside a vararg function");
+ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
+ break;
+ }
+ case '{': { /* constructor */
+ constructor(ls, v);
+ return;
+ }
+ case TK_FUNCTION: {
+ luaX_next(ls);
+ body(ls, v, 0, ls->linenumber);
+ return;
+ }
+ default: {
+ primaryexp(ls, v);
+ return;
+ }
+ }
+ luaX_next(ls);
+}
+
+
+static UnOpr getunopr (int op) {
+ switch (op) {
+ case TK_NOT: return OPR_NOT;
+ case '-': return OPR_MINUS;
+ case '#': return OPR_LEN;
+ default: return OPR_NOUNOPR;
+ }
+}
+
+
+static BinOpr getbinopr (int op) {
+ switch (op) {
+ case '+': return OPR_ADD;
+ case '-': return OPR_SUB;
+ case '*': return OPR_MUL;
+ case '/': return OPR_DIV;
+ case '%': return OPR_MOD;
+ case '^': return OPR_POW;
+ case TK_CONCAT: return OPR_CONCAT;
+ case TK_NE: return OPR_NE;
+ case TK_EQ: return OPR_EQ;
+ case '<': return OPR_LT;
+ case TK_LE: return OPR_LE;
+ case '>': return OPR_GT;
+ case TK_GE: return OPR_GE;
+ case TK_AND: return OPR_AND;
+ case TK_OR: return OPR_OR;
+ default: return OPR_NOBINOPR;
+ }
+}
+
+
+static const struct {
+ lu_byte left; /* left priority for each binary operator */
+ lu_byte right; /* right priority */
+} priority[] = { /* ORDER OPR */
+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */
+ {10, 9}, {5, 4}, /* power and concat (right associative) */
+ {3, 3}, {3, 3}, /* equality and inequality */
+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
+ {2, 2}, {1, 1} /* logical (and/or) */
+};
+
+#define UNARY_PRIORITY 8 /* priority for unary operators */
+
+
+/*
+** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
+** where `binop' is any binary operator with a priority higher than `limit'
+*/
+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
+ BinOpr op;
+ UnOpr uop;
+ enterlevel(ls);
+ uop = getunopr(ls->t.token);
+ if (uop != OPR_NOUNOPR) {
+ luaX_next(ls);
+ subexpr(ls, v, UNARY_PRIORITY);
+ luaK_prefix(ls->fs, uop, v);
+ }
+ else simpleexp(ls, v);
+ /* expand while operators have priorities higher than `limit' */
+ op = getbinopr(ls->t.token);
+ while (op != OPR_NOBINOPR && priority[op].left > limit) {
+ expdesc v2;
+ BinOpr nextop;
+ luaX_next(ls);
+ luaK_infix(ls->fs, op, v);
+ /* read sub-expression with higher priority */
+ nextop = subexpr(ls, &v2, priority[op].right);
+ luaK_posfix(ls->fs, op, v, &v2);
+ op = nextop;
+ }
+ leavelevel(ls);
+ return op; /* return first untreated operator */
+}
+
+
+static void expr (LexState *ls, expdesc *v) {
+ subexpr(ls, v, 0);
+}
+
+/* }==================================================================== */
+
+
+
+/*
+** {======================================================================
+** Rules for Statements
+** =======================================================================
+*/
+
+
+static int block_follow (int token) {
+ switch (token) {
+ case TK_ELSE: case TK_ELSEIF: case TK_END:
+ case TK_UNTIL: case TK_EOS:
+ return 1;
+ default: return 0;
+ }
+}
+
+
+static void block (LexState *ls) {
+ /* block -> chunk */
+ FuncState *fs = ls->fs;
+ BlockCnt bl;
+ enterblock(fs, &bl, 0);
+ chunk(ls);
+ lua_assert(bl.breaklist == NO_JUMP);
+ leaveblock(fs);
+}
+
+
+/*
+** structure to chain all variables in the left-hand side of an
+** assignment
+*/
+struct LHS_assign {
+ struct LHS_assign *prev;
+ expdesc v; /* variable (global, local, upvalue, or indexed) */
+};
+
+
+/*
+** check whether, in an assignment to a local variable, the local variable
+** is needed in a previous assignment (to a table). If so, save original
+** local value in a safe place and use this safe copy in the previous
+** assignment.
+*/
+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
+ FuncState *fs = ls->fs;
+ int extra = fs->freereg; /* eventual position to save local variable */
+ int conflict = 0;
+ for (; lh; lh = lh->prev) {
+ if (lh->v.k == VINDEXED) {
+ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
+ conflict = 1;
+ lh->v.u.s.info = extra; /* previous assignment will use safe copy */
+ }
+ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */
+ conflict = 1;
+ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
+ }
+ }
+ }
+ if (conflict) {
+ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
+ expdesc e;
+ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
+ "syntax error");
+ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
+ struct LHS_assign nv;
+ nv.prev = lh;
+ primaryexp(ls, &nv.v);
+ if (nv.v.k == VLOCAL)
+ check_conflict(ls, lh, &nv.v);
+ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
+ "variables in assignment");
+ assignment(ls, &nv, nvars+1);
+ }
+ else { /* assignment -> `=' explist1 */
+ int nexps;
+ checknext(ls, '=');
+ nexps = explist1(ls, &e);
+ if (nexps != nvars) {
+ adjust_assign(ls, nvars, nexps, &e);
+ if (nexps > nvars)
+ ls->fs->freereg -= nexps - nvars; /* remove extra values */
+ }
+ else {
+ luaK_setoneret(ls->fs, &e); /* close last expression */
+ luaK_storevar(ls->fs, &lh->v, &e);
+ return; /* avoid default */
+ }
+ }
+ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
+ luaK_storevar(ls->fs, &lh->v, &e);
+}
+
+
+static int cond (LexState *ls) {
+ /* cond -> exp */
+ expdesc v;
+ expr(ls, &v); /* read condition */
+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ luaK_goiftrue(ls->fs, &v);
+ return v.f;
+}
+
+
+static void breakstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ BlockCnt *bl = fs->bl;
+ int upval = 0;
+ while (bl && !bl->isbreakable) {
+ upval |= bl->upval;
+ bl = bl->previous;
+ }
+ if (!bl)
+ luaX_syntaxerror(ls, "no loop to break");
+ if (upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+}
+
+
+static void whilestat (LexState *ls, int line) {
+ /* whilestat -> WHILE cond DO block END */
+ FuncState *fs = ls->fs;
+ int whileinit;
+ int condexit;
+ BlockCnt bl;
+ luaX_next(ls); /* skip WHILE */
+ whileinit = luaK_getlabel(fs);
+ condexit = cond(ls);
+ enterblock(fs, &bl, 1);
+ checknext(ls, TK_DO);
+ block(ls);
+ luaK_patchlist(fs, luaK_jump(fs), whileinit);
+ check_match(ls, TK_END, TK_WHILE, line);
+ leaveblock(fs);
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
+}
+
+
+static void repeatstat (LexState *ls, int line) {
+ /* repeatstat -> REPEAT block UNTIL cond */
+ int condexit;
+ FuncState *fs = ls->fs;
+ int repeat_init = luaK_getlabel(fs);
+ BlockCnt bl1, bl2;
+ enterblock(fs, &bl1, 1); /* loop block */
+ enterblock(fs, &bl2, 0); /* scope block */
+ luaX_next(ls); /* skip REPEAT */
+ chunk(ls);
+ check_match(ls, TK_UNTIL, TK_REPEAT, line);
+ condexit = cond(ls); /* read condition (inside scope block) */
+ if (!bl2.upval) { /* no upvalues? */
+ leaveblock(fs); /* finish scope */
+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
+ }
+ else { /* complete semantics when there are upvalues */
+ breakstat(ls); /* if condition then break */
+ luaK_patchtohere(ls->fs, condexit); /* else... */
+ leaveblock(fs); /* finish scope... */
+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
+ }
+ leaveblock(fs); /* finish loop */
+}
+
+
+static int exp1 (LexState *ls) {
+ expdesc e;
+ int k;
+ expr(ls, &e);
+ k = e.k;
+ luaK_exp2nextreg(ls->fs, &e);
+ return k;
+}
+
+
+static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
+ /* forbody -> DO block */
+ BlockCnt bl;
+ FuncState *fs = ls->fs;
+ int prep, endfor;
+ adjustlocalvars(ls, 3); /* control variables */
+ checknext(ls, TK_DO);
+ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
+ enterblock(fs, &bl, 0); /* scope for declared variables */
+ adjustlocalvars(ls, nvars);
+ luaK_reserveregs(fs, nvars);
+ block(ls);
+ leaveblock(fs); /* end of scope for declared variables */
+ luaK_patchtohere(fs, prep);
+ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
+ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
+}
+
+
+static void fornum (LexState *ls, TString *varname, int line) {
+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
+ FuncState *fs = ls->fs;
+ int base = fs->freereg;
+ new_localvarliteral(ls, "(for index)", 0);
+ new_localvarliteral(ls, "(for limit)", 1);
+ new_localvarliteral(ls, "(for step)", 2);
+ new_localvar(ls, varname, 3);
+ checknext(ls, '=');
+ exp1(ls); /* initial value */
+ checknext(ls, ',');
+ exp1(ls); /* limit */
+ if (testnext(ls, ','))
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base, line, 1, 1);
+}
+
+
+static void forlist (LexState *ls, TString *indexname) {
+ /* forlist -> NAME {,NAME} IN explist1 forbody */
+ FuncState *fs = ls->fs;
+ expdesc e;
+ int nvars = 0;
+ int line;
+ int base = fs->freereg;
+ /* create control variables */
+ new_localvarliteral(ls, "(for generator)", nvars++);
+ new_localvarliteral(ls, "(for state)", nvars++);
+ new_localvarliteral(ls, "(for control)", nvars++);
+ /* create declared variables */
+ new_localvar(ls, indexname, nvars++);
+ while (testnext(ls, ','))
+ new_localvar(ls, str_checkname(ls), nvars++);
+ checknext(ls, TK_IN);
+ line = ls->linenumber;
+ adjust_assign(ls, 3, explist1(ls, &e), &e);
+ luaK_checkstack(fs, 3); /* extra space to call generator */
+ forbody(ls, base, line, nvars - 3, 0);
+}
+
+
+static void forstat (LexState *ls, int line) {
+ /* forstat -> FOR (fornum | forlist) END */
+ FuncState *fs = ls->fs;
+ TString *varname;
+ BlockCnt bl;
+ enterblock(fs, &bl, 1); /* scope for loop and control variables */
+ luaX_next(ls); /* skip `for' */
+ varname = str_checkname(ls); /* first variable name */
+ switch (ls->t.token) {
+ case '=': fornum(ls, varname, line); break;
+ case ',': case TK_IN: forlist(ls, varname); break;
+ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
+ }
+ check_match(ls, TK_END, TK_FOR, line);
+ leaveblock(fs); /* loop scope (`break' jumps to this point) */
+}
+
+
+static int test_then_block (LexState *ls) {
+ /* test_then_block -> [IF | ELSEIF] cond THEN block */
+ int condexit;
+ luaX_next(ls); /* skip IF or ELSEIF */
+ condexit = cond(ls);
+ checknext(ls, TK_THEN);
+ block(ls); /* `then' part */
+ return condexit;
+}
+
+
+static void ifstat (LexState *ls, int line) {
+ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
+ FuncState *fs = ls->fs;
+ int flist;
+ int escapelist = NO_JUMP;
+ flist = test_then_block(ls); /* IF cond THEN block */
+ while (ls->t.token == TK_ELSEIF) {
+ luaK_concat(fs, &escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ flist = test_then_block(ls); /* ELSEIF cond THEN block */
+ }
+ if (ls->t.token == TK_ELSE) {
+ luaK_concat(fs, &escapelist, luaK_jump(fs));
+ luaK_patchtohere(fs, flist);
+ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */
+ block(ls); /* `else' part */
+ }
+ else
+ luaK_concat(fs, &escapelist, flist);
+ luaK_patchtohere(fs, escapelist);
+ check_match(ls, TK_END, TK_IF, line);
+}
+
+
+static void localfunc (LexState *ls) {
+ expdesc v, b;
+ FuncState *fs = ls->fs;
+ new_localvar(ls, str_checkname(ls), 0);
+ init_exp(&v, VLOCAL, fs->freereg);
+ luaK_reserveregs(fs, 1);
+ adjustlocalvars(ls, 1);
+ body(ls, &b, 0, ls->linenumber);
+ luaK_storevar(fs, &v, &b);
+ /* debug information will only see the variable after this point! */
+ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
+}
+
+
+static void localstat (LexState *ls) {
+ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
+ int nvars = 0;
+ int nexps;
+ expdesc e;
+ do {
+ new_localvar(ls, str_checkname(ls), nvars++);
+ } while (testnext(ls, ','));
+ if (testnext(ls, '='))
+ nexps = explist1(ls, &e);
+ else {
+ e.k = VVOID;
+ nexps = 0;
+ }
+ adjust_assign(ls, nvars, nexps, &e);
+ adjustlocalvars(ls, nvars);
+}
+
+
+static int funcname (LexState *ls, expdesc *v) {
+ /* funcname -> NAME {field} [`:' NAME] */
+ int needself = 0;
+ singlevar(ls, v);
+ while (ls->t.token == '.')
+ field(ls, v);
+ if (ls->t.token == ':') {
+ needself = 1;
+ field(ls, v);
+ }
+ return needself;
+}
+
+
+static void funcstat (LexState *ls, int line) {
+ /* funcstat -> FUNCTION funcname body */
+ int needself;
+ expdesc v, b;
+ luaX_next(ls); /* skip FUNCTION */
+ needself = funcname(ls, &v);
+ body(ls, &b, needself, line);
+ luaK_storevar(ls->fs, &v, &b);
+ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
+}
+
+
+static void exprstat (LexState *ls) {
+ /* stat -> func | assignment */
+ FuncState *fs = ls->fs;
+ struct LHS_assign v;
+ primaryexp(ls, &v.v);
+ if (v.v.k == VCALL) /* stat -> func */
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
+ else { /* stat -> assignment */
+ v.prev = NULL;
+ assignment(ls, &v, 1);
+ }
+}
+
+
+static void retstat (LexState *ls) {
+ /* stat -> RETURN explist */
+ FuncState *fs = ls->fs;
+ expdesc e;
+ int first, nret; /* registers with returned values */
+ luaX_next(ls); /* skip RETURN */
+ if (block_follow(ls->t.token) || ls->t.token == ';')
+ first = nret = 0; /* return no values */
+ else {
+ nret = explist1(ls, &e); /* optional return values */
+ if (hasmultret(e.k)) {
+ luaK_setmultret(fs, &e);
+ if (e.k == VCALL && nret == 1) { /* tail call? */
+ SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
+ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
+ }
+ first = fs->nactvar;
+ nret = LUA_MULTRET; /* return all values */
+ }
+ else {
+ if (nret == 1) /* only one single value? */
+ first = luaK_exp2anyreg(fs, &e);
+ else {
+ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
+ first = fs->nactvar; /* return all `active' values */
+ lua_assert(nret == fs->freereg - first);
+ }
+ }
+ }
+ luaK_ret(fs, first, nret);
+}
+
+
+static int statement (LexState *ls) {
+ int line = ls->linenumber; /* may be needed for error messages */
+ switch (ls->t.token) {
+ case TK_IF: { /* stat -> ifstat */
+ ifstat(ls, line);
+ return 0;
+ }
+ case TK_WHILE: { /* stat -> whilestat */
+ whilestat(ls, line);
+ return 0;
+ }
+ case TK_DO: { /* stat -> DO block END */
+ luaX_next(ls); /* skip DO */
+ block(ls);
+ check_match(ls, TK_END, TK_DO, line);
+ return 0;
+ }
+ case TK_FOR: { /* stat -> forstat */
+ forstat(ls, line);
+ return 0;
+ }
+ case TK_REPEAT: { /* stat -> repeatstat */
+ repeatstat(ls, line);
+ return 0;
+ }
+ case TK_FUNCTION: {
+ funcstat(ls, line); /* stat -> funcstat */
+ return 0;
+ }
+ case TK_LOCAL: { /* stat -> localstat */
+ luaX_next(ls); /* skip LOCAL */
+ if (testnext(ls, TK_FUNCTION)) /* local function? */
+ localfunc(ls);
+ else
+ localstat(ls);
+ return 0;
+ }
+ case TK_RETURN: { /* stat -> retstat */
+ retstat(ls);
+ return 1; /* must be last statement */
+ }
+ case TK_BREAK: { /* stat -> breakstat */
+ luaX_next(ls); /* skip BREAK */
+ breakstat(ls);
+ return 1; /* must be last statement */
+ }
+ default: {
+ exprstat(ls);
+ return 0; /* to avoid warnings */
+ }
+ }
+}
+
+
+static void chunk (LexState *ls) {
+ /* chunk -> { stat [`;'] } */
+ int islast = 0;
+ enterlevel(ls);
+ while (!islast && !block_follow(ls->t.token)) {
+ islast = statement(ls);
+ testnext(ls, ';');
+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
+ ls->fs->freereg >= ls->fs->nactvar);
+ ls->fs->freereg = ls->fs->nactvar; /* free registers */
+ }
+ leavelevel(ls);
+}
+
+/* }====================================================================== */
diff --git a/debian/grub-extras/lua/lparser.h b/debian/grub-extras/lua/lparser.h
new file mode 100644
index 0000000..18836af
--- /dev/null
+++ b/debian/grub-extras/lua/lparser.h
@@ -0,0 +1,82 @@
+/*
+** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua Parser
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lparser_h
+#define lparser_h
+
+#include "llimits.h"
+#include "lobject.h"
+#include "lzio.h"
+
+
+/*
+** Expression descriptor
+*/
+
+typedef enum {
+ VVOID, /* no value */
+ VNIL,
+ VTRUE,
+ VFALSE,
+ VK, /* info = index of constant in `k' */
+ VKNUM, /* nval = numerical value */
+ VLOCAL, /* info = local register */
+ VUPVAL, /* info = index of upvalue in `upvalues' */
+ VGLOBAL, /* info = index of table; aux = index of global name in `k' */
+ VINDEXED, /* info = table register; aux = index register (or `k') */
+ VJMP, /* info = instruction pc */
+ VRELOCABLE, /* info = instruction pc */
+ VNONRELOC, /* info = result register */
+ VCALL, /* info = instruction pc */
+ VVARARG /* info = instruction pc */
+} expkind;
+
+typedef struct expdesc {
+ expkind k;
+ union {
+ struct { int info, aux; } s;
+ lua_Number nval;
+ } u;
+ int t; /* patch list of `exit when true' */
+ int f; /* patch list of `exit when false' */
+} expdesc;
+
+
+typedef struct upvaldesc {
+ lu_byte k;
+ lu_byte info;
+} upvaldesc;
+
+
+struct BlockCnt; /* defined in lparser.c */
+
+
+/* state needed to generate code for a given function */
+typedef struct FuncState {
+ Proto *f; /* current function header */
+ Table *h; /* table to find (and reuse) elements in `k' */
+ struct FuncState *prev; /* enclosing function */
+ struct LexState *ls; /* lexical state */
+ struct lua_State *L; /* copy of the Lua state */
+ struct BlockCnt *bl; /* chain of current blocks */
+ int pc; /* next position to code (equivalent to `ncode') */
+ int lasttarget; /* `pc' of last `jump target' */
+ int jpc; /* list of pending jumps to `pc' */
+ int freereg; /* first free register */
+ int nk; /* number of elements in `k' */
+ int np; /* number of elements in `p' */
+ short nlocvars; /* number of elements in `locvars' */
+ lu_byte nactvar; /* number of active local variables */
+ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
+ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
+} FuncState;
+
+
+LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ const char *name);
+
+
+#endif
diff --git a/debian/grub-extras/lua/lstate.c b/debian/grub-extras/lua/lstate.c
new file mode 100644
index 0000000..2a7964a
--- /dev/null
+++ b/debian/grub-extras/lua/lstate.c
@@ -0,0 +1,213 @@
+/*
+** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+
+#include <stddef.h>
+
+#define lstate_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "llex.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE * sizeof (lua_State))
+#define fromstate(l) (cast(lua_State *, (l)) - LUAI_EXTRASPACE)
+#define tostate(l) (cast(lua_State *, cast(lua_State *, l) + LUAI_EXTRASPACE))
+
+
+/*
+** Main thread combines a thread state and the global state
+*/
+typedef struct LG {
+ lua_State l;
+ global_State g;
+} LG;
+
+
+
+static void stack_init (lua_State *L1, lua_State *L) {
+ /* initialize CallInfo array */
+ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
+ L1->ci = L1->base_ci;
+ L1->size_ci = BASIC_CI_SIZE;
+ L1->end_ci = L1->base_ci + L1->size_ci - 1;
+ /* initialize stack array */
+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
+ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
+ L1->top = L1->stack;
+ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
+ /* initialize first ci */
+ L1->ci->func = L1->top;
+ setnilvalue(L1->top++); /* `function' entry for this `ci' */
+ L1->base = L1->ci->base = L1->top;
+ L1->ci->top = L1->top + LUA_MINSTACK;
+}
+
+
+static void freestack (lua_State *L, lua_State *L1) {
+ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
+ luaM_freearray(L, L1->stack, L1->stacksize, TValue);
+}
+
+
+/*
+** open parts that may cause memory-allocation errors
+*/
+static void f_luaopen (lua_State *L, void *ud) {
+ global_State *g = G(L);
+ UNUSED(ud);
+ stack_init(L, L); /* init stack */
+ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
+ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
+ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
+ luaT_init(L);
+ luaX_init(L);
+ luaS_fix(luaS_newliteral(L, MEMERRMSG));
+ g->GCthreshold = 4*g->totalbytes;
+}
+
+
+static void preinit_state (lua_State *L, global_State *g) {
+ G(L) = g;
+ L->stack = NULL;
+ L->stacksize = 0;
+ L->errorJmp = NULL;
+ L->hook = NULL;
+ L->hookmask = 0;
+ L->basehookcount = 0;
+ L->allowhook = 1;
+ resethookcount(L);
+ L->openupval = NULL;
+ L->size_ci = 0;
+ L->nCcalls = L->baseCcalls = 0;
+ L->status = 0;
+ L->base_ci = L->ci = NULL;
+ L->savedpc = NULL;
+ L->errfunc = 0;
+ setnilvalue(gt(L));
+}
+
+
+static void close_state (lua_State *L) {
+ global_State *g = G(L);
+ luaF_close(L, L->stack); /* close all upvalues for this thread */
+ luaC_freeall(L); /* collect all objects */
+ lua_assert(g->rootgc == obj2gco(L));
+ lua_assert(g->strt.nuse == 0);
+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
+ luaZ_freebuffer(L, &g->buff);
+ freestack(L, L);
+ lua_assert(g->totalbytes == sizeof(LG));
+ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
+}
+
+
+lua_State *luaE_newthread (lua_State *L) {
+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
+ luaC_link(L, obj2gco(L1), LUA_TTHREAD);
+ preinit_state(L1, G(L));
+ stack_init(L1, L); /* init stack */
+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */
+ L1->hookmask = L->hookmask;
+ L1->basehookcount = L->basehookcount;
+ L1->hook = L->hook;
+ resethookcount(L1);
+ lua_assert(iswhite(obj2gco(L1)));
+ return L1;
+}
+
+
+void luaE_freethread (lua_State *L, lua_State *L1) {
+ luaF_close(L1, L1->stack); /* close all upvalues for this thread */
+ lua_assert(L1->openupval == NULL);
+ luai_userstatefree(L1);
+ freestack(L, L1);
+ luaM_freemem(L, fromstate(L1), state_size(lua_State));
+}
+
+
+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+ int i;
+ lua_State *L;
+ global_State *g;
+ void *l = (*f)(ud, NULL, 0, state_size(LG));
+ if (l == NULL) return NULL;
+ L = tostate(l);
+ g = &((LG *)L)->g;
+ L->next = NULL;
+ L->tt = LUA_TTHREAD;
+ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+ L->marked = luaC_white(g);
+ set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
+ preinit_state(L, g);
+ g->frealloc = f;
+ g->ud = ud;
+ g->mainthread = L;
+ g->uvhead.u.l.prev = &g->uvhead;
+ g->uvhead.u.l.next = &g->uvhead;
+ g->GCthreshold = 0; /* mark it as unfinished state */
+ g->strt.size = 0;
+ g->strt.nuse = 0;
+ g->strt.hash = NULL;
+ setnilvalue(registry(L));
+ luaZ_initbuffer(L, &g->buff);
+ g->panic = NULL;
+ g->gcstate = GCSpause;
+ g->rootgc = obj2gco(L);
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->tmudata = NULL;
+ g->totalbytes = sizeof(LG);
+ g->gcpause = LUAI_GCPAUSE;
+ g->gcstepmul = LUAI_GCMUL;
+ g->gcdept = 0;
+ for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
+ /* memory allocation error: free partial state */
+ close_state(L);
+ L = NULL;
+ }
+ else
+ luai_userstateopen(L);
+ return L;
+}
+
+
+static void callallgcTM (lua_State *L, void *ud) {
+ UNUSED(ud);
+ luaC_callGCTM(L); /* call GC metamethods for all udata */
+}
+
+
+LUA_API void lua_close (lua_State *L) {
+ L = G(L)->mainthread; /* only the main thread can be closed */
+ lua_lock(L);
+ luaF_close(L, L->stack); /* close all upvalues for this thread */
+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
+ L->errfunc = 0; /* no error function during GC metamethods */
+ do { /* repeat until no more errors */
+ L->ci = L->base_ci;
+ L->base = L->top = L->ci->base;
+ L->nCcalls = L->baseCcalls = 0;
+ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
+ lua_assert(G(L)->tmudata == NULL);
+ luai_userstateclose(L);
+ close_state(L);
+}
diff --git a/debian/grub-extras/lua/lstate.h b/debian/grub-extras/lua/lstate.h
new file mode 100644
index 0000000..3bc575b
--- /dev/null
+++ b/debian/grub-extras/lua/lstate.h
@@ -0,0 +1,169 @@
+/*
+** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstate_h
+#define lstate_h
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "ltm.h"
+#include "lzio.h"
+
+
+
+struct lua_longjmp; /* defined in ldo.c */
+
+
+/* table of globals */
+#define gt(L) (&L->l_gt)
+
+/* registry */
+#define registry(L) (&G(L)->l_registry)
+
+
+/* extra stack space to handle TM calls and some other extras */
+#define EXTRA_STACK 5
+
+
+#define BASIC_CI_SIZE 8
+
+#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
+
+
+
+typedef struct stringtable {
+ GCObject **hash;
+ lu_int32 nuse; /* number of elements */
+ int size;
+} stringtable;
+
+
+/*
+** informations about a call
+*/
+typedef struct CallInfo {
+ StkId base; /* base for this function */
+ StkId func; /* function index in the stack */
+ StkId top; /* top for this function */
+ const Instruction *savedpc;
+ int nresults; /* expected number of results from this function */
+ int tailcalls; /* number of tail calls lost under this entry */
+} CallInfo;
+
+
+
+#define curr_func(L) (clvalue(L->ci->func))
+#define ci_func(ci) (clvalue((ci)->func))
+#define f_isLua(ci) (!ci_func(ci)->c.isC)
+#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
+
+
+/*
+** `global state', shared by all threads of this state
+*/
+typedef struct global_State {
+ stringtable strt; /* hash table for strings */
+ lua_Alloc frealloc; /* function to reallocate memory */
+ void *ud; /* auxiliary data to `frealloc' */
+ lu_byte currentwhite;
+ lu_byte gcstate; /* state of garbage collector */
+ int sweepstrgc; /* position of sweep in `strt' */
+ GCObject *rootgc; /* list of all collectable objects */
+ GCObject **sweepgc; /* position of sweep in `rootgc' */
+ GCObject *gray; /* list of gray objects */
+ GCObject *grayagain; /* list of objects to be traversed atomically */
+ GCObject *weak; /* list of weak tables (to be cleared) */
+ GCObject *tmudata; /* last element of list of userdata to be GC */
+ Mbuffer buff; /* temporary buffer for string concatentation */
+ lu_mem GCthreshold;
+ lu_mem totalbytes; /* number of bytes currently allocated */
+ lu_mem estimate; /* an estimate of number of bytes actually in use */
+ lu_mem gcdept; /* how much GC is `behind schedule' */
+ int gcpause; /* size of pause between successive GCs */
+ int gcstepmul; /* GC `granularity' */
+ lua_CFunction panic; /* to be called in unprotected errors */
+ TValue l_registry;
+ struct lua_State *mainthread;
+ UpVal uvhead; /* head of double-linked list of all open upvalues */
+ struct Table *mt[NUM_TAGS]; /* metatables for basic types */
+ TString *tmname[TM_N]; /* array with tag-method names */
+} global_State;
+
+
+/*
+** `per thread' state
+*/
+struct lua_State {
+ CommonHeader;
+ lu_byte status;
+ StkId top; /* first free slot in the stack */
+ StkId base; /* base of current function */
+ global_State *l_G;
+ CallInfo *ci; /* call info for current function */
+ const Instruction *savedpc; /* `savedpc' of current function */
+ StkId stack_last; /* last free slot in the stack */
+ StkId stack; /* stack base */
+ CallInfo *end_ci; /* points after end of ci array*/
+ CallInfo *base_ci; /* array of CallInfo's */
+ int stacksize;
+ int size_ci; /* size of array `base_ci' */
+ unsigned short nCcalls; /* number of nested C calls */
+ unsigned short baseCcalls; /* nested C calls when resuming coroutine */
+ lu_byte hookmask;
+ lu_byte allowhook;
+ int basehookcount;
+ int hookcount;
+ lua_Hook hook;
+ TValue l_gt; /* table of globals */
+ TValue env; /* temporary place for environments */
+ GCObject *openupval; /* list of open upvalues in this stack */
+ GCObject *gclist;
+ struct lua_longjmp *errorJmp; /* current error recover point */
+ ptrdiff_t errfunc; /* current error handling function (stack index) */
+};
+
+
+#define G(L) (L->l_G)
+
+
+/*
+** Union of all collectable objects
+*/
+union GCObject {
+ GCheader gch;
+ union TString ts;
+ union Udata u;
+ union Closure cl;
+ struct Table h;
+ struct Proto p;
+ struct UpVal uv;
+ struct lua_State th; /* thread */
+};
+
+
+/* macros to convert a GCObject into a specific value */
+#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#define gco2ts(o) (&rawgco2ts(o)->tsv)
+#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
+#define gco2u(o) (&rawgco2u(o)->uv)
+#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
+#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
+#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define ngcotouv(o) \
+ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+
+/* macro to convert any Lua object into a GCObject */
+#define obj2gco(v) (cast(GCObject *, (v)))
+
+
+LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
+LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
+
+#endif
+
diff --git a/debian/grub-extras/lua/lstring.c b/debian/grub-extras/lua/lstring.c
new file mode 100644
index 0000000..bfdf190
--- /dev/null
+++ b/debian/grub-extras/lua/lstring.c
@@ -0,0 +1,112 @@
+/*
+** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
+** String table (keeps all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <string.h>
+#endif
+
+#define lstring_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+
+
+
+void luaS_resize (lua_State *L, int newsize) {
+ GCObject **newhash;
+ stringtable *tb;
+ int i;
+ if (G(L)->gcstate == GCSsweepstring)
+ return; /* cannot resize during GC traverse */
+ newhash = luaM_newvector(L, newsize, GCObject *);
+ tb = &G(L)->strt;
+ for (i=0; i<newsize; i++) newhash[i] = NULL;
+ /* rehash */
+ for (i=0; i<tb->size; i++) {
+ GCObject *p = tb->hash[i];
+ while (p) { /* for each node in the list */
+ GCObject *next = p->gch.next; /* save next */
+ unsigned int h = gco2ts(p)->hash;
+ int h1 = lmod(h, newsize); /* new position */
+ lua_assert(cast_int(h%newsize) == lmod(h, newsize));
+ p->gch.next = newhash[h1]; /* chain it */
+ newhash[h1] = p;
+ p = next;
+ }
+ }
+ luaM_freearray(L, tb->hash, tb->size, TString *);
+ tb->size = newsize;
+ tb->hash = newhash;
+}
+
+
+static TString *newlstr (lua_State *L, const char *str, size_t l,
+ unsigned int h) {
+ TString *ts;
+ stringtable *tb;
+ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+ luaM_toobig(L);
+ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
+ ts->tsv.len = l;
+ ts->tsv.hash = h;
+ ts->tsv.marked = luaC_white(G(L));
+ ts->tsv.tt = LUA_TSTRING;
+ ts->tsv.reserved = 0;
+ memcpy(ts+1, str, l*sizeof(char));
+ ((char *)(ts+1))[l] = '\0'; /* ending 0 */
+ tb = &G(L)->strt;
+ h = lmod(h, tb->size);
+ ts->tsv.next = tb->hash[h]; /* chain new entry */
+ tb->hash[h] = obj2gco(ts);
+ tb->nuse++;
+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
+ luaS_resize(L, tb->size*2); /* too crowded */
+ return ts;
+}
+
+
+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
+ GCObject *o;
+ unsigned int h = cast(unsigned int, l); /* seed */
+ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
+ size_t l1;
+ for (l1=l; l1>=step; l1-=step) /* compute hash */
+ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
+ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
+ o != NULL;
+ o = o->gch.next) {
+ TString *ts = rawgco2ts(o);
+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
+ /* string may be dead */
+ if (isdead(G(L), o)) changewhite(o);
+ return ts;
+ }
+ }
+ return newlstr(L, str, l, h); /* not found */
+}
+
+
+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
+ Udata *u;
+ if (s > MAX_SIZET - sizeof(Udata))
+ luaM_toobig(L);
+ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
+ u->uv.marked = luaC_white(G(L)); /* is not finalized */
+ u->uv.tt = LUA_TUSERDATA;
+ u->uv.len = s;
+ u->uv.metatable = NULL;
+ u->uv.env = e;
+ /* chain it on udata list (after main thread) */
+ u->uv.next = G(L)->mainthread->next;
+ G(L)->mainthread->next = obj2gco(u);
+ return u;
+}
+
diff --git a/debian/grub-extras/lua/lstring.h b/debian/grub-extras/lua/lstring.h
new file mode 100644
index 0000000..73a2ff8
--- /dev/null
+++ b/debian/grub-extras/lua/lstring.h
@@ -0,0 +1,31 @@
+/*
+** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $
+** String table (keep all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstring_h
+#define lstring_h
+
+
+#include "lgc.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
+
+#define sizeudata(u) (sizeof(union Udata)+(u)->len)
+
+#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
+#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
+ (sizeof(s)/sizeof(char))-1))
+
+#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
+
+LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+#endif
diff --git a/debian/grub-extras/lua/lstrlib.c b/debian/grub-extras/lua/lstrlib.c
new file mode 100644
index 0000000..c6bf0a4
--- /dev/null
+++ b/debian/grub-extras/lua/lstrlib.c
@@ -0,0 +1,874 @@
+/*
+** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $
+** Standard library for string operations and pattern-matching
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+/* macro to `unsign' a character */
+#define uchar(c) ((unsigned char)(c))
+
+
+
+static int str_len (lua_State *L) {
+ size_t l;
+ luaL_checklstring(L, 1, &l);
+ lua_pushinteger(L, l);
+ return 1;
+}
+
+
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
+ /* relative string position: negative means back from end */
+ if (pos < 0) pos += (ptrdiff_t)len + 1;
+ return (pos >= 0) ? pos : 0;
+}
+
+
+static int str_sub (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start <= end)
+ lua_pushlstring(L, s+start-1, end-start+1);
+ else lua_pushliteral(L, "");
+ return 1;
+}
+
+
+static int str_reverse (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ while (l--) luaL_addchar(&b, s[l]);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_lower (lua_State *L) {
+ size_t l;
+ size_t i;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ for (i=0; i<l; i++)
+ luaL_addchar(&b, tolower(uchar(s[i])));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_upper (lua_State *L) {
+ size_t l;
+ size_t i;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ for (i=0; i<l; i++)
+ luaL_addchar(&b, toupper(uchar(s[i])));
+ luaL_pushresult(&b);
+ return 1;
+}
+
+static int str_rep (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int n = luaL_checkint(L, 2);
+ luaL_buffinit(L, &b);
+ while (n-- > 0)
+ luaL_addlstring(&b, s, l);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int str_byte (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+ if (posi > pose) return 0; /* empty interval; return no values */
+ n = (int)(pose - posi + 1);
+ if (posi + n <= pose) /* overflow? */
+ luaL_error(L, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
+ for (i=0; i<n; i++)
+ lua_pushinteger(L, uchar(s[posi+i-1]));
+ return n;
+}
+
+
+static int str_char (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ for (i=1; i<=n; i++) {
+ int c = luaL_checkint(L, i);
+ luaL_argcheck(L, uchar(c) == c, i, "invalid value");
+ luaL_addchar(&b, uchar(c));
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static int writer (lua_State *L, const void* b, size_t size, void* B) {
+ (void)L;
+ luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+ return 0;
+}
+
+
+static int str_dump (lua_State *L) {
+ luaL_Buffer b;
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ luaL_buffinit(L,&b);
+ if (lua_dump(L, writer, &b) != 0)
+ luaL_error(L, "unable to dump given function");
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** PATTERN MATCHING
+** =======================================================
+*/
+
+
+#define CAP_UNFINISHED (-1)
+#define CAP_POSITION (-2)
+
+typedef struct MatchState {
+ const char *src_init; /* init of source string */
+ const char *src_end; /* end (`\0') of source string */
+ lua_State *L;
+ int level; /* total number of captures (finished or unfinished) */
+ struct {
+ const char *init;
+ ptrdiff_t len;
+ } capture[LUA_MAXCAPTURES];
+} MatchState;
+
+
+#define L_ESC '%'
+#define SPECIALS "^$*+?.([%-"
+
+
+static int check_capture (MatchState *ms, int l) {
+ l -= '1';
+ if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
+ return luaL_error(ms->L, "invalid capture index");
+ return l;
+}
+
+
+static int capture_to_close (MatchState *ms) {
+ int level = ms->level;
+ for (level--; level>=0; level--)
+ if (ms->capture[level].len == CAP_UNFINISHED) return level;
+ return luaL_error(ms->L, "invalid pattern capture");
+}
+
+
+static const char *classend (MatchState *ms, const char *p) {
+ switch (*p++) {
+ case L_ESC: {
+ if (*p == '\0')
+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+ return p+1;
+ }
+ case '[': {
+ if (*p == '^') p++;
+ do { /* look for a `]' */
+ if (*p == '\0')
+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ if (*(p++) == L_ESC && *p != '\0')
+ p++; /* skip escapes (e.g. `%]') */
+ } while (*p != ']');
+ return p+1;
+ }
+ default: {
+ return p;
+ }
+ }
+}
+
+
+static int match_class (int c, int cl) {
+ int res;
+ switch (tolower(cl)) {
+ case 'a' : res = isalpha(c); break;
+ case 'c' : res = iscntrl(c); break;
+ case 'd' : res = isdigit(c); break;
+ case 'l' : res = islower(c); break;
+ case 'p' : res = ispunct(c); break;
+ case 's' : res = isspace(c); break;
+ case 'u' : res = isupper(c); break;
+ case 'w' : res = isalnum(c); break;
+ case 'x' : res = isxdigit(c); break;
+ case 'z' : res = (c == 0); break;
+ default: return (cl == c);
+ }
+ return (islower(cl) ? res : !res);
+}
+
+
+static int matchbracketclass (int c, const char *p, const char *ec) {
+ int sig = 1;
+ if (*(p+1) == '^') {
+ sig = 0;
+ p++; /* skip the `^' */
+ }
+ while (++p < ec) {
+ if (*p == L_ESC) {
+ p++;
+ if (match_class(c, uchar(*p)))
+ return sig;
+ }
+ else if ((*(p+1) == '-') && (p+2 < ec)) {
+ p+=2;
+ if (uchar(*(p-2)) <= c && c <= uchar(*p))
+ return sig;
+ }
+ else if (uchar(*p) == c) return sig;
+ }
+ return !sig;
+}
+
+
+static int singlematch (int c, const char *p, const char *ep) {
+ switch (*p) {
+ case '.': return 1; /* matches any char */
+ case L_ESC: return match_class(c, uchar(*(p+1)));
+ case '[': return matchbracketclass(c, p, ep-1);
+ default: return (uchar(*p) == c);
+ }
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p);
+
+
+static const char *matchbalance (MatchState *ms, const char *s,
+ const char *p) {
+ if (*p == 0 || *(p+1) == 0)
+ luaL_error(ms->L, "unbalanced pattern");
+ if (*s != *p) return NULL;
+ else {
+ int b = *p;
+ int e = *(p+1);
+ int cont = 1;
+ while (++s < ms->src_end) {
+ if (*s == e) {
+ if (--cont == 0) return s+1;
+ }
+ else if (*s == b) cont++;
+ }
+ }
+ return NULL; /* string ends out of balance */
+}
+
+
+static const char *max_expand (MatchState *ms, const char *s,
+ const char *p, const char *ep) {
+ ptrdiff_t i = 0; /* counts maximum expand for item */
+ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
+ i++;
+ /* keeps trying to match with the maximum repetitions */
+ while (i>=0) {
+ const char *res = match(ms, (s+i), ep+1);
+ if (res) return res;
+ i--; /* else didn't match; reduce 1 repetition to try again */
+ }
+ return NULL;
+}
+
+
+static const char *min_expand (MatchState *ms, const char *s,
+ const char *p, const char *ep) {
+ for (;;) {
+ const char *res = match(ms, s, ep+1);
+ if (res != NULL)
+ return res;
+ else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
+ s++; /* try with one more repetition */
+ else return NULL;
+ }
+}
+
+
+static const char *start_capture (MatchState *ms, const char *s,
+ const char *p, int what) {
+ const char *res;
+ int level = ms->level;
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
+ ms->capture[level].init = s;
+ ms->capture[level].len = what;
+ ms->level = level+1;
+ if ((res=match(ms, s, p)) == NULL) /* match failed? */
+ ms->level--; /* undo capture */
+ return res;
+}
+
+
+static const char *end_capture (MatchState *ms, const char *s,
+ const char *p) {
+ int l = capture_to_close(ms);
+ const char *res;
+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */
+ if ((res = match(ms, s, p)) == NULL) /* match failed? */
+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
+ return res;
+}
+
+
+static const char *match_capture (MatchState *ms, const char *s, int l) {
+ size_t len;
+ l = check_capture(ms, l);
+ len = ms->capture[l].len;
+ if ((size_t)(ms->src_end-s) >= len &&
+ memcmp(ms->capture[l].init, s, len) == 0)
+ return s+len;
+ else return NULL;
+}
+
+
+static const char *match (MatchState *ms, const char *s, const char *p) {
+ init: /* using goto's to optimize tail recursion */
+ switch (*p) {
+ case '(': { /* start capture */
+ if (*(p+1) == ')') /* position capture? */
+ return start_capture(ms, s, p+2, CAP_POSITION);
+ else
+ return start_capture(ms, s, p+1, CAP_UNFINISHED);
+ }
+ case ')': { /* end capture */
+ return end_capture(ms, s, p+1);
+ }
+ case L_ESC: {
+ switch (*(p+1)) {
+ case 'b': { /* balanced string? */
+ s = matchbalance(ms, s, p+2);
+ if (s == NULL) return NULL;
+ p+=4; goto init; /* else return match(ms, s, p+4); */
+ }
+ case 'f': { /* frontier? */
+ const char *ep; char previous;
+ p += 2;
+ if (*p != '[')
+ luaL_error(ms->L, "missing " LUA_QL("[") " after "
+ LUA_QL("%%f") " in pattern");
+ ep = classend(ms, p); /* points to what is next */
+ previous = (s == ms->src_init) ? '\0' : *(s-1);
+ if (matchbracketclass(uchar(previous), p, ep-1) ||
+ !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
+ p=ep; goto init; /* else return match(ms, s, ep); */
+ }
+ default: {
+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
+ s = match_capture(ms, s, uchar(*(p+1)));
+ if (s == NULL) return NULL;
+ p+=2; goto init; /* else return match(ms, s, p+2) */
+ }
+ goto dflt; /* case default */
+ }
+ }
+ }
+ case '\0': { /* end of pattern */
+ return s; /* match succeeded */
+ }
+ case '$': {
+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
+ return (s == ms->src_end) ? s : NULL; /* check end of string */
+ else goto dflt;
+ }
+ default: dflt: { /* it is a pattern item */
+ const char *ep = classend(ms, p); /* points to what is next */
+ int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
+ switch (*ep) {
+ case '?': { /* optional */
+ const char *res;
+ if (m && ((res=match(ms, s+1, ep+1)) != NULL))
+ return res;
+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */
+ }
+ case '*': { /* 0 or more repetitions */
+ return max_expand(ms, s, p, ep);
+ }
+ case '+': { /* 1 or more repetitions */
+ return (m ? max_expand(ms, s+1, p, ep) : NULL);
+ }
+ case '-': { /* 0 or more repetitions (minimum) */
+ return min_expand(ms, s, p, ep);
+ }
+ default: {
+ if (!m) return NULL;
+ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
+ }
+ }
+ }
+ }
+}
+
+
+
+static const char *lmemfind (const char *s1, size_t l1,
+ const char *s2, size_t l2) {
+ if (l2 == 0) return s1; /* empty strings are everywhere */
+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */
+ else {
+ const char *init; /* to search for a `*s2' inside `s1' */
+ l2--; /* 1st char will be checked by `memchr' */
+ l1 = l1-l2; /* `s2' cannot be found after that */
+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
+ init++; /* 1st char is already checked */
+ if (memcmp(init, s2+1, l2) == 0)
+ return init-1;
+ else { /* correct `l1' and `s1' to try again */
+ l1 -= init-s1;
+ s1 = init;
+ }
+ }
+ return NULL; /* not found */
+ }
+}
+
+
+static void push_onecapture (MatchState *ms, int i, const char *s,
+ const char *e) {
+ if (i >= ms->level) {
+ if (i == 0) /* ms->level == 0, too */
+ lua_pushlstring(ms->L, s, e - s); /* add whole match */
+ else
+ luaL_error(ms->L, "invalid capture index");
+ }
+ else {
+ ptrdiff_t l = ms->capture[i].len;
+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+ if (l == CAP_POSITION)
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
+ else
+ lua_pushlstring(ms->L, ms->capture[i].init, l);
+ }
+}
+
+
+static int push_captures (MatchState *ms, const char *s, const char *e) {
+ int i;
+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
+ luaL_checkstack(ms->L, nlevels, "too many captures");
+ for (i = 0; i < nlevels; i++)
+ push_onecapture(ms, i, s, e);
+ return nlevels; /* number of strings pushed */
+}
+
+
+static int str_find_aux (lua_State *L, int find) {
+ size_t l1, l2;
+ const char *s = luaL_checklstring(L, 1, &l1);
+ const char *p = luaL_checklstring(L, 2, &l2);
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
+ /* do a plain search */
+ const char *s2 = lmemfind(s+init, l1-init, p, l2);
+ if (s2) {
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, s2-s+l2);
+ return 2;
+ }
+ }
+ else {
+ MatchState ms;
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ const char *s1=s+init;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+l1;
+ do {
+ const char *res;
+ ms.level = 0;
+ if ((res=match(&ms, s1, p)) != NULL) {
+ if (find) {
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
+ return push_captures(&ms, NULL, 0) + 2;
+ }
+ else
+ return push_captures(&ms, s1, res);
+ }
+ } while (s1++ < ms.src_end && !anchor);
+ }
+ lua_pushnil(L); /* not found */
+ return 1;
+}
+
+
+static int str_find (lua_State *L) {
+ return str_find_aux(L, 1);
+}
+
+
+static int str_match (lua_State *L) {
+ return str_find_aux(L, 0);
+}
+
+
+static int gmatch_aux (lua_State *L) {
+ MatchState ms;
+ size_t ls;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ const char *p = lua_tostring(L, lua_upvalueindex(2));
+ const char *src;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+ls;
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
+ src <= ms.src_end;
+ src++) {
+ const char *e;
+ ms.level = 0;
+ if ((e = match(&ms, src, p)) != NULL) {
+ lua_Integer newstart = e-s;
+ if (e == src) newstart++; /* empty match? go at least one position */
+ lua_pushinteger(L, newstart);
+ lua_replace(L, lua_upvalueindex(3));
+ return push_captures(&ms, src, e);
+ }
+ }
+ return 0; /* not found */
+}
+
+
+static int gmatch (lua_State *L) {
+ luaL_checkstring(L, 1);
+ luaL_checkstring(L, 2);
+ lua_settop(L, 2);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, gmatch_aux, 3);
+ return 1;
+}
+
+
+static int gfind_nodef (lua_State *L) {
+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
+ LUA_QL("string.gmatch"));
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ size_t l, i;
+ const char *news = lua_tolstring(ms->L, 3, &l);
+ for (i = 0; i < l; i++) {
+ if (news[i] != L_ESC)
+ luaL_addchar(b, news[i]);
+ else {
+ i++; /* skip ESC */
+ if (!isdigit(uchar(news[i])))
+ luaL_addchar(b, news[i]);
+ else if (news[i] == '0')
+ luaL_addlstring(b, s, e - s);
+ else {
+ push_onecapture(ms, news[i] - '1', s, e);
+ luaL_addvalue(b); /* add capture to accumulated result */
+ }
+ }
+ }
+}
+
+
+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ lua_State *L = ms->L;
+ switch (lua_type(L, 3)) {
+ case LUA_TNUMBER:
+ case LUA_TSTRING: {
+ add_s(ms, b, s, e);
+ return;
+ }
+ case LUA_TFUNCTION: {
+ int n;
+ lua_pushvalue(L, 3);
+ n = push_captures(ms, s, e);
+ lua_call(L, n, 1);
+ break;
+ }
+ case LUA_TTABLE: {
+ push_onecapture(ms, 0, s, e);
+ lua_gettable(L, 3);
+ break;
+ }
+ }
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, s, e - s); /* keep original text */
+ }
+ else if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
+}
+
+
+static int str_gsub (lua_State *L) {
+ size_t srcl;
+ const char *src = luaL_checklstring(L, 1, &srcl);
+ const char *p = luaL_checkstring(L, 2);
+ int tr = lua_type(L, 3);
+ int max_s = luaL_optint(L, 4, srcl+1);
+ int anchor = (*p == '^') ? (p++, 1) : 0;
+ int n = 0;
+ MatchState ms;
+ luaL_Buffer b;
+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
+ "string/function/table expected");
+ luaL_buffinit(L, &b);
+ ms.L = L;
+ ms.src_init = src;
+ ms.src_end = src+srcl;
+ while (n < max_s) {
+ const char *e;
+ ms.level = 0;
+ e = match(&ms, src, p);
+ if (e) {
+ n++;
+ add_value(&ms, &b, src, e);
+ }
+ if (e && e>src) /* non empty match? */
+ src = e; /* skip it */
+ else if (src < ms.src_end)
+ luaL_addchar(&b, *src++);
+ else break;
+ if (anchor) break;
+ }
+ luaL_addlstring(&b, src, ms.src_end-src);
+ luaL_pushresult(&b);
+ lua_pushinteger(L, n); /* number of substitutions */
+ return 2;
+}
+
+/* }====================================================== */
+
+
+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
+#define MAX_ITEM 512
+/* valid flags in a format specification */
+#define FLAGS "-+ #0"
+/*
+** maximum size of each format specification (such as '%-099.99d')
+** (+10 accounts for %99.99x plus margin of error)
+*/
+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+
+
+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ luaL_addchar(b, '"');
+ while (l--) {
+ switch (*s) {
+ case '"': case '\\': case '\n': {
+ luaL_addchar(b, '\\');
+ luaL_addchar(b, *s);
+ break;
+ }
+ case '\r': {
+ luaL_addlstring(b, "\\r", 2);
+ break;
+ }
+ case '\0': {
+ luaL_addlstring(b, "\\000", 4);
+ break;
+ }
+ default: {
+ luaL_addchar(b, *s);
+ break;
+ }
+ }
+ s++;
+ }
+ luaL_addchar(b, '"');
+}
+
+static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
+ const char *p = strfrmt;
+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
+ luaL_error(L, "invalid format (repeated flags)");
+ if (isdigit(uchar(*p))) p++; /* skip width */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ if (*p == '.') {
+ p++;
+ if (isdigit(uchar(*p))) p++; /* skip precision */
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
+ }
+ if (isdigit(uchar(*p)))
+ luaL_error(L, "invalid format (width or precision too long)");
+ *(form++) = '%';
+ strncpy(form, strfrmt, p - strfrmt + 1);
+ form += p - strfrmt + 1;
+ *form = '\0';
+ return p;
+}
+
+
+static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+ strcpy(form + l - 1, LUA_INTFRMLEN);
+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
+}
+
+
+static int str_format (lua_State *L) {
+ int arg = 1;
+ size_t sfl;
+ const char *strfrmt = luaL_checklstring(L, arg, &sfl);
+ const char *strfrmt_end = strfrmt+sfl;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (strfrmt < strfrmt_end) {
+ if (*strfrmt != L_ESC)
+ luaL_addchar(&b, *strfrmt++);
+ else if (*++strfrmt == L_ESC)
+ luaL_addchar(&b, *strfrmt++); /* %% */
+ else { /* format item */
+ char form[MAX_FORMAT]; /* to store the format (`%...') */
+ char buff[MAX_ITEM]; /* to store the formatted item */
+ arg++;
+ strfrmt = scanformat(L, strfrmt, form);
+ switch (*strfrmt++) {
+ case 'c': {
+ snprintf(buff, sizeof (buff), form, (int)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+ snprintf(buff, sizeof (buff), form,
+ (LUA_INTFRM_T)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen(form);
+ snprintf(buff, sizeof (buff), form,
+ (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
+ break;
+ }
+#if 0
+ case 'e': case 'E': case 'f':
+ case 'g': case 'G': {
+ snprintf(buff, sizeof (buff), form, (double)luaL_checknumber(L, arg));
+ break;
+ }
+#endif
+ case 'q': {
+ addquoted(L, &b, arg);
+ continue; /* skip the 'addsize' at the end */
+ }
+ case 's': {
+ size_t l;
+ const char *s = luaL_checklstring(L, arg, &l);
+ if (!strchr(form, '.') && l >= 100) {
+ /* no precision and string is too long to be formatted;
+ keep original string */
+ lua_pushvalue(L, arg);
+ luaL_addvalue(&b);
+ continue; /* skip the `addsize' at the end */
+ }
+ else {
+ snprintf(buff, sizeof (buff), form, s);
+ break;
+ }
+ }
+ default: { /* also treat cases `pnLlh' */
+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
+ LUA_QL("format"), *(strfrmt - 1));
+ }
+ }
+ luaL_addlstring(&b, buff, strlen(buff));
+ }
+ }
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+static const luaL_Reg strlib[] = {
+ {"byte", str_byte},
+ {"char", str_char},
+ {"dump", str_dump},
+ {"find", str_find},
+ {"format", str_format},
+ {"gfind", gfind_nodef},
+ {"gmatch", gmatch},
+ {"gsub", str_gsub},
+ {"len", str_len},
+ {"lower", str_lower},
+ {"match", str_match},
+ {"rep", str_rep},
+ {"reverse", str_reverse},
+ {"sub", str_sub},
+ {"upper", str_upper},
+ {NULL, NULL}
+};
+
+
+static void createmetatable (lua_State *L) {
+ lua_createtable(L, 0, 1); /* create metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2);
+ lua_setmetatable(L, -2); /* set string metatable */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* string library... */
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
+ lua_pop(L, 1); /* pop metatable */
+}
+
+
+/*
+** Open string library
+*/
+LUALIB_API int luaopen_string (lua_State *L) {
+ luaL_register(L, LUA_STRLIBNAME, strlib);
+#if defined(LUA_COMPAT_GFIND)
+ lua_getfield(L, -1, "gmatch");
+ lua_setfield(L, -2, "gfind");
+#endif
+ createmetatable(L);
+ return 1;
+}
+
diff --git a/debian/grub-extras/lua/ltable.c b/debian/grub-extras/lua/ltable.c
new file mode 100644
index 0000000..f6501f8
--- /dev/null
+++ b/debian/grub-extras/lua/ltable.c
@@ -0,0 +1,594 @@
+/*
+** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+
+/*
+** Implementation of tables (aka arrays, objects, or hash tables).
+** Tables keep its elements in two parts: an array part and a hash part.
+** Non-negative integer keys are all candidates to be kept in the array
+** part. The actual size of the array is the largest `n' such that at
+** least half the slots between 0 and n are in use.
+** Hash uses a mix of chained scatter table with Brent's variation.
+** A main invariant of these tables is that, if an element is not
+** in its main position (i.e. the `original' position that its hash gives
+** to it), then the colliding element is in its own main position.
+** Hence even when the load factor reaches 100%, performance remains good.
+*/
+
+#if 0
+#include <math.h>
+#include <string.h>
+#endif
+
+#define ltable_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstate.h"
+#include "ltable.h"
+
+
+/*
+** max size of array part is 2^MAXBITS
+*/
+#if LUAI_BITSINT > 26
+#define MAXBITS 26
+#else
+#define MAXBITS (LUAI_BITSINT-2)
+#endif
+
+#define MAXASIZE (1 << MAXBITS)
+
+
+#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
+
+#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+#define hashboolean(t,p) hashpow2(t, p)
+
+
+/*
+** for some types, it is better to avoid modulus by power of 2, as
+** they tend to have many 2 factors.
+*/
+#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
+
+
+#define hashpointer(t,p) hashmod(t, IntPoint(p))
+
+
+/*
+** number of ints inside a lua_Number
+*/
+#define numints cast_int(sizeof(lua_Number)/sizeof(int))
+
+
+
+#define dummynode (&dummynode_)
+
+static const Node dummynode_ = {
+ {{NULL}, LUA_TNIL}, /* value */
+ {{{NULL}, LUA_TNIL, NULL}} /* key */
+};
+
+
+/*
+** hash for lua_Numbers
+*/
+static Node *hashnum (const Table *t, lua_Number n) {
+ unsigned int a[numints];
+ int i;
+ if (luai_numeq(n, 0)) /* avoid problems with -0 */
+ return gnode(t, 0);
+ memcpy(a, &n, sizeof(a));
+ for (i = 1; i < numints; i++) a[0] += a[i];
+ return hashmod(t, a[0]);
+}
+
+
+
+/*
+** returns the `main' position of an element in a table (that is, the index
+** of its hash value)
+*/
+static Node *mainposition (const Table *t, const TValue *key) {
+ switch (ttype(key)) {
+ case LUA_TNUMBER:
+ return hashnum(t, nvalue(key));
+ case LUA_TSTRING:
+ return hashstr(t, rawtsvalue(key));
+ case LUA_TBOOLEAN:
+ return hashboolean(t, bvalue(key));
+ case LUA_TLIGHTUSERDATA:
+ return hashpointer(t, pvalue(key));
+ default:
+ return hashpointer(t, gcvalue(key));
+ }
+}
+
+
+/*
+** returns the index for `key' if `key' is an appropriate key to live in
+** the array part of the table, -1 otherwise.
+*/
+static int arrayindex (const TValue *key) {
+ if (ttisnumber(key)) {
+ lua_Number n = nvalue(key);
+ int k;
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), n))
+ return k;
+ }
+ return -1; /* `key' did not match some condition */
+}
+
+
+/*
+** returns the index of a `key' for table traversals. First goes all
+** elements in the array part, then elements in the hash part. The
+** beginning of a traversal is signalled by -1.
+*/
+static int findindex (lua_State *L, Table *t, StkId key) {
+ int i;
+ if (ttisnil(key)) return -1; /* first iteration */
+ i = arrayindex(key);
+ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
+ return i-1; /* yes; that's the index (corrected to C) */
+ else {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ /* key may be dead already, but it is ok to use it in `next' */
+ if (luaO_rawequalObj(key2tval(n), key) ||
+ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
+ gcvalue(gkey(n)) == gcvalue(key))) {
+ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
+ /* hash elements are numbered after array ones */
+ return i + t->sizearray;
+ }
+ else n = gnext(n);
+ } while (n);
+ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
+ return 0; /* to avoid warnings */
+ }
+}
+
+
+int luaH_next (lua_State *L, Table *t, StkId key) {
+ int i = findindex(L, t, key); /* find original element */
+ for (i++; i < t->sizearray; i++) { /* try first array part */
+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
+ setnvalue(key, cast_num(i+1));
+ setobj2s(L, key+1, &t->array[i]);
+ return 1;
+ }
+ }
+ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
+ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
+ setobj2s(L, key, key2tval(gnode(t, i)));
+ setobj2s(L, key+1, gval(gnode(t, i)));
+ return 1;
+ }
+ }
+ return 0; /* no more elements */
+}
+
+
+/*
+** {=============================================================
+** Rehash
+** ==============================================================
+*/
+
+
+static int computesizes (int nums[], int *narray) {
+ int i;
+ int twotoi; /* 2^i */
+ int a = 0; /* number of elements smaller than 2^i */
+ int na = 0; /* number of elements to go to array part */
+ int n = 0; /* optimal size for array part */
+ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
+ if (nums[i] > 0) {
+ a += nums[i];
+ if (a > twotoi/2) { /* more than half elements present? */
+ n = twotoi; /* optimal size (till now) */
+ na = a; /* all elements smaller than n will go to array part */
+ }
+ }
+ if (a == *narray) break; /* all elements already counted */
+ }
+ *narray = n;
+ lua_assert(*narray/2 <= na && na <= *narray);
+ return na;
+}
+
+
+static int countint (const TValue *key, int *nums) {
+ int k = arrayindex(key);
+ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+static int numusearray (const Table *t, int *nums) {
+ int lg;
+ int ttlg; /* 2^lg */
+ int ause = 0; /* summation of `nums' */
+ int i = 1; /* count to traverse all array keys */
+ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
+ int lc = 0; /* counter */
+ int lim = ttlg;
+ if (lim > t->sizearray) {
+ lim = t->sizearray; /* adjust upper limit */
+ if (i > lim)
+ break; /* no more elements to count */
+ }
+ /* count elements in range (2^(lg-1), 2^lg] */
+ for (; i <= lim; i++) {
+ if (!ttisnil(&t->array[i-1]))
+ lc++;
+ }
+ nums[lg] += lc;
+ ause += lc;
+ }
+ return ause;
+}
+
+
+static int numusehash (const Table *t, int *nums, int *pnasize) {
+ int totaluse = 0; /* total number of elements */
+ int ause = 0; /* summation of `nums' */
+ int i = sizenode(t);
+ while (i--) {
+ Node *n = &t->node[i];
+ if (!ttisnil(gval(n))) {
+ ause += countint(key2tval(n), nums);
+ totaluse++;
+ }
+ }
+ *pnasize += ause;
+ return totaluse;
+}
+
+
+static void setarrayvector (lua_State *L, Table *t, int size) {
+ int i;
+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
+ for (i=t->sizearray; i<size; i++)
+ setnilvalue(&t->array[i]);
+ t->sizearray = size;
+}
+
+
+static void setnodevector (lua_State *L, Table *t, int size) {
+ int lsize;
+ if (size == 0) { /* no elements to hash part? */
+ t->node = cast(Node *, dummynode); /* use common `dummynode' */
+ lsize = 0;
+ }
+ else {
+ int i;
+ lsize = ceillog2(size);
+ if (lsize > MAXBITS)
+ luaG_runerror(L, "table overflow");
+ size = twoto(lsize);
+ t->node = luaM_newvector(L, size, Node);
+ for (i=0; i<size; i++) {
+ Node *n = gnode(t, i);
+ gnext(n) = NULL;
+ setnilvalue(gkey(n));
+ setnilvalue(gval(n));
+ }
+ }
+ t->lsizenode = cast_byte(lsize);
+ t->lastfree = gnode(t, size); /* all positions are free */
+}
+
+
+static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
+ int i;
+ int oldasize = t->sizearray;
+ int oldhsize = t->lsizenode;
+ Node *nold = t->node; /* save old hash ... */
+ if (nasize > oldasize) /* array part must grow? */
+ setarrayvector(L, t, nasize);
+ /* create new hash part with appropriate size */
+ setnodevector(L, t, nhsize);
+ if (nasize < oldasize) { /* array part must shrink? */
+ t->sizearray = nasize;
+ /* re-insert elements from vanishing slice */
+ for (i=nasize; i<oldasize; i++) {
+ if (!ttisnil(&t->array[i]))
+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
+ }
+ /* shrink array */
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+ }
+ /* re-insert elements from hash part */
+ for (i = twoto(oldhsize) - 1; i >= 0; i--) {
+ Node *old = nold+i;
+ if (!ttisnil(gval(old)))
+ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
+ }
+ if (nold != dummynode)
+ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
+}
+
+
+void luaH_resizearray (lua_State *L, Table *t, int nasize) {
+ int nsize = (t->node == dummynode) ? 0 : sizenode(t);
+ resize(L, t, nasize, nsize);
+}
+
+
+static void rehash (lua_State *L, Table *t, const TValue *ek) {
+ int nasize, na;
+ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
+ int i;
+ int totaluse;
+ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
+ nasize = numusearray(t, nums); /* count keys in array part */
+ totaluse = nasize; /* all those keys are integer keys */
+ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
+ /* count extra key */
+ nasize += countint(ek, nums);
+ totaluse++;
+ /* compute new size for array part */
+ na = computesizes(nums, &nasize);
+ /* resize the table to new computed sizes */
+ resize(L, t, nasize, totaluse - na);
+}
+
+
+
+/*
+** }=============================================================
+*/
+
+
+Table *luaH_new (lua_State *L, int narray, int nhash) {
+ Table *t = luaM_new(L, Table);
+ luaC_link(L, obj2gco(t), LUA_TTABLE);
+ t->metatable = NULL;
+ t->flags = cast_byte(~0);
+ /* temporary values (kept only if some malloc fails) */
+ t->array = NULL;
+ t->sizearray = 0;
+ t->lsizenode = 0;
+ t->node = cast(Node *, dummynode);
+ setarrayvector(L, t, narray);
+ setnodevector(L, t, nhash);
+ return t;
+}
+
+
+void luaH_free (lua_State *L, Table *t) {
+ if (t->node != dummynode)
+ luaM_freearray(L, t->node, sizenode(t), Node);
+ luaM_freearray(L, t->array, t->sizearray, TValue);
+ luaM_free(L, t);
+}
+
+
+static Node *getfreepos (Table *t) {
+ while (t->lastfree-- > t->node) {
+ if (ttisnil(gkey(t->lastfree)))
+ return t->lastfree;
+ }
+ return NULL; /* could not find a free place */
+}
+
+
+
+/*
+** inserts a new key into a hash table; first, check whether key's main
+** position is free. If not, check whether colliding node is in its main
+** position or not: if it is not, move colliding node to an empty place and
+** put new key in its main position; otherwise (colliding node is in its main
+** position), new key goes to an empty position.
+*/
+static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
+ Node *mp = mainposition(t, key);
+ if (!ttisnil(gval(mp)) || mp == dummynode) {
+ Node *othern;
+ Node *n = getfreepos(t); /* get a free place */
+ if (n == NULL) { /* cannot find a free place? */
+ rehash(L, t, key); /* grow table */
+ return luaH_set(L, t, key); /* re-insert key into grown table */
+ }
+ lua_assert(n != dummynode);
+ othern = mainposition(t, key2tval(mp));
+ if (othern != mp) { /* is colliding node out of its main position? */
+ /* yes; move colliding node into free position */
+ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
+#if 0
+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+#else
+ memcpy (n, mp, sizeof (*n));
+#endif
+ gnext(mp) = NULL; /* now `mp' is free */
+ setnilvalue(gval(mp));
+ }
+ else { /* colliding node is in its own main position */
+ /* new node will go into free position */
+ gnext(n) = gnext(mp); /* chain new position */
+ gnext(mp) = n;
+ mp = n;
+ }
+ }
+ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
+ luaC_barriert(L, t, key);
+ lua_assert(ttisnil(gval(mp)));
+ return gval(mp);
+}
+
+
+/*
+** search function for integers
+*/
+const TValue *luaH_getnum (Table *t, int key) {
+ /* (1 <= key && key <= t->sizearray) */
+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+ return &t->array[key-1];
+ else {
+ lua_Number nk = cast_num(key);
+ Node *n = hashnum(t, nk);
+ do { /* check whether `key' is somewhere in the chain */
+ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
+}
+
+
+/*
+** search function for strings
+*/
+const TValue *luaH_getstr (Table *t, TString *key) {
+ Node *n = hashstr(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+}
+
+
+/*
+** main search function
+*/
+const TValue *luaH_get (Table *t, const TValue *key) {
+ switch (ttype(key)) {
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
+ case LUA_TNUMBER: {
+ int k;
+ lua_Number n = nvalue(key);
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+ return luaH_getnum(t, k); /* use specialized version */
+ /* else go through */
+ }
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(key2tval(n), key))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
+ }
+}
+
+
+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
+ const TValue *p = luaH_get(t, key);
+ t->flags = 0;
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+ else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+ luaG_runerror(L, "table index is NaN");
+ return newkey(L, t, key);
+ }
+}
+
+
+TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+ const TValue *p = luaH_getnum(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setnvalue(&k, cast_num(key));
+ return newkey(L, t, &k);
+ }
+}
+
+
+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
+ const TValue *p = luaH_getstr(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setsvalue(L, &k, key);
+ return newkey(L, t, &k);
+ }
+}
+
+
+static int unbound_search (Table *t, unsigned int j) {
+ unsigned int i = j; /* i is zero or a present index */
+ j++;
+ /* find `i' and `j' such that i is present and j is not */
+ while (!ttisnil(luaH_getnum(t, j))) {
+ i = j;
+ j *= 2;
+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+ i = 1;
+ while (!ttisnil(luaH_getnum(t, i))) i++;
+ return i - 1;
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(luaH_getnum(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+}
+
+
+/*
+** Try to find a boundary in table `t'. A `boundary' is an integer index
+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
+*/
+int luaH_getn (Table *t) {
+ unsigned int j = t->sizearray;
+ if (j > 0 && ttisnil(&t->array[j - 1])) {
+ /* there is a boundary in the array part: (binary) search for it */
+ unsigned int i = 0;
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(&t->array[m - 1])) j = m;
+ else i = m;
+ }
+ return i;
+ }
+ /* else must find a boundary in hash part */
+ else if (t->node == dummynode) /* hash part is empty? */
+ return j; /* that is easy... */
+ else return unbound_search(t, j);
+}
+
+
+
+#if defined(LUA_DEBUG)
+
+Node *luaH_mainposition (const Table *t, const TValue *key) {
+ return mainposition(t, key);
+}
+
+int luaH_isdummy (Node *n) { return n == dummynode; }
+
+#endif
diff --git a/debian/grub-extras/lua/ltable.h b/debian/grub-extras/lua/ltable.h
new file mode 100644
index 0000000..f5b9d5e
--- /dev/null
+++ b/debian/grub-extras/lua/ltable.h
@@ -0,0 +1,40 @@
+/*
+** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua tables (hash)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltable_h
+#define ltable_h
+
+#include "lobject.h"
+
+
+#define gnode(t,i) (&(t)->node[i])
+#define gkey(n) (&(n)->i_key.nk)
+#define gval(n) (&(n)->i_val)
+#define gnext(n) ((n)->i_key.nk.next)
+
+#define key2tval(n) (&(n)->i_key.tvk)
+
+
+LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
+LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
+LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
+LUAI_FUNC void luaH_free (lua_State *L, Table *t);
+LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
+LUAI_FUNC int luaH_getn (Table *t);
+
+
+#if defined(LUA_DEBUG)
+LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
+LUAI_FUNC int luaH_isdummy (Node *n);
+#endif
+
+
+#endif
diff --git a/debian/grub-extras/lua/ltablib.c b/debian/grub-extras/lua/ltablib.c
new file mode 100644
index 0000000..34a3467
--- /dev/null
+++ b/debian/grub-extras/lua/ltablib.c
@@ -0,0 +1,288 @@
+/*
+** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $
+** Library for Table Manipulation
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <stddef.h>
+#endif
+
+#define ltablib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
+
+
+static int foreachi (lua_State *L) {
+ int i;
+ int n = aux_getn(L, 1);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ for (i=1; i <= n; i++) {
+ lua_pushvalue(L, 2); /* function */
+ lua_pushinteger(L, i); /* 1st argument */
+ lua_rawgeti(L, 1, i); /* 2nd argument */
+ lua_call(L, 2, 1);
+ if (!lua_isnil(L, -1))
+ return 1;
+ lua_pop(L, 1); /* remove nil result */
+ }
+ return 0;
+}
+
+
+static int foreach (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pushvalue(L, 2); /* function */
+ lua_pushvalue(L, -3); /* key */
+ lua_pushvalue(L, -3); /* value */
+ lua_call(L, 2, 1);
+ if (!lua_isnil(L, -1))
+ return 1;
+ lua_pop(L, 2); /* remove value and result */
+ }
+ return 0;
+}
+
+
+static int maxn (lua_State *L) {
+ lua_Number max = 0;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pop(L, 1); /* remove value */
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ lua_Number v = lua_tonumber(L, -1);
+ if (v > max) max = v;
+ }
+ }
+ lua_pushnumber(L, max);
+ return 1;
+}
+
+
+static int getn (lua_State *L) {
+ lua_pushinteger(L, aux_getn(L, 1));
+ return 1;
+}
+
+
+static int setn (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+#ifndef luaL_setn
+ luaL_setn(L, 1, luaL_checkint(L, 2));
+#else
+ luaL_error(L, LUA_QL("setn") " is obsolete");
+#endif
+ lua_pushvalue(L, 1);
+ return 1;
+}
+
+
+static int tinsert (lua_State *L) {
+ int e = aux_getn(L, 1) + 1; /* first empty element */
+ int pos; /* where to insert new element */
+ switch (lua_gettop(L)) {
+ case 2: { /* called with only 2 arguments */
+ pos = e; /* insert new element at the end */
+ break;
+ }
+ case 3: {
+ int i;
+ pos = luaL_checkint(L, 2); /* 2nd argument is the position */
+ if (pos > e) e = pos; /* `grow' array if necessary */
+ for (i = e; i > pos; i--) { /* move up elements */
+ lua_rawgeti(L, 1, i-1);
+ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
+ }
+ break;
+ }
+ default: {
+ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
+ }
+ }
+ luaL_setn(L, 1, e); /* new size */
+ lua_rawseti(L, 1, pos); /* t[pos] = v */
+ return 0;
+}
+
+
+static int tremove (lua_State *L) {
+ int e = aux_getn(L, 1);
+ int pos = luaL_optint(L, 2, e);
+ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
+ return 0; /* nothing to remove */
+ luaL_setn(L, 1, e - 1); /* t.n = n-1 */
+ lua_rawgeti(L, 1, pos); /* result = t[pos] */
+ for ( ;pos<e; pos++) {
+ lua_rawgeti(L, 1, pos+1);
+ lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
+ }
+ lua_pushnil(L);
+ lua_rawseti(L, 1, e); /* t[e] = nil */
+ return 1;
+}
+
+
+static void addfield (lua_State *L, luaL_Buffer *b, int i) {
+ lua_rawgeti(L, 1, i);
+ if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid value (%s) at index %d in table for "
+ LUA_QL("concat"), luaL_typename(L, -1), i);
+ luaL_addvalue(b);
+}
+
+
+static int tconcat (lua_State *L) {
+ luaL_Buffer b;
+ size_t lsep;
+ int i, last;
+ const char *sep = luaL_optlstring(L, 2, "", &lsep);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i = luaL_optint(L, 3, 1);
+ last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
+ luaL_buffinit(L, &b);
+ for (; i < last; i++) {
+ addfield(L, &b, i);
+ luaL_addlstring(&b, sep, lsep);
+ }
+ if (i == last) /* add last value (if interval was not empty) */
+ addfield(L, &b, i);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
+
+/*
+** {======================================================
+** Quicksort
+** (based on `Algorithms in MODULA-3', Robert Sedgewick;
+** Addison-Wesley, 1993.)
+*/
+
+
+static void set2 (lua_State *L, int i, int j) {
+ lua_rawseti(L, 1, i);
+ lua_rawseti(L, 1, j);
+}
+
+static int sort_comp (lua_State *L, int a, int b) {
+ if (!lua_isnil(L, 2)) { /* function? */
+ int res;
+ lua_pushvalue(L, 2);
+ lua_pushvalue(L, a-1); /* -1 to compensate function */
+ lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
+ lua_call(L, 2, 1);
+ res = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+ }
+ else /* a < b? */
+ return lua_lessthan(L, a, b);
+}
+
+static void auxsort (lua_State *L, int l, int u) {
+ while (l < u) { /* for tail recursion */
+ int i, j;
+ /* sort elements a[l], a[(l+u)/2] and a[u] */
+ lua_rawgeti(L, 1, l);
+ lua_rawgeti(L, 1, u);
+ if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
+ set2(L, l, u); /* swap a[l] - a[u] */
+ else
+ lua_pop(L, 2);
+ if (u-l == 1) break; /* only 2 elements */
+ i = (l+u)/2;
+ lua_rawgeti(L, 1, i);
+ lua_rawgeti(L, 1, l);
+ if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
+ set2(L, i, l);
+ else {
+ lua_pop(L, 1); /* remove a[l] */
+ lua_rawgeti(L, 1, u);
+ if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
+ set2(L, i, u);
+ else
+ lua_pop(L, 2);
+ }
+ if (u-l == 2) break; /* only 3 elements */
+ lua_rawgeti(L, 1, i); /* Pivot */
+ lua_pushvalue(L, -1);
+ lua_rawgeti(L, 1, u-1);
+ set2(L, i, u-1);
+ /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
+ i = l; j = u-1;
+ for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
+ /* repeat ++i until a[i] >= P */
+ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
+ if (i>u) luaL_error(L, "invalid order function for sorting");
+ lua_pop(L, 1); /* remove a[i] */
+ }
+ /* repeat --j until a[j] <= P */
+ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
+ if (j<l) luaL_error(L, "invalid order function for sorting");
+ lua_pop(L, 1); /* remove a[j] */
+ }
+ if (j<i) {
+ lua_pop(L, 3); /* pop pivot, a[i], a[j] */
+ break;
+ }
+ set2(L, i, j);
+ }
+ lua_rawgeti(L, 1, u-1);
+ lua_rawgeti(L, 1, i);
+ set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
+ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
+ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
+ if (i-l < u-i) {
+ j=l; i=i-1; l=i+2;
+ }
+ else {
+ j=i+1; i=u; u=j-2;
+ }
+ auxsort(L, j, i); /* call recursively the smaller one */
+ } /* repeat the routine for the larger one */
+}
+
+static int sort (lua_State *L) {
+ int n = aux_getn(L, 1);
+ luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
+ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ lua_settop(L, 2); /* make sure there is two arguments */
+ auxsort(L, 1, n);
+ return 0;
+}
+
+/* }====================================================== */
+
+
+static const luaL_Reg tab_funcs[] = {
+ {"concat", tconcat},
+ {"foreach", foreach},
+ {"foreachi", foreachi},
+ {"getn", getn},
+ {"maxn", maxn},
+ {"insert", tinsert},
+ {"remove", tremove},
+ {"setn", setn},
+ {"sort", sort},
+ {NULL, NULL}
+};
+
+
+LUALIB_API int luaopen_table (lua_State *L) {
+ luaL_register(L, LUA_TABLIBNAME, tab_funcs);
+ return 1;
+}
+
diff --git a/debian/grub-extras/lua/ltm.c b/debian/grub-extras/lua/ltm.c
new file mode 100644
index 0000000..9ff53c7
--- /dev/null
+++ b/debian/grub-extras/lua/ltm.c
@@ -0,0 +1,76 @@
+/*
+** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <string.h>
+#endif
+
+#define ltm_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+
+
+
+const char *const luaT_typenames[] = {
+ "nil", "boolean", "userdata", "number",
+ "string", "table", "function", "userdata", "thread",
+ "proto", "upval"
+};
+
+
+void luaT_init (lua_State *L) {
+ static const char *const luaT_eventname[] = { /* ORDER TM */
+ "__index", "__newindex",
+ "__gc", "__mode", "__eq",
+ "__add", "__sub", "__mul", "__div", "__mod",
+ "__pow", "__unm", "__len", "__lt", "__le",
+ "__concat", "__call"
+ };
+ int i;
+ for (i=0; i<TM_N; i++) {
+ G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
+ luaS_fix(G(L)->tmname[i]); /* never collect these names */
+ }
+}
+
+
+/*
+** function to be used with macro "fasttm": optimized for absence of
+** tag methods
+*/
+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
+ const TValue *tm = luaH_getstr(events, ename);
+ lua_assert(event <= TM_EQ);
+ if (ttisnil(tm)) { /* no tag method? */
+ events->flags |= cast_byte(1u<<event); /* cache this fact */
+ return NULL;
+ }
+ else return tm;
+}
+
+
+const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
+ Table *mt;
+ switch (ttype(o)) {
+ case LUA_TTABLE:
+ mt = hvalue(o)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(o)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(o)];
+ }
+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+}
+
diff --git a/debian/grub-extras/lua/ltm.h b/debian/grub-extras/lua/ltm.h
new file mode 100644
index 0000000..64343b7
--- /dev/null
+++ b/debian/grub-extras/lua/ltm.h
@@ -0,0 +1,54 @@
+/*
+** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltm_h
+#define ltm_h
+
+
+#include "lobject.h"
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER TM"
+*/
+typedef enum {
+ TM_INDEX,
+ TM_NEWINDEX,
+ TM_GC,
+ TM_MODE,
+ TM_EQ, /* last tag method with `fast' access */
+ TM_ADD,
+ TM_SUB,
+ TM_MUL,
+ TM_DIV,
+ TM_MOD,
+ TM_POW,
+ TM_UNM,
+ TM_LEN,
+ TM_LT,
+ TM_LE,
+ TM_CONCAT,
+ TM_CALL,
+ TM_N /* number of elements in the enum */
+} TMS;
+
+
+
+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
+ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+
+#define fasttm(l,et,e) gfasttm(G(l), et, e)
+
+LUAI_DATA const char *const luaT_typenames[];
+
+
+LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
+LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
+ TMS event);
+LUAI_FUNC void luaT_init (lua_State *L);
+
+#endif
diff --git a/debian/grub-extras/lua/lua.h b/debian/grub-extras/lua/lua.h
new file mode 100644
index 0000000..91aa410
--- /dev/null
+++ b/debian/grub-extras/lua/lua.h
@@ -0,0 +1,388 @@
+/*
+** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
+** Lua - An Extensible Extension Language
+** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** See Copyright Notice at the end of this file
+*/
+
+
+#ifndef lua_h
+#define lua_h
+
+#include <stdarg.h>
+#include <stddef.h>
+
+
+#include "luaconf.h"
+
+
+#define LUA_VERSION "Lua 5.1"
+#define LUA_RELEASE "Lua 5.1.4"
+#define LUA_VERSION_NUM 501
+#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
+#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+/* mark for precompiled code (`<esc>Lua') */
+#define LUA_SIGNATURE "\033Lua"
+
+/* option for multiple returns in `lua_pcall' and `lua_call' */
+#define LUA_MULTRET (-1)
+
+
+/*
+** pseudo-indices
+*/
+#define LUA_REGISTRYINDEX (-10000)
+#define LUA_ENVIRONINDEX (-10001)
+#define LUA_GLOBALSINDEX (-10002)
+#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
+
+
+/* thread status; 0 is OK */
+#define LUA_YIELD 1
+#define LUA_ERRRUN 2
+#define LUA_ERRSYNTAX 3
+#define LUA_ERRMEM 4
+#define LUA_ERRERR 5
+
+
+typedef struct lua_State lua_State;
+
+typedef int (*lua_CFunction) (lua_State *L);
+
+
+/*
+** functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
+
+
+/*
+** prototype for memory-allocation functions
+*/
+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
+
+
+/*
+** basic types
+*/
+#define LUA_TNONE (-1)
+
+#define LUA_TNIL 0
+#define LUA_TBOOLEAN 1
+#define LUA_TLIGHTUSERDATA 2
+#define LUA_TNUMBER 3
+#define LUA_TSTRING 4
+#define LUA_TTABLE 5
+#define LUA_TFUNCTION 6
+#define LUA_TUSERDATA 7
+#define LUA_TTHREAD 8
+
+
+
+/* minimum Lua stack available to a C function */
+#define LUA_MINSTACK 20
+
+
+/*
+** generic extra include file
+*/
+#if defined(LUA_USER_H)
+#include LUA_USER_H
+#endif
+
+
+/* type of numbers in Lua */
+typedef LUA_NUMBER lua_Number;
+
+
+/* type for integer functions */
+typedef LUA_INTEGER lua_Integer;
+
+
+
+/*
+** state manipulation
+*/
+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
+LUA_API void (lua_close) (lua_State *L);
+LUA_API lua_State *(lua_newthread) (lua_State *L);
+
+LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
+
+
+/*
+** basic stack manipulation
+*/
+LUA_API int (lua_gettop) (lua_State *L);
+LUA_API void (lua_settop) (lua_State *L, int idx);
+LUA_API void (lua_pushvalue) (lua_State *L, int idx);
+LUA_API void (lua_remove) (lua_State *L, int idx);
+LUA_API void (lua_insert) (lua_State *L, int idx);
+LUA_API void (lua_replace) (lua_State *L, int idx);
+LUA_API int (lua_checkstack) (lua_State *L, int sz);
+
+LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
+
+
+/*
+** access functions (stack -> C)
+*/
+
+LUA_API int (lua_isnumber) (lua_State *L, int idx);
+LUA_API int (lua_isstring) (lua_State *L, int idx);
+LUA_API int (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int (lua_isuserdata) (lua_State *L, int idx);
+LUA_API int (lua_type) (lua_State *L, int idx);
+LUA_API const char *(lua_typename) (lua_State *L, int tp);
+
+LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
+LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
+LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
+
+LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
+LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
+LUA_API int (lua_toboolean) (lua_State *L, int idx);
+LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
+LUA_API size_t (lua_objlen) (lua_State *L, int idx);
+LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
+LUA_API void *(lua_touserdata) (lua_State *L, int idx);
+LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
+LUA_API const void *(lua_topointer) (lua_State *L, int idx);
+
+
+/*
+** push functions (C -> stack)
+*/
+LUA_API void (lua_pushnil) (lua_State *L);
+LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
+LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
+LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
+LUA_API void (lua_pushstring) (lua_State *L, const char *s);
+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
+ va_list argp);
+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
+LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
+LUA_API void (lua_pushboolean) (lua_State *L, int b);
+LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
+LUA_API int (lua_pushthread) (lua_State *L);
+
+
+/*
+** get functions (Lua -> stack)
+*/
+LUA_API void (lua_gettable) (lua_State *L, int idx);
+LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_rawget) (lua_State *L, int idx);
+LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
+LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
+LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
+LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
+LUA_API void (lua_getfenv) (lua_State *L, int idx);
+
+
+/*
+** set functions (stack -> Lua)
+*/
+LUA_API void (lua_settable) (lua_State *L, int idx);
+LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
+LUA_API void (lua_rawset) (lua_State *L, int idx);
+LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
+LUA_API int (lua_setfenv) (lua_State *L, int idx);
+
+
+/*
+** `load' and `call' functions (load and run Lua code)
+*/
+LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
+LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
+LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
+LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
+ const char *chunkname);
+
+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
+
+
+/*
+** coroutine functions
+*/
+LUA_API int (lua_yield) (lua_State *L, int nresults);
+LUA_API int (lua_resume) (lua_State *L, int narg);
+LUA_API int (lua_status) (lua_State *L);
+
+/*
+** garbage-collection function and options
+*/
+
+#define LUA_GCSTOP 0
+#define LUA_GCRESTART 1
+#define LUA_GCCOLLECT 2
+#define LUA_GCCOUNT 3
+#define LUA_GCCOUNTB 4
+#define LUA_GCSTEP 5
+#define LUA_GCSETPAUSE 6
+#define LUA_GCSETSTEPMUL 7
+
+LUA_API int (lua_gc) (lua_State *L, int what, int data);
+
+
+/*
+** miscellaneous functions
+*/
+
+LUA_API int (lua_error) (lua_State *L);
+
+LUA_API int (lua_next) (lua_State *L, int idx);
+
+LUA_API void (lua_concat) (lua_State *L, int n);
+
+LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define lua_pop(L,n) lua_settop(L, -(n)-1)
+
+#define lua_newtable(L) lua_createtable(L, 0, 0)
+
+#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
+
+#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
+
+#define lua_strlen(L,i) lua_objlen(L, (i))
+
+#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
+#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
+#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
+#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
+#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
+#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
+#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
+#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
+
+#define lua_pushliteral(L, s) \
+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+
+#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
+#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
+
+#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
+
+
+
+/*
+** compatibility macros and functions
+*/
+
+#define lua_open() luaL_newstate()
+
+#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
+
+#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
+
+#define lua_Chunkreader lua_Reader
+#define lua_Chunkwriter lua_Writer
+
+
+/* hack */
+LUA_API void lua_setlevel (lua_State *from, lua_State *to);
+
+
+/*
+** {======================================================================
+** Debug API
+** =======================================================================
+*/
+
+
+/*
+** Event codes
+*/
+#define LUA_HOOKCALL 0
+#define LUA_HOOKRET 1
+#define LUA_HOOKLINE 2
+#define LUA_HOOKCOUNT 3
+#define LUA_HOOKTAILRET 4
+
+
+/*
+** Event masks
+*/
+#define LUA_MASKCALL (1 << LUA_HOOKCALL)
+#define LUA_MASKRET (1 << LUA_HOOKRET)
+#define LUA_MASKLINE (1 << LUA_HOOKLINE)
+#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
+
+typedef struct lua_Debug lua_Debug; /* activation record */
+
+
+/* Functions to be called by the debuger in specific events */
+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API lua_Hook lua_gethook (lua_State *L);
+LUA_API int lua_gethookmask (lua_State *L);
+LUA_API int lua_gethookcount (lua_State *L);
+
+
+struct lua_Debug {
+ int event;
+ const char *name; /* (n) */
+ const char *namewhat; /* (n) `global', `local', `field', `method' */
+ const char *what; /* (S) `Lua', `C', `main', `tail' */
+ const char *source; /* (S) */
+ int currentline; /* (l) */
+ int nups; /* (u) number of upvalues */
+ int linedefined; /* (S) */
+ int lastlinedefined; /* (S) */
+ char short_src[LUA_IDSIZE]; /* (S) */
+ /* private part */
+ int i_ci; /* active function */
+};
+
+/* }====================================================================== */
+
+
+/******************************************************************************
+* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+
+#endif
diff --git a/debian/grub-extras/lua/luaconf.h b/debian/grub-extras/lua/luaconf.h
new file mode 100644
index 0000000..652e8d1
--- /dev/null
+++ b/debian/grub-extras/lua/luaconf.h
@@ -0,0 +1,846 @@
+/*
+** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $
+** Configuration file for Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lconfig_h
+#define lconfig_h
+
+#if 0
+#include <limits.h>
+#include <stddef.h>
+#endif
+
+#include "grub_lua.h"
+
+/*
+** ==================================================================
+** Search for "@@" to find all configurable definitions.
+** ===================================================================
+*/
+
+
+/*
+@@ LUA_ANSI controls the use of non-ansi features.
+** CHANGE it (define it) if you want Lua to avoid the use of any
+** non-ansi feature or library.
+*/
+#if defined(__STRICT_ANSI__)
+#define LUA_ANSI
+#endif
+
+
+#if !defined(LUA_ANSI) && defined(_WIN32)
+#define LUA_WIN
+#endif
+
+#if defined(LUA_USE_LINUX)
+#define LUA_USE_POSIX
+#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
+#define LUA_USE_READLINE /* needs some extra libraries */
+#endif
+
+#if defined(LUA_USE_MACOSX)
+#define LUA_USE_POSIX
+#define LUA_DL_DYLD /* does not need extra library */
+#endif
+
+
+
+/*
+@@ LUA_USE_POSIX includes all functionallity listed as X/Open System
+@* Interfaces Extension (XSI).
+** CHANGE it (define it) if your system is XSI compatible.
+*/
+#if 0
+#if defined(LUA_USE_POSIX)
+#define LUA_USE_MKSTEMP
+#define LUA_USE_ISATTY
+#define LUA_USE_POPEN
+#define LUA_USE_ULONGJMP
+#endif
+#endif
+
+/*
+@@ LUA_PATH and LUA_CPATH are the names of the environment variables that
+@* Lua check to set its paths.
+@@ LUA_INIT is the name of the environment variable that Lua
+@* checks for initialization code.
+** CHANGE them if you want different names.
+*/
+#define LUA_PATH "LUA_PATH"
+#define LUA_CPATH "LUA_CPATH"
+#define LUA_INIT "LUA_INIT"
+
+
+/*
+@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
+@* Lua libraries.
+@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
+@* C libraries.
+** CHANGE them if your machine has a non-conventional directory
+** hierarchy or if you want to install your libraries in
+** non-conventional directories.
+*/
+#if defined(_WIN32)
+/*
+** In Windows, any exclamation mark ('!') in the path is replaced by the
+** path of the directory of the executable file of the current process.
+*/
+#define LUA_LDIR "!\\lua\\"
+#define LUA_CDIR "!\\"
+#define LUA_PATH_DEFAULT \
+ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
+#define LUA_CPATH_DEFAULT \
+ ".\\?.dll;" ".\\?51.dll;" LUA_CDIR"?.dll;" LUA_CDIR"?51.dll;" LUA_CDIR"clibs\\?.dll;" LUA_CDIR"clibs\\?51.dll;" LUA_CDIR"loadall.dll;" LUA_CDIR"clibs\\loadall.dll"
+
+#else
+#define LUA_ROOT "/usr/local/"
+#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
+#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
+#define LUA_PATH_DEFAULT \
+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
+#define LUA_CPATH_DEFAULT \
+ "./?.so;" "./lib?51.so;" LUA_CDIR"?.so;" LUA_CDIR"lib?51.so;" LUA_CDIR"loadall.so"
+#endif
+
+
+/*
+@@ LUA_DIRSEP is the directory separator (for submodules).
+** CHANGE it if your machine does not use "/" as the directory separator
+** and is not Windows. (On Windows Lua automatically uses "\".)
+*/
+#if defined(_WIN32)
+#define LUA_DIRSEP "\\"
+#else
+#define LUA_DIRSEP "/"
+#endif
+
+
+/*
+@@ LUA_PATHSEP is the character that separates templates in a path.
+@@ LUA_PATH_MARK is the string that marks the substitution points in a
+@* template.
+@@ LUA_EXECDIR in a Windows path is replaced by the executable's
+@* directory.
+@@ LUA_IGMARK is a mark to ignore all before it when bulding the
+@* luaopen_ function name.
+** CHANGE them if for some reason your system cannot use those
+** characters. (E.g., if one of those characters is a common character
+** in file/directory names.) Probably you do not need to change them.
+*/
+#define LUA_PATHSEP ";"
+#define LUA_PATH_MARK "?"
+#define LUA_EXECDIR "!"
+#define LUA_IGMARK "-"
+
+
+/*
+@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+** machines, ptrdiff_t gives a good choice between int or long.)
+*/
+#define LUA_INTEGER ptrdiff_t
+
+
+/*
+@@ LUA_API is a mark for all core API functions.
+@@ LUALIB_API is a mark for all standard library functions.
+** CHANGE them if you need to define those functions in some special way.
+** For instance, if you want to create one Windows DLL with the core and
+** the libraries, you may want to use the following definition (define
+** LUA_BUILD_AS_DLL to get it).
+*/
+#if defined(LUA_BUILD_AS_DLL)
+
+#if defined(LUA_CORE) || defined(LUA_LIB)
+#define LUA_API __declspec(dllexport)
+#else
+#define LUA_API __declspec(dllimport)
+#endif
+
+#else
+
+#define LUA_API extern
+
+#endif
+
+/* more often than not the libs go together with the core */
+#define LUALIB_API LUA_API
+
+
+/*
+@@ LUAI_FUNC is a mark for all extern functions that are not to be
+@* exported to outside modules.
+@@ LUAI_DATA is a mark for all extern (const) variables that are not to
+@* be exported to outside modules.
+** CHANGE them if you need to mark them in some special way. Elf/gcc
+** (versions 3.2 and later) mark them as "hidden" to optimize access
+** when Lua is compiled as a shared library.
+*/
+#if defined(luaall_c)
+#define LUAI_FUNC static
+#define LUAI_DATA /* empty */
+
+#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
+ defined(__ELF__)
+#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
+#define LUAI_DATA LUAI_FUNC
+
+#else
+#define LUAI_FUNC extern
+#define LUAI_DATA extern
+#endif
+
+
+
+/*
+@@ LUA_QL describes how error messages quote program elements.
+** CHANGE it if you want a different appearance.
+*/
+#define LUA_QL(x) "'" x "'"
+#define LUA_QS LUA_QL("%s")
+
+
+/*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@* of a function in debug information.
+** CHANGE it if you want a different size.
+*/
+#define LUA_IDSIZE 60
+
+
+/*
+** {==================================================================
+** Stand-alone configuration
+** ===================================================================
+*/
+
+#if defined(lua_c) || defined(luaall_c)
+
+/*
+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+@* is, whether we're running lua interactively).
+** CHANGE it if you have a better definition for non-POSIX/non-Windows
+** systems.
+*/
+#if defined(LUA_USE_ISATTY)
+#include <unistd.h>
+#define lua_stdin_is_tty() isatty(0)
+#elif defined(LUA_WIN)
+#include <io.h>
+#include <stdio.h>
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+#else
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
+#endif
+
+
+/*
+@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
+** CHANGE them if you want different prompts. (You can also change the
+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
+*/
+#define LUA_PROMPT "> "
+#define LUA_PROMPT2 ">> "
+
+
+/*
+@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
+** CHANGE it if your stand-alone interpreter has a different name and
+** your system is not able to detect that name automatically.
+*/
+#define LUA_PROGNAME "lua"
+
+
+/*
+@@ LUA_MAXINPUT is the maximum length for an input line in the
+@* stand-alone interpreter.
+** CHANGE it if you need longer lines.
+*/
+#define LUA_MAXINPUT 512
+
+
+/*
+@@ lua_readline defines how to show a prompt and then read a line from
+@* the standard input.
+@@ lua_saveline defines how to "save" a read line in a "history".
+@@ lua_freeline defines how to free a line read by lua_readline.
+** CHANGE them if you want to improve this functionality (e.g., by using
+** GNU readline and history facilities).
+*/
+#if defined(LUA_USE_READLINE)
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
+#define lua_saveline(L,idx) \
+ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
+ add_history(lua_tostring(L, idx)); /* add it to history */
+#define lua_freeline(L,b) ((void)L, free(b))
+#else
+#define lua_readline(L,b,p) \
+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
+#define lua_saveline(L,idx) { (void)L; (void)idx; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
+#endif
+
+#endif
+
+/* }================================================================== */
+
+
+/*
+@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles
+@* as a percentage.
+** CHANGE it if you want the GC to run faster or slower (higher values
+** mean larger pauses which mean slower collection.) You can also change
+** this value dynamically.
+*/
+#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */
+
+
+/*
+@@ LUAI_GCMUL defines the default speed of garbage collection relative to
+@* memory allocation as a percentage.
+** CHANGE it if you want to change the granularity of the garbage
+** collection. (Higher values mean coarser collections. 0 represents
+** infinity, where each step performs a full collection.) You can also
+** change this value dynamically.
+*/
+#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
+
+
+
+/*
+@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.
+** CHANGE it (define it) if you want exact compatibility with the
+** behavior of setn/getn in Lua 5.0.
+*/
+#undef LUA_COMPAT_GETN
+
+/*
+@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.
+** CHANGE it to undefined as soon as you do not need a global 'loadlib'
+** function (the function is still available as 'package.loadlib').
+*/
+#undef LUA_COMPAT_LOADLIB
+
+/*
+@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.
+** CHANGE it to undefined as soon as your programs use only '...' to
+** access vararg parameters (instead of the old 'arg' table).
+*/
+#define LUA_COMPAT_VARARG
+
+/*
+@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.
+** CHANGE it to undefined as soon as your programs use 'math.fmod' or
+** the new '%' operator instead of 'math.mod'.
+*/
+#define LUA_COMPAT_MOD
+
+/*
+@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting
+@* facility.
+** CHANGE it to 2 if you want the old behaviour, or undefine it to turn
+** off the advisory error when nesting [[...]].
+*/
+#define LUA_COMPAT_LSTR 1
+
+/*
+@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.
+** CHANGE it to undefined as soon as you rename 'string.gfind' to
+** 'string.gmatch'.
+*/
+#define LUA_COMPAT_GFIND
+
+/*
+@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'
+@* behavior.
+** CHANGE it to undefined as soon as you replace to 'luaL_register'
+** your uses of 'luaL_openlib'
+*/
+#define LUA_COMPAT_OPENLIB
+
+
+
+/*
+@@ luai_apicheck is the assert macro used by the Lua-C API.
+** CHANGE luai_apicheck if you want Lua to perform some checks in the
+** parameters it gets from API calls. This may slow down the interpreter
+** a bit, but may be quite useful when debugging C code that interfaces
+** with Lua. A useful redefinition is to use assert.h.
+*/
+#if defined(LUA_USE_APICHECK)
+#include <assert.h>
+#define luai_apicheck(L,o) { (void)L; assert(o); }
+#else
+#define luai_apicheck(L,o) { (void)L; }
+#endif
+
+
+/*
+@@ LUAI_BITSINT defines the number of bits in an int.
+** CHANGE here if Lua cannot automatically detect the number of bits of
+** your machine. Probably you do not need to change this.
+*/
+/* avoid overflows in comparison */
+#if INT_MAX-20 < 32760
+#define LUAI_BITSINT 16
+#elif INT_MAX > 2147483640L
+/* int has at least 32 bits */
+#define LUAI_BITSINT 32
+#else
+#error "you must define LUA_BITSINT with number of bits in an integer"
+#endif
+
+
+/*
+@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+@@ LUAI_INT32 is an signed integer with at least 32 bits.
+@@ LUAI_UMEM is an unsigned integer big enough to count the total
+@* memory used by Lua.
+@@ LUAI_MEM is a signed integer big enough to count the total memory
+@* used by Lua.
+** CHANGE here if for some weird reason the default definitions are not
+** good enough for your machine. (The definitions in the 'else'
+** part always works, but may waste space on machines with 64-bit
+** longs.) Probably you do not need to change this.
+*/
+#if LUAI_BITSINT >= 32
+#define LUAI_UINT32 unsigned int
+#define LUAI_INT32 int
+#define LUAI_MAXINT32 INT_MAX
+#define LUAI_UMEM size_t
+#define LUAI_MEM ptrdiff_t
+#else
+/* 16-bit ints */
+#define LUAI_UINT32 unsigned long
+#define LUAI_INT32 long
+#define LUAI_MAXINT32 LONG_MAX
+#define LUAI_UMEM unsigned long
+#define LUAI_MEM long
+#endif
+
+
+/*
+@@ LUAI_MAXCALLS limits the number of nested calls.
+** CHANGE it if you need really deep recursive calls. This limit is
+** arbitrary; its only purpose is to stop infinite recursion before
+** exhausting memory.
+*/
+#define LUAI_MAXCALLS 20000
+
+
+/*
+@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
+@* can use.
+** CHANGE it if you need lots of (Lua) stack space for your C
+** functions. This limit is arbitrary; its only purpose is to stop C
+** functions to consume unlimited stack space. (must be smaller than
+** -LUA_REGISTRYINDEX)
+*/
+#define LUAI_MAXCSTACK 8000
+
+
+
+/*
+** {==================================================================
+** CHANGE (to smaller values) the following definitions if your system
+** has a small C stack. (Or you may want to change them to larger
+** values if your system has a large C stack and these limits are
+** too rigid for you.) Some of these constants control the size of
+** stack-allocated arrays used by the compiler or the interpreter, while
+** others limit the maximum number of recursive calls that the compiler
+** or the interpreter can perform. Values too large may cause a C stack
+** overflow for some forms of deep constructs.
+** ===================================================================
+*/
+
+
+/*
+@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and
+@* syntactical nested non-terminals in a program.
+*/
+#define LUAI_MAXCCALLS 200
+
+
+/*
+@@ LUAI_MAXVARS is the maximum number of local variables per function
+@* (must be smaller than 250).
+*/
+#define LUAI_MAXVARS 200
+
+
+/*
+@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
+@* (must be smaller than 250).
+*/
+#define LUAI_MAXUPVALUES 60
+
+
+/*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+*/
+#if 0
+#define LUAL_BUFFERSIZE BUFSIZ
+#else
+#define LUAL_BUFFERSIZE 512
+#endif
+
+/* }================================================================== */
+
+
+
+
+/*
+** {==================================================================
+@@ LUA_NUMBER is the type of numbers in Lua.
+** CHANGE the following definitions only if you want to build Lua
+** with a number type different from double. You may also need to
+** change lua_number2int & lua_number2integer.
+** ===================================================================
+*/
+
+#if 0
+#define LUA_NUMBER_DOUBLE
+#define LUA_NUMBER double
+
+/*
+@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+@* over a number.
+*/
+#define LUAI_UACNUMBER double
+#else
+
+#define LUA_NUMBER int
+#define LUAI_UACNUMBER int
+
+#endif
+
+/*
+@@ LUA_NUMBER_SCAN is the format for reading numbers.
+@@ LUA_NUMBER_FMT is the format for writing numbers.
+@@ lua_number2str converts a number to a string.
+@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+@@ lua_str2number converts a string to a number.
+*/
+#if 0
+#define LUA_NUMBER_SCAN "%lf"
+#define LUA_NUMBER_FMT "%.14g"
+#else
+#define LUA_NUMBER_SCAN "%d"
+#define LUA_NUMBER_FMT "%d"
+#endif
+#define lua_number2str(s,n) snprintf((s), LUAI_MAXNUMBER2STR, LUA_NUMBER_FMT, (n))
+#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+#define lua_str2number(s,p) strtod((s), (p))
+
+
+/*
+@@ The luai_num* macros define the primitive operations over numbers.
+*/
+#if defined(LUA_CORE)
+#if 0
+#include <math.h>
+#endif
+#define luai_numadd(a,b) ((a)+(b))
+#define luai_numsub(a,b) ((a)-(b))
+#define luai_nummul(a,b) ((a)*(b))
+#if 0
+#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
+#define luai_numpow(a,b) (pow(a,b))
+#else
+
+static inline LUA_NUMBER
+luai_numdiv (LUA_NUMBER a, LUA_NUMBER b)
+{
+ int neg = 0;
+ unsigned res;
+ if (a < 0)
+ {
+ a = -a;
+ neg = !neg;
+ }
+ if (b < 0)
+ {
+ b = -b;
+ neg = !neg;
+ }
+ res = (unsigned) a / (unsigned) b;
+ return neg ? -res : res;
+}
+
+static inline LUA_NUMBER
+luai_nummod (LUA_NUMBER a, LUA_NUMBER b)
+{
+ int neg = 0;
+ unsigned res;
+ if (a < 0)
+ {
+ a = -a;
+ neg = !neg;
+ }
+ if (b < 0)
+ {
+ b = -b;
+ neg = !neg;
+ }
+ res = (unsigned) a % (unsigned) b;
+ return neg ? -res : res;
+}
+
+static inline LUA_NUMBER
+luai_numpow (LUA_NUMBER a, LUA_NUMBER b)
+{
+ LUA_NUMBER c;
+
+ c = 1;
+ while (b > 0)
+ {
+ c *= a;
+ b--;
+ }
+
+ return c;
+}
+
+#endif
+#define luai_numunm(a) (-(a))
+#define luai_numeq(a,b) ((a)==(b))
+#define luai_numlt(a,b) ((a)<(b))
+#define luai_numle(a,b) ((a)<=(b))
+#define luai_numisnan(a) (!luai_numeq((a), (a)))
+#endif
+
+
+/*
+@@ lua_number2int is a macro to convert lua_Number to int.
+@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+** CHANGE them if you know a faster way to convert a lua_Number to
+** int (with any rounding method and without throwing errors) in your
+** system. In Pentium machines, a naive typecast from double to int
+** in C is extremely slow, so any alternative is worth trying.
+*/
+
+#if 0
+/* On a Pentium, resort to a trick */
+#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+ (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+
+/* On a Microsoft compiler, use assembler */
+#if defined(_MSC_VER)
+
+#define lua_number2int(i,d) __asm fld d __asm fistp i
+#define lua_number2integer(i,n) lua_number2int(i, n)
+
+/* the next trick should work on any Pentium, but sometimes clashes
+ with a DirectX idiosyncrasy */
+#else
+
+union luai_Cast { double l_d; long l_l; };
+#define lua_number2int(i,d) \
+ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+#define lua_number2integer(i,n) lua_number2int(i, n)
+
+#endif
+
+
+/* this option always works, but may be slow */
+#else
+#define lua_number2int(i,d) ((i)=(int)(d))
+#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
+
+#endif
+
+#else
+#define lua_number2int(i,d) ((i)=(int)(d))
+#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
+#endif
+
+/* }================================================================== */
+
+
+/*
+@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+** CHANGE it if your system requires alignments larger than double. (For
+** instance, if your system supports long doubles and they must be
+** aligned in 16-byte boundaries, then you should add long double in the
+** union.) Probably you do not need to change this.
+*/
+#define LUAI_USER_ALIGNMENT_T grub_properly_aligned_t
+
+
+/*
+@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.
+** CHANGE them if you prefer to use longjmp/setjmp even with C++
+** or if want/don't to use _longjmp/_setjmp instead of regular
+** longjmp/setjmp. By default, Lua handles errors with exceptions when
+** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
+** and with longjmp/setjmp otherwise.
+*/
+#if defined(__cplusplus)
+/* C++ exceptions */
+#define LUAI_THROW(L,c) throw(c)
+#define LUAI_TRY(L,c,a) try { a } catch(...) \
+ { if ((c)->status == 0) (c)->status = -1; }
+#define luai_jmpbuf int /* dummy variable */
+
+#elif defined(LUA_USE_ULONGJMP)
+/* in Unix, try _longjmp/_setjmp (more efficient) */
+#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
+#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
+#define luai_jmpbuf jmp_buf
+
+#else
+/* default handling with long jumps */
+#define LUAI_THROW(L,c) longjmp((c)->b, 1)
+#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
+#define luai_jmpbuf jmp_buf
+
+#endif
+
+
+/*
+@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern
+@* can do during pattern-matching.
+** CHANGE it if you need more captures. This limit is arbitrary.
+*/
+#define LUA_MAXCAPTURES 32
+
+
+/*
+@@ lua_tmpnam is the function that the OS library uses to create a
+@* temporary name.
+@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.
+** CHANGE them if you have an alternative to tmpnam (which is considered
+** insecure) or if you want the original tmpnam anyway. By default, Lua
+** uses tmpnam except when POSIX is available, where it uses mkstemp.
+*/
+#if defined(loslib_c) || defined(luaall_c)
+
+#if defined(LUA_USE_MKSTEMP)
+#include <unistd.h>
+#define LUA_TMPNAMBUFSIZE 32
+#define lua_tmpnam(b,e) { \
+ strcpy(b, "/tmp/lua_XXXXXX"); \
+ e = mkstemp(b); \
+ if (e != -1) close(e); \
+ e = (e == -1); }
+
+#else
+#define LUA_TMPNAMBUFSIZE L_tmpnam
+#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
+#endif
+
+#endif
+
+
+/*
+@@ lua_popen spawns a new process connected to the current one through
+@* the file streams.
+** CHANGE it if you have a way to implement it in your system.
+*/
+#if defined(LUA_USE_POPEN)
+
+#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
+#define lua_pclose(L,file) ((void)L, (pclose(file) != -1))
+
+#elif defined(LUA_WIN)
+
+#define lua_popen(L,c,m) ((void)L, _popen(c,m))
+#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
+
+#else
+
+#define lua_popen(L,c,m) ((void)((void)c, m), \
+ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
+#define lua_pclose(L,file) ((void)((void)L, file), 0)
+
+#endif
+
+/*
+@@ LUA_DL_* define which dynamic-library system Lua should use.
+** CHANGE here if Lua has problems choosing the appropriate
+** dynamic-library system for your platform (either Windows' DLL, Mac's
+** dyld, or Unix's dlopen). If your system is some kind of Unix, there
+** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for
+** it. To use dlopen you also need to adapt the src/Makefile (probably
+** adding -ldl to the linker options), so Lua does not select it
+** automatically. (When you change the makefile to add -ldl, you must
+** also add -DLUA_USE_DLOPEN.)
+** If you do not want any kind of dynamic library, undefine all these
+** options.
+** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
+*/
+#if 0
+#if defined(LUA_USE_DLOPEN)
+#define LUA_DL_DLOPEN
+#endif
+
+#if defined(LUA_WIN)
+#define LUA_DL_DLL
+#endif
+#endif
+
+/*
+@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
+@* (the data goes just *before* the lua_State pointer).
+** CHANGE (define) this if you really need that. This value must be
+** a multiple of the maximum alignment required for your machine.
+*/
+#define LUAI_EXTRASPACE 0
+
+
+/*
+@@ luai_userstate* allow user-specific actions on threads.
+** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
+** extra when a thread is created/deleted/resumed/yielded.
+*/
+#define luai_userstateopen(L) ((void)L)
+#define luai_userstateclose(L) ((void)L)
+#define luai_userstatethread(L,L1) ((void)L)
+#define luai_userstatefree(L) ((void)L)
+#define luai_userstateresume(L,n) ((void)L)
+#define luai_userstateyield(L,n) ((void)L)
+
+
+/*
+@@ LUA_INTFRMLEN is the length modifier for integer conversions
+@* in 'string.format'.
+@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+@* modifier.
+** CHANGE them if your system supports long long or does not support long.
+*/
+
+#if defined(LUA_USELONGLONG)
+
+#define LUA_INTFRMLEN "ll"
+#define LUA_INTFRM_T long long
+
+#else
+
+#define LUA_INTFRMLEN "l"
+#define LUA_INTFRM_T long
+
+#endif
+
+
+
+/* =================================================================== */
+
+/*
+** Local configuration. You can use this space to add your redefinitions
+** without modifying the main part of the file.
+*/
+
+
+
+#endif
diff --git a/debian/grub-extras/lua/lualib.h b/debian/grub-extras/lua/lualib.h
new file mode 100644
index 0000000..e9ff9ba
--- /dev/null
+++ b/debian/grub-extras/lua/lualib.h
@@ -0,0 +1,53 @@
+/*
+** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua standard libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lualib_h
+#define lualib_h
+
+#include "lua.h"
+
+
+/* Key to file-handle type */
+#define LUA_FILEHANDLE "FILE*"
+
+
+#define LUA_COLIBNAME "coroutine"
+LUALIB_API int (luaopen_base) (lua_State *L);
+
+#define LUA_TABLIBNAME "table"
+LUALIB_API int (luaopen_table) (lua_State *L);
+
+#define LUA_IOLIBNAME "io"
+LUALIB_API int (luaopen_io) (lua_State *L);
+
+#define LUA_OSLIBNAME "os"
+LUALIB_API int (luaopen_os) (lua_State *L);
+
+#define LUA_STRLIBNAME "string"
+LUALIB_API int (luaopen_string) (lua_State *L);
+
+#define LUA_MATHLIBNAME "math"
+LUALIB_API int (luaopen_math) (lua_State *L);
+
+#define LUA_DBLIBNAME "debug"
+LUALIB_API int (luaopen_debug) (lua_State *L);
+
+#define LUA_LOADLIBNAME "package"
+LUALIB_API int (luaopen_package) (lua_State *L);
+
+
+/* open all previous libraries */
+LUALIB_API void (luaL_openlibs) (lua_State *L);
+
+
+
+#ifndef lua_assert
+#define lua_assert(x) ((void)0)
+#endif
+
+
+#endif
diff --git a/debian/grub-extras/lua/lundump.c b/debian/grub-extras/lua/lundump.c
new file mode 100644
index 0000000..637d842
--- /dev/null
+++ b/debian/grub-extras/lua/lundump.c
@@ -0,0 +1,229 @@
+/*
+** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <string.h>
+#endif
+
+#define lundump_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstring.h"
+#include "lundump.h"
+#include "lzio.h"
+
+typedef struct {
+ lua_State* L;
+ ZIO* Z;
+ Mbuffer* b;
+ const char* name;
+} LoadState;
+
+#ifdef LUAC_TRUST_BINARIES
+#define IF(c,s)
+#define error(S,s)
+#else
+#define IF(c,s) if (c) error(S,s)
+
+static void error(LoadState* S, const char* why)
+{
+ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
+ luaD_throw(S->L,LUA_ERRSYNTAX);
+}
+#endif
+
+#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
+#define LoadByte(S) (lu_byte)LoadChar(S)
+#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
+#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
+
+static void LoadBlock(LoadState* S, void* b, size_t size)
+{
+ size_t r=luaZ_read(S->Z,b,size);
+ IF (r!=0, "unexpected end");
+}
+
+static int LoadChar(LoadState* S)
+{
+ char x;
+ LoadVar(S,x);
+ return x;
+}
+
+static int LoadInt(LoadState* S)
+{
+ int x;
+ LoadVar(S,x);
+ IF (x<0, "bad integer");
+ return x;
+}
+
+static lua_Number LoadNumber(LoadState* S)
+{
+ lua_Number x;
+ LoadVar(S,x);
+ return x;
+}
+
+static TString* LoadString(LoadState* S)
+{
+ size_t size;
+ LoadVar(S,size);
+ if (size==0)
+ return NULL;
+ else
+ {
+ char* s=luaZ_openspace(S->L,S->b,size);
+ LoadBlock(S,s,size);
+ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
+ }
+}
+
+static void LoadCode(LoadState* S, Proto* f)
+{
+ int n=LoadInt(S);
+ f->code=luaM_newvector(S->L,n,Instruction);
+ f->sizecode=n;
+ LoadVector(S,f->code,n,sizeof(Instruction));
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p);
+
+static void LoadConstants(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->k=luaM_newvector(S->L,n,TValue);
+ f->sizek=n;
+ for (i=0; i<n; i++) setnilvalue(&f->k[i]);
+ for (i=0; i<n; i++)
+ {
+ TValue* o=&f->k[i];
+ int t=LoadChar(S);
+ switch (t)
+ {
+ case LUA_TNIL:
+ setnilvalue(o);
+ break;
+ case LUA_TBOOLEAN:
+ setbvalue(o,LoadChar(S)!=0);
+ break;
+ case LUA_TNUMBER:
+ setnvalue(o,LoadNumber(S));
+ break;
+ case LUA_TSTRING:
+ setsvalue2n(S->L,o,LoadString(S));
+ break;
+ default:
+ error(S,"bad constant");
+ break;
+ }
+ }
+ n=LoadInt(S);
+ f->p=luaM_newvector(S->L,n,Proto*);
+ f->sizep=n;
+ for (i=0; i<n; i++) f->p[i]=NULL;
+ for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
+}
+
+static void LoadDebug(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->lineinfo=luaM_newvector(S->L,n,int);
+ f->sizelineinfo=n;
+ LoadVector(S,f->lineinfo,n,sizeof(int));
+ n=LoadInt(S);
+ f->locvars=luaM_newvector(S->L,n,LocVar);
+ f->sizelocvars=n;
+ for (i=0; i<n; i++) f->locvars[i].varname=NULL;
+ for (i=0; i<n; i++)
+ {
+ f->locvars[i].varname=LoadString(S);
+ f->locvars[i].startpc=LoadInt(S);
+ f->locvars[i].endpc=LoadInt(S);
+ }
+ n=LoadInt(S);
+ f->upvalues=luaM_newvector(S->L,n,TString*);
+ f->sizeupvalues=n;
+ for (i=0; i<n; i++) f->upvalues[i]=NULL;
+ for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p)
+{
+ Proto* f;
+ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
+ f=luaF_newproto(S->L);
+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
+ f->source=LoadString(S); if (f->source==NULL) f->source=p;
+ f->linedefined=LoadInt(S);
+ f->lastlinedefined=LoadInt(S);
+ f->nups=LoadByte(S);
+ f->numparams=LoadByte(S);
+ f->is_vararg=LoadByte(S);
+ f->maxstacksize=LoadByte(S);
+ LoadCode(S,f);
+ LoadConstants(S,f);
+ LoadDebug(S,f);
+ IF (!luaG_checkcode(f), "bad code");
+ S->L->top--;
+ S->L->nCcalls--;
+ return f;
+}
+
+static void LoadHeader(LoadState* S)
+{
+ char h[LUAC_HEADERSIZE];
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+}
+
+/*
+** load precompiled chunk
+*/
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
+{
+ LoadState S;
+ if (*name=='@' || *name=='=')
+ S.name=name+1;
+ else if (*name==LUA_SIGNATURE[0])
+ S.name="binary string";
+ else
+ S.name=name;
+ S.L=L;
+ S.Z=Z;
+ S.b=buff;
+ LoadHeader(&S);
+ return LoadFunction(&S,luaS_newliteral(L,"=?"));
+}
+
+/*
+* make header
+*/
+void luaU_header (char* h)
+{
+ int x=1;
+ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
+ h+=sizeof(LUA_SIGNATURE)-1;
+ *h++=(char)LUAC_VERSION;
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+ *h++=(char)sizeof(size_t);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
+}
diff --git a/debian/grub-extras/lua/lundump.h b/debian/grub-extras/lua/lundump.h
new file mode 100644
index 0000000..c80189d
--- /dev/null
+++ b/debian/grub-extras/lua/lundump.h
@@ -0,0 +1,36 @@
+/*
+** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lundump_h
+#define lundump_h
+
+#include "lobject.h"
+#include "lzio.h"
+
+/* load one chunk; from lundump.c */
+LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
+
+/* make header; from lundump.c */
+LUAI_FUNC void luaU_header (char* h);
+
+/* dump one chunk; from ldump.c */
+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+
+#ifdef luac_c
+/* print one chunk; from print.c */
+LUAI_FUNC void luaU_print (const Proto* f, int full);
+#endif
+
+/* for header of binary files -- this is Lua 5.1 */
+#define LUAC_VERSION 0x51
+
+/* for header of binary files -- this is the official format */
+#define LUAC_FORMAT 0
+
+/* size of header of binary files */
+#define LUAC_HEADERSIZE 12
+
+#endif
diff --git a/debian/grub-extras/lua/lvm.c b/debian/grub-extras/lua/lvm.c
new file mode 100644
index 0000000..0ff1fa0
--- /dev/null
+++ b/debian/grub-extras/lua/lvm.c
@@ -0,0 +1,764 @@
+/*
+** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define lvm_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "ltm.h"
+#include "lvm.h"
+
+
+
+/* limit for table tag-method chains (to avoid loops) */
+#define MAXTAGLOOP 100
+
+
+const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+ lua_Number num;
+ if (ttisnumber(obj)) return obj;
+ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+ setnvalue(n, num);
+ return n;
+ }
+ else
+ return NULL;
+}
+
+
+int luaV_tostring (lua_State *L, StkId obj) {
+ if (!ttisnumber(obj))
+ return 0;
+ else {
+ char s[LUAI_MAXNUMBER2STR];
+ lua_Number n = nvalue(obj);
+ lua_number2str(s, n);
+ setsvalue2s(L, obj, luaS_new(L, s));
+ return 1;
+ }
+}
+
+
+static void traceexec (lua_State *L, const Instruction *pc) {
+ lu_byte mask = L->hookmask;
+ const Instruction *oldpc = L->savedpc;
+ L->savedpc = pc;
+ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
+ resethookcount(L);
+ luaD_callhook(L, LUA_HOOKCOUNT, -1);
+ }
+ if (mask & LUA_MASKLINE) {
+ Proto *p = ci_func(L->ci)->l.p;
+ int npc = pcRel(pc, p);
+ int newline = getline(p, npc);
+ /* call linehook when enter a new function, when jump back (loop),
+ or when enter a new line */
+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
+ luaD_callhook(L, LUA_HOOKLINE, newline);
+ }
+}
+
+
+static void callTMres (lua_State *L, StkId res, const TValue *f,
+ const TValue *p1, const TValue *p2) {
+ ptrdiff_t result = savestack(L, res);
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ luaD_checkstack(L, 3);
+ L->top += 3;
+ luaD_call(L, L->top - 3, 1);
+ res = restorestack(L, result);
+ L->top--;
+ setobjs2s(L, res, L->top);
+}
+
+
+
+static void callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, const TValue *p3) {
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ setobj2s(L, L->top+3, p3); /* 3th argument */
+ luaD_checkstack(L, 4);
+ L->top += 4;
+ luaD_call(L, L->top - 4, 0);
+}
+
+
+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ const TValue *res = luaH_get(h, key); /* do a primitive get */
+ if (!ttisnil(res) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
+ setobj2s(L, val, res);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTMres(L, val, tm, t, key);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
+ }
+ luaG_runerror(L, "loop in gettable");
+}
+
+
+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
+ if (!ttisnil(oldval) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
+ setobj2t(L, oldval, val);
+ luaC_barriert(L, h, val);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTM(L, tm, t, key, val);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
+ }
+ luaG_runerror(L, "loop in settable");
+}
+
+
+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ if (ttisnil(tm))
+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
+ if (ttisnil(tm)) return 0;
+ callTMres(L, res, tm, p1, p2);
+ return 1;
+}
+
+
+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+ TMS event) {
+ const TValue *tm1 = fasttm(L, mt1, event);
+ const TValue *tm2;
+ if (tm1 == NULL) return NULL; /* no metamethod */
+ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
+ tm2 = fasttm(L, mt2, event);
+ if (tm2 == NULL) return NULL; /* no metamethod */
+ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */
+ return tm1;
+ return NULL;
+}
+
+
+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
+ TMS event) {
+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
+ const TValue *tm2;
+ if (ttisnil(tm1)) return -1; /* no metamethod? */
+ tm2 = luaT_gettmbyobj(L, p2, event);
+ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
+ return -1;
+ callTMres(L, L->top, tm1, p1, p2);
+ return !l_isfalse(L->top);
+}
+
+
+static int l_strcmp (const TString *ls, const TString *rs) {
+ const char *l = getstr(ls);
+ size_t ll = ls->tsv.len;
+ const char *r = getstr(rs);
+ size_t lr = rs->tsv.len;
+ for (;;) {
+ int temp = strcoll(l, r);
+ if (temp != 0) return temp;
+ else { /* strings are equal up to a `\0' */
+ size_t len = strlen(l); /* index of first `\0' in both strings */
+ if (len == lr) /* r is finished? */
+ return (len == ll) ? 0 : 1;
+ else if (len == ll) /* l is finished? */
+ return -1; /* l is smaller than r (because r is not finished) */
+ /* both strings longer than `len'; go on comparing (after the `\0') */
+ len++;
+ l += len; ll -= len; r += len; lr -= len;
+ }
+ }
+}
+
+
+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+ if (ttype(l) != ttype(r))
+ return luaG_ordererror(L, l, r);
+ else if (ttisnumber(l))
+ return luai_numlt(nvalue(l), nvalue(r));
+ else if (ttisstring(l))
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+ return res;
+ return luaG_ordererror(L, l, r);
+}
+
+
+static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+ if (ttype(l) != ttype(r))
+ return luaG_ordererror(L, l, r);
+ else if (ttisnumber(l))
+ return luai_numle(nvalue(l), nvalue(r));
+ else if (ttisstring(l))
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
+ return res;
+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
+ return !res;
+ return luaG_ordererror(L, l, r);
+}
+
+
+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
+ const TValue *tm;
+ lua_assert(ttype(t1) == ttype(t2));
+ switch (ttype(t1)) {
+ case LUA_TNIL: return 1;
+ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
+ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
+ case LUA_TUSERDATA: {
+ if (uvalue(t1) == uvalue(t2)) return 1;
+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+ TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_TTABLE: {
+ if (hvalue(t1) == hvalue(t2)) return 1;
+ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ default: return gcvalue(t1) == gcvalue(t2);
+ }
+ if (tm == NULL) return 0; /* no TM? */
+ callTMres(L, L->top, tm, t1, t2); /* call TM */
+ return !l_isfalse(L->top);
+}
+
+
+void luaV_concat (lua_State *L, int total, int last) {
+ do {
+ StkId top = L->base + last + 1;
+ int n = 2; /* number of elements handled in this pass (at least 2) */
+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
+ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
+ luaG_concaterror(L, top-2, top-1);
+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
+ (void)tostring(L, top - 2); /* result is first op (as string) */
+ else {
+ /* at least two string values; get as many as possible */
+ size_t tl = tsvalue(top-1)->len;
+ char *buffer;
+ int i;
+ /* collect total length */
+ for (n = 1; n < total && tostring(L, top-n-1); n++) {
+ size_t l = tsvalue(top-n-1)->len;
+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
+ tl += l;
+ }
+ buffer = luaZ_openspace(L, &G(L)->buff, tl);
+ tl = 0;
+ for (i=n; i>0; i--) { /* concat all strings */
+ size_t l = tsvalue(top-i)->len;
+ memcpy(buffer+tl, svalue(top-i), l);
+ tl += l;
+ }
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
+ }
+ total -= n-1; /* got `n' strings to create 1 new */
+ last -= n-1;
+ } while (total > 1); /* repeat until only 1 result left */
+}
+
+
+static void Arith (lua_State *L, StkId ra, const TValue *rb,
+ const TValue *rc, TMS op) {
+ TValue tempb, tempc;
+ const TValue *b, *c;
+ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+ (c = luaV_tonumber(rc, &tempc)) != NULL) {
+ lua_Number nb = nvalue(b), nc = nvalue(c);
+ switch (op) {
+ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+ default: lua_assert(0); break;
+ }
+ }
+ else if (!call_binTM(L, rb, rc, ra, op))
+ luaG_aritherror(L, rb, rc);
+}
+
+
+
+/*
+** some macros for common tasks in `luaV_execute'
+*/
+
+#define runtime_check(L, c) { if (!(c)) break; }
+
+#define RA(i) (base+GETARG_A(i))
+/* to be used after possible stack reallocation */
+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
+
+
+#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);}
+
+
+#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
+
+
+#define arith_op(op,tm) { \
+ TValue *rb = RKB(i); \
+ TValue *rc = RKC(i); \
+ if (ttisnumber(rb) && ttisnumber(rc)) { \
+ lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+ setnvalue(ra, op(nb, nc)); \
+ } \
+ else \
+ Protect(Arith(L, ra, rb, rc, tm)); \
+ }
+
+
+
+void luaV_execute (lua_State *L, int nexeccalls) {
+ LClosure *cl;
+ StkId base;
+ TValue *k;
+ const Instruction *pc;
+ reentry: /* entry point */
+ lua_assert(isLua(L->ci));
+ pc = L->savedpc;
+ cl = &clvalue(L->ci->func)->l;
+ base = L->base;
+ k = cl->p->k;
+ /* main loop of interpreter */
+ for (;;) {
+ const Instruction i = *pc++;
+ StkId ra;
+ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
+ traceexec(L, pc);
+ if (L->status == LUA_YIELD) { /* did hook yield? */
+ L->savedpc = pc - 1;
+ return;
+ }
+ base = L->base;
+ }
+ /* warning!! several calls may realloc the stack and invalidate `ra' */
+ ra = RA(i);
+ lua_assert(base == L->base && L->base == L->ci->base);
+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
+ switch (GET_OPCODE(i)) {
+ case OP_MOVE: {
+ setobjs2s(L, ra, RB(i));
+ continue;
+ }
+ case OP_LOADK: {
+ setobj2s(L, ra, KBx(i));
+ continue;
+ }
+ case OP_LOADBOOL: {
+ setbvalue(ra, GETARG_B(i));
+ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
+ continue;
+ }
+ case OP_LOADNIL: {
+ TValue *rb = RB(i);
+ do {
+ setnilvalue(rb--);
+ } while (rb >= ra);
+ continue;
+ }
+ case OP_GETUPVAL: {
+ int b = GETARG_B(i);
+ setobj2s(L, ra, cl->upvals[b]->v);
+ continue;
+ }
+ case OP_GETGLOBAL: {
+ TValue g;
+ TValue *rb = KBx(i);
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(rb));
+ Protect(luaV_gettable(L, &g, rb, ra));
+ continue;
+ }
+ case OP_GETTABLE: {
+ Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+ continue;
+ }
+ case OP_SETGLOBAL: {
+ TValue g;
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(KBx(i)));
+ Protect(luaV_settable(L, &g, KBx(i), ra));
+ continue;
+ }
+ case OP_SETUPVAL: {
+ UpVal *uv = cl->upvals[GETARG_B(i)];
+ setobj(L, uv->v, ra);
+ luaC_barrier(L, uv, ra);
+ continue;
+ }
+ case OP_SETTABLE: {
+ Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+ continue;
+ }
+ case OP_NEWTABLE: {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_SELF: {
+ StkId rb = RB(i);
+ setobjs2s(L, ra+1, rb);
+ Protect(luaV_gettable(L, rb, RKC(i), ra));
+ continue;
+ }
+ case OP_ADD: {
+ arith_op(luai_numadd, TM_ADD);
+ continue;
+ }
+ case OP_SUB: {
+ arith_op(luai_numsub, TM_SUB);
+ continue;
+ }
+ case OP_MUL: {
+ arith_op(luai_nummul, TM_MUL);
+ continue;
+ }
+ case OP_DIV: {
+ arith_op(luai_numdiv, TM_DIV);
+ continue;
+ }
+ case OP_MOD: {
+ arith_op(luai_nummod, TM_MOD);
+ continue;
+ }
+ case OP_POW: {
+ arith_op(luai_numpow, TM_POW);
+ continue;
+ }
+ case OP_UNM: {
+ TValue *rb = RB(i);
+ if (ttisnumber(rb)) {
+ lua_Number nb = nvalue(rb);
+ setnvalue(ra, luai_numunm(nb));
+ }
+ else {
+ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ }
+ continue;
+ }
+ case OP_NOT: {
+ int res = l_isfalse(RB(i)); /* next assignment may change this value */
+ setbvalue(ra, res);
+ continue;
+ }
+ case OP_LEN: {
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+ setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
+ break;
+ }
+ case LUA_TSTRING: {
+ setnvalue(ra, cast_num(tsvalue(rb)->len));
+ break;
+ }
+ default: { /* try metamethod */
+ Protect(
+ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
+ luaG_typeerror(L, rb, "get length of");
+ )
+ }
+ }
+ continue;
+ }
+ case OP_CONCAT: {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
+ setobjs2s(L, RA(i), base+b);
+ continue;
+ }
+ case OP_JMP: {
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+ case OP_EQ: {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ Protect(
+ if (equalobj(L, rb, rc) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_LT: {
+ Protect(
+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_LE: {
+ Protect(
+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
+ }
+ case OP_TEST: {
+ if (l_isfalse(ra) != GETARG_C(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ pc++;
+ continue;
+ }
+ case OP_TESTSET: {
+ TValue *rb = RB(i);
+ if (l_isfalse(rb) != GETARG_C(i)) {
+ setobjs2s(L, ra, rb);
+ dojump(L, pc, GETARG_sBx(*pc));
+ }
+ pc++;
+ continue;
+ }
+ case OP_CALL: {
+ int b = GETARG_B(i);
+ int nresults = GETARG_C(i) - 1;
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ switch (luaD_precall(L, ra, nresults)) {
+ case PCRLUA: {
+ nexeccalls++;
+ goto reentry; /* restart luaV_execute over new Lua function */
+ }
+ case PCRC: {
+ /* it was a C function (`precall' called it); adjust results */
+ if (nresults >= 0) L->top = L->ci->top;
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_TAILCALL: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
+ switch (luaD_precall(L, ra, LUA_MULTRET)) {
+ case PCRLUA: {
+ /* tail call: put new frame in place of previous one */
+ CallInfo *ci = L->ci - 1; /* previous frame */
+ int aux;
+ StkId func = ci->func;
+ StkId pfunc = (ci+1)->func; /* previous function index */
+ if (L->openupval) luaF_close(L, ci->base);
+ L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
+ setobjs2s(L, func+aux, pfunc+aux);
+ ci->top = L->top = func+aux; /* correct top */
+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
+ ci->savedpc = L->savedpc;
+ ci->tailcalls++; /* one more call lost */
+ L->ci--; /* remove new frame */
+ goto reentry;
+ }
+ case PCRC: { /* it was a C function (`precall' called it) */
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_RETURN: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b-1;
+ if (L->openupval) luaF_close(L, base);
+ L->savedpc = pc;
+ b = luaD_poscall(L, ra);
+ if (--nexeccalls == 0) /* was previous function running `here'? */
+ return; /* no: return */
+ else { /* yes: continue its execution */
+ if (b) L->top = L->ci->top;
+ lua_assert(isLua(L->ci));
+ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);
+ goto reentry;
+ }
+ }
+ case OP_FORLOOP: {
+ lua_Number step = nvalue(ra+2);
+ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+ lua_Number limit = nvalue(ra+1);
+ if (luai_numlt(0, step) ? luai_numle(idx, limit)
+ : luai_numle(limit, idx)) {
+ dojump(L, pc, GETARG_sBx(i)); /* jump back */
+ setnvalue(ra, idx); /* update internal index... */
+ setnvalue(ra+3, idx); /* ...and external index */
+ }
+ continue;
+ }
+ case OP_FORPREP: {
+ const TValue *init = ra;
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
+ if (!tonumber(init, ra))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ luaG_runerror(L, LUA_QL("for") " limit must be a number");
+ else if (!tonumber(pstep, ra+2))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+ case OP_TFORLOOP: {
+ StkId cb = ra + 3; /* call base */
+ setobjs2s(L, cb+2, ra+2);
+ setobjs2s(L, cb+1, ra+1);
+ setobjs2s(L, cb, ra);
+ L->top = cb+3; /* func. + 2 args (state and index) */
+ Protect(luaD_call(L, cb, GETARG_C(i)));
+ L->top = L->ci->top;
+ cb = RA(i) + 3; /* previous call may change the stack */
+ if (!ttisnil(cb)) { /* continue loop? */
+ setobjs2s(L, cb-1, cb); /* save control variable */
+ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */
+ }
+ pc++;
+ continue;
+ }
+ case OP_SETLIST: {
+ int n = GETARG_B(i);
+ int c = GETARG_C(i);
+ int last;
+ Table *h;
+ if (n == 0) {
+ n = cast_int(L->top - ra) - 1;
+ L->top = L->ci->top;
+ }
+ if (c == 0) c = cast_int(*pc++);
+ runtime_check(L, ttistable(ra));
+ h = hvalue(ra);
+ last = ((c-1)*LFIELDS_PER_FLUSH) + n;
+ if (last > h->sizearray) /* needs more space? */
+ luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+ setobj2t(L, luaH_setnum(L, h, last--), val);
+ luaC_barriert(L, h, val);
+ }
+ continue;
+ }
+ case OP_CLOSE: {
+ luaF_close(L, ra);
+ continue;
+ }
+ case OP_CLOSURE: {
+ Proto *p;
+ Closure *ncl;
+ int nup, j;
+ p = cl->p->p[GETARG_Bx(i)];
+ nup = p->nups;
+ ncl = luaF_newLclosure(L, nup, cl->env);
+ ncl->l.p = p;
+ for (j=0; j<nup; j++, pc++) {
+ if (GET_OPCODE(*pc) == OP_GETUPVAL)
+ ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
+ else {
+ lua_assert(GET_OPCODE(*pc) == OP_MOVE);
+ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
+ }
+ }
+ setclvalue(L, ra, ncl);
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_VARARG: {
+ int b = GETARG_B(i) - 1;
+ int j;
+ CallInfo *ci = L->ci;
+ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
+ if (b == LUA_MULTRET) {
+ Protect(luaD_checkstack(L, n));
+ ra = RA(i); /* previous call may change the stack */
+ b = n;
+ L->top = ra + n;
+ }
+ for (j = 0; j < b; j++) {
+ if (j < n) {
+ setobjs2s(L, ra + j, ci->base - n + j);
+ }
+ else {
+ setnilvalue(ra + j);
+ }
+ }
+ continue;
+ }
+ }
+ }
+}
+
diff --git a/debian/grub-extras/lua/lvm.h b/debian/grub-extras/lua/lvm.h
new file mode 100644
index 0000000..bfe4f56
--- /dev/null
+++ b/debian/grub-extras/lua/lvm.h
@@ -0,0 +1,36 @@
+/*
+** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $
+** Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lvm_h
+#define lvm_h
+
+
+#include "ldo.h"
+#include "lobject.h"
+#include "ltm.h"
+
+
+#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+
+#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
+ (((o) = luaV_tonumber(o,n)) != NULL))
+
+#define equalobj(L,o1,o2) \
+ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
+
+
+LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
+LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
+LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
+LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
+ StkId val);
+LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
+ StkId val);
+LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);
+LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);
+
+#endif
diff --git a/debian/grub-extras/lua/lzio.c b/debian/grub-extras/lua/lzio.c
new file mode 100644
index 0000000..3ccba19
--- /dev/null
+++ b/debian/grub-extras/lua/lzio.c
@@ -0,0 +1,83 @@
+/*
+** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
+** a generic input stream interface
+** See Copyright Notice in lua.h
+*/
+
+#if 0
+#include <string.h>
+#endif
+
+#define lzio_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "llimits.h"
+#include "lmem.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+int luaZ_fill (ZIO *z) {
+ size_t size;
+ lua_State *L = z->L;
+ const char *buff;
+ lua_unlock(L);
+ buff = z->reader(L, z->data, &size);
+ lua_lock(L);
+ if (buff == NULL || size == 0) return EOZ;
+ z->n = size - 1;
+ z->p = buff;
+ return char2int(*(z->p++));
+}
+
+
+int luaZ_lookahead (ZIO *z) {
+ if (z->n == 0) {
+ if (luaZ_fill(z) == EOZ)
+ return EOZ;
+ else {
+ z->n++; /* luaZ_fill removed first byte; put back it */
+ z->p--;
+ }
+ }
+ return char2int(*z->p);
+}
+
+
+void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
+ z->L = L;
+ z->reader = reader;
+ z->data = data;
+ z->n = 0;
+ z->p = NULL;
+}
+
+
+/* --------------------------------------------------------------- read --- */
+size_t luaZ_read (ZIO *z, void *b, size_t n) {
+ while (n) {
+ size_t m;
+ if (luaZ_lookahead(z) == EOZ)
+ return n; /* return number of missing bytes */
+ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
+ memcpy(b, z->p, m);
+ z->n -= m;
+ z->p += m;
+ b = (char *)b + m;
+ n -= m;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+ if (n > buff->buffsize) {
+ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+ luaZ_resizebuffer(L, buff, n);
+ }
+ return buff->buffer;
+}
+
+
diff --git a/debian/grub-extras/lua/lzio.h b/debian/grub-extras/lua/lzio.h
new file mode 100644
index 0000000..51d695d
--- /dev/null
+++ b/debian/grub-extras/lua/lzio.h
@@ -0,0 +1,67 @@
+/*
+** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $
+** Buffered streams
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lzio_h
+#define lzio_h
+
+#include "lua.h"
+
+#include "lmem.h"
+
+
+#define EOZ (-1) /* end of stream */
+
+typedef struct Zio ZIO;
+
+#define char2int(c) cast(int, cast(unsigned char, (c)))
+
+#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
+
+typedef struct Mbuffer {
+ char *buffer;
+ size_t n;
+ size_t buffsize;
+} Mbuffer;
+
+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define luaZ_buffer(buff) ((buff)->buffer)
+#define luaZ_sizebuffer(buff) ((buff)->buffsize)
+#define luaZ_bufflen(buff) ((buff)->n)
+
+#define luaZ_resetbuffer(buff) ((buff)->n = 0)
+
+
+#define luaZ_resizebuffer(L, buff, size) \
+ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+ (buff)->buffsize = size)
+
+#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
+
+
+LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
+LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
+ void *data);
+LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
+LUAI_FUNC int luaZ_lookahead (ZIO *z);
+
+
+
+/* --------- Private Part ------------------ */
+
+struct Zio {
+ size_t n; /* bytes still unread */
+ const char *p; /* current position in buffer */
+ lua_Reader reader;
+ void* data; /* additional data */
+ lua_State *L; /* Lua state (for reader) */
+};
+
+
+LUAI_FUNC int luaZ_fill (ZIO *z);
+
+#endif
diff --git a/debian/grub-extras/lua/osdetect.lua b/debian/grub-extras/lua/osdetect.lua
new file mode 100644
index 0000000..a264e61
--- /dev/null
+++ b/debian/grub-extras/lua/osdetect.lua
@@ -0,0 +1,204 @@
+#!lua
+--
+-- Copyright (C) 2009 Free Software Foundation, Inc.
+--
+-- GRUB is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- GRUB is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+--
+
+function enum_device (device, fs, uuid)
+ local root
+ local title
+ local source
+ local kernels = {}
+ local kernelnames = {}
+ local kernel_num = 0
+
+ local function enum_file (name)
+ local version
+
+ version = string.match (name, "vmlinuz%-(.*)")
+ if (version == nil) then
+ version = string.match (name, "linux%-(.*)")
+ end
+ if (version ~= nil) then
+ table.insert (kernels, version)
+ table.insert (kernelnames, name)
+ kernel_num = kernel_num + 1
+ end
+ end
+
+ local function sort_kernel (first, second)
+ local a1, a2, a3, a4, b1, b2, b3, b4
+
+ a1, a2, a3, a4 = string.match (first, "(%d+)%.?(%d*).?(%d*)%-?(%d*)")
+ b1, b2, b3, b4 = string.match (second, "(%d+)%.?(%d*).?(%d*)%-?(%d*)")
+ return (a1 > b1) or (a2 > b2) or (a3 > b3) or (a4 < b4);
+ end
+ local function freebsd_variants (title, header, footer)
+ normal = "\nset FreeBSD.acpi_load=YES" ..
+ "\nset FreeBSD.hint.acpi.0.disabled=0"
+ noacpi = "\nunset FreeBSD.acpi_load" ..
+ "\nset FreeBSD.hint.acpi.0.disabled=1" ..
+ "\nset FreeBSD.loader.acpi_disabled_by_user=1"
+ safe = "\nset FreeBSD.hint.apic.0.disabled=1" ..
+ "\nset FreeBSD.hw.ata.ata_dma=0" ..
+ "\nset FreeBSD.hw.ata.atapi_dma=0" ..
+ "\nset FreeBSD.hw.ata.wc=0" ..
+ "\nset FreeBSD.hw.eisa_slots=0" ..
+ "\nset FreeBSD.hint.kbdmux.0.disabled=1"
+ grub.add_menu (header .. normal .. footer, title)
+ grub.add_menu (header .. " --single" .. normal .. footer,
+ title .. " (single)")
+ grub.add_menu (header .. " --verbose" .. normal .. footer,
+ title .. " (verbose)")
+ grub.add_menu (header .. " --verbose" .. noacpi .. footer,
+ title .. " (without ACPI)")
+ grub.add_menu (header .. " --verbose" .. noacpi .. safe .. footer,
+ title .. " (safe mode)")
+ end
+
+ root = "(" .. device .. ")/"
+ source = "set root=" .. device .. "\nchainloader +1"
+
+ local drive_num = string.match (device, "hd(%d+)")
+ if (drive_num ~= nil) and (drive_num ~= "0") then
+ source = source .. "\ndrivemap -s hd0 hd" .. drive_num
+ end
+
+ title = nil
+ if (grub.file_exist (root .. "bootmgr") and
+ grub.file_exist (root .. "boot/bcd")) then
+ title = "Windows Vista bootmgr"
+ source = "set root=" .. device .. "\nchainloader +1"
+ elseif (grub.file_exist (root .. "ntldr") and
+ grub.file_exist (root .. "ntdetect.com") and
+ grub.file_exist (root .. "boot.ini")) then
+ title = "Windows NT/2000/XP loader"
+ elseif (grub.file_exist (root .. "windows/win.com")) then
+ title = "Windows 98/ME"
+ elseif (grub.file_exist (root .. "io.sys") and
+ grub.file_exist (root .. "command.com")) then
+ title = "MS-DOS"
+ elseif (grub.file_exist (root .. "kernel.sys")) then
+ title = "FreeDOS"
+ elseif ((fs == "ufs1" or fs == "ufs2") and grub.file_exist (root .. "boot/kernel/kernel") and
+ grub.file_exist (root .. "boot/device.hints")) then
+ header = "set root=" .. device .. "\nfreebsd /boot/kernel/kernel"
+ footer = "\nset FreeBSD.vfs.root.mountfrom=ufs:ufsid/" .. uuid ..
+ "\nfreebsd_loadenv /boot/device.hints"
+ title = "FreeBSD (on " .. fs .. " ".. device .. ")"
+ freebsd_variants (title, header, footer)
+ return 0
+ elseif (fs == "zfs" and grub.file_exist (root .. "/@/boot/kernel/kernel") and
+ grub.file_exist (root .. "/@/boot/device.hints")) then
+ header = "set root=" .. device .. "\nfreebsd /@/boot/kernel/kernel"
+ footer = "\nfreebsd_module_elf /@/boot/kernel/opensolaris.ko" ..
+ "\nfreebsd_module_elf /@/boot/kernel/zfs.ko" ..
+ "\nfreebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache" ..
+ "\nprobe -l -s name $root" ..
+ "\nset FreeBSD.vfs.root.mountfrom=zfs:$name" ..
+ "\nfreebsd_loadenv /@/boot/device.hints"
+ title = "FreeBSD (on " .. fs .. " ".. device .. ")"
+ freebsd_variants (title, header, footer)
+ return 0
+ elseif (fs == "hfsplus" and grub.file_exist (root .. "mach_kernel")) then
+ source = "set root=" .. device ..
+ "\ninsmod vbe" ..
+ "\ndo_resume=0" ..
+ "\nif [ /var/vm/sleepimage -nt10 / ]; then" ..
+ "\n if xnu_resume /var/vm/sleepimage; then" ..
+ "\n do_resume=1" ..
+ "\n fi" ..
+ "\nfi" ..
+ "\nif [ $do_resume == 0 ]; then" ..
+ "\n xnu_uuid " .. uuid .. " uuid" ..
+ "\n if [ -f /Extra/DSDT.aml ]; then" ..
+ "\n acpi -e /Extra/DSDT.aml" ..
+ "\n fi" ..
+ "\n xnu_kernel /mach_kernel boot-uuid=${uuid} rd=*uuid" ..
+ "\n if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then" ..
+ "\n xnu_mkext /System/Library/Extensions.mkext" ..
+ "\n else" ..
+ "\n xnu_kextdir /System/Library/Extensions" ..
+ "\n fi" ..
+ "\n if [ -f /Extra/Extensions.mkext ]; then" ..
+ "\n xnu_mkext /Extra/Extensions.mkext" ..
+ "\n fi" ..
+ "\n if [ -d /Extra/Extensions ]; then" ..
+ "\n xnu_kextdir /Extra/Extensions" ..
+ "\n fi" ..
+ "\n if [ -f /Extra/devtree.txt ]; then" ..
+ "\n xnu_devtree /Extra/devtree.txt" ..
+ "\n fi" ..
+ "\n if [ -f /Extra/splash.jpg ]; then" ..
+ "\n insmod jpeg" ..
+ "\n xnu_splash /Extra/splash.jpg" ..
+ "\n fi" ..
+ "\n if [ -f /Extra/splash.png ]; then" ..
+ "\n insmod png" ..
+ "\n xnu_splash /Extra/splash.png" ..
+ "\n fi" ..
+ "\n if [ -f /Extra/splash.tga ]; then" ..
+ "\n insmod tga" ..
+ "\n xnu_splash /Extra/splash.tga" ..
+ "\n fi" ..
+ "\nfi"
+ title = "Mac OS X/Darwin"
+ else
+ grub.enum_file (enum_file, root .. "boot")
+ if kernel_num ~= 0 then
+ table.sort (kernels, sort_kernel)
+ table.sort (kernelnames, sort_kernel)
+ for i = 1, kernel_num do
+ local initrd
+
+ title = "Linux " .. kernels[i]
+ source = "set root=" .. device ..
+ "\nlinux /boot/" .. kernelnames[i] ..
+ " root=UUID=" .. uuid .. " ro"
+
+ if grub.file_exist (root .. "boot/initrd-" ..
+ kernels[i] .. ".img") then
+ initrd = "\ninitrd /boot/initrd-" .. kernels[i] .. ".img"
+ elseif grub.file_exist (root .. "boot/initrd.img-" .. kernels[i]) then
+ initrd = "\ninitrd /boot/initrd.img-" .. kernels[i]
+ elseif grub.file_exist (root .. "boot/initrd-" .. kernels[i]) then
+ initrd = "\ninitrd /boot/initrd-" .. kernels[i]
+ else
+ initrd = ""
+ end
+
+ grub.add_menu (source .. initrd, title)
+ grub.add_menu (source .. " single" .. initrd,
+ title .. " (single-user mode)")
+ end
+ return 0
+ end
+ end
+
+ if title == nil then
+ local partition = string.match (device, ".*,(%d+)")
+
+ if (partition ~= nil) and (tonumber (partition) > 4) then
+ return 0
+ end
+
+ title = "Other OS"
+ end
+
+ grub.add_menu (source, title)
+ return 0
+end
+
+grub.enum_device (enum_device)
diff --git a/debian/grub-extras/ntldr-img/COPYING b/debian/grub-extras/ntldr-img/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/debian/grub-extras/ntldr-img/Makefile.core.common b/debian/grub-extras/ntldr-img/Makefile.core.common
new file mode 100644
index 0000000..f5c0c60
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/Makefile.core.common
@@ -0,0 +1,38 @@
+if COND_i386_pc
+# Compatibility symlink.
+g2hdr.bin: g2hdr.img
+ rm -f $@
+ $(LN_S) $< $@
+platform_DATA += g2hdr.bin
+CLEANFILES += g2hdr.bin
+
+g2ldr.mbr: g2ldr.img
+ head -c 8192 $< > $@
+platform_DATA += g2ldr.mbr
+CLEANFILES += g2ldr.mbr
+
+grldr.mbr: grldr.img
+ head -c 8192 $< > $@
+CLEANFILES += grldr.mbr
+
+bin2h: contrib/ntldr-img/bin2h.c
+ $(BUILD_CC) $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $^ -o $@
+CLEANFILES += bin2h
+
+grub_mbr.h: grldr.mbr bin2h
+ ./bin2h grub_mbr 8192 < $< > $@
+CLEANFILES += grub_mbr.h
+
+grub-ntldr-img$(EXEEXT): contrib/ntldr-img/grubinst.c contrib/ntldr-img/utils.c grub_mbr.h
+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(HOST_LDFLAGS) -DGRUB_UTIL=1 -I. -I$(srcdir)/contrib/ntldr-img -DLINUX -o $@ $(srcdir)/contrib/ntldr-img/grubinst.c $(srcdir)/contrib/ntldr-img/utils.c
+bin_PROGRAMS += grub-ntldr-img
+CLEANFILES += grub-ntldr-img
+
+# Compatibility symlink.
+grubinst$(EXEEXT): grub-ntldr-img$(EXEEXT)
+ rm -f $@
+ $(LN_S) $< $@
+noinst_PROGRAMS += grubinst
+CLEANFILES += grubinst
+
+endif
diff --git a/debian/grub-extras/ntldr-img/Makefile.core.def b/debian/grub-extras/ntldr-img/Makefile.core.def
new file mode 100644
index 0000000..59dd44b
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/Makefile.core.def
@@ -0,0 +1,32 @@
+AutoGen definitions Makefile.tpl;
+
+image = {
+ name = g2hdr;
+ i386_pc = contrib/ntldr-img/g2hdr.S;
+ i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
+ i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x0';
+ objcopyflags = '-O binary';
+ enable = i386_pc;
+};
+
+image = {
+ name = grldr;
+ i386_pc = contrib/ntldr-img/grldrstart.S;
+ i386_pc = contrib/ntldr-img/ntfsbs.S;
+ i386_pc_ccasflags = -DGRLDR_MBR;
+ i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
+ i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7c00';
+ objcopyflags = '-O binary';
+ enable = i386_pc;
+};
+
+image = {
+ name = g2ldr;
+ i386_pc = contrib/ntldr-img/grldrstart.S;
+ i386_pc = contrib/ntldr-img/ntfsbs.S;
+ i386_pc_ccasflags = '-DGRLDR_MBR -DBOOTGRUB2';
+ i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
+ i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7c00';
+ objcopyflags = '-O binary';
+ enable = i386_pc;
+};
diff --git a/debian/grub-extras/ntldr-img/README b/debian/grub-extras/ntldr-img/README
new file mode 100644
index 0000000..874bd08
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/README
@@ -0,0 +1,11 @@
+
+grub-extras is meant to be used as an overlay on grub2 source tree.
+
+Build instructions:
+
+ - Copy grub-extras in a subdirectory of your grub2 checkout.
+ For example, "grub-extras".
+
+ - Export GRUB_CONTRIB environment variable to point to this directory.
+
+ - Build GRUB as usual.
diff --git a/debian/grub-extras/ntldr-img/bin2h.c b/debian/grub-extras/ntldr-img/bin2h.c
new file mode 100644
index 0000000..f713b55
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/bin2h.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 Robert Millan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (int argc, char *argv[])
+{
+ int b, i;
+ char *sym;
+ unsigned int len;
+
+ if (argc != 3)
+ {
+ fprintf (stderr, "Usage: %s symbol_name length\n", argv[0]);
+ exit (1);
+ }
+
+ sym = argv[1];
+ len = atoi (argv[2]);
+
+ b = getchar ();
+ if (b == EOF)
+ goto abort;
+
+ printf ("/* THIS CHUNK OF BYTES IS AUTOMATICALY GENERATED */\n"
+ "unsigned char %s[%u] =\n{\n", sym, len);
+
+ while (1)
+ {
+ printf ("0x%02x", b);
+
+ b = getchar ();
+ if (b == EOF)
+ goto end;
+
+ for (i = 0; i < 16 - 1; i++)
+ {
+ printf (", 0x%02x", b);
+
+ b = getchar ();
+ if (b == EOF)
+ goto end;
+ }
+
+ printf (",\n");
+ }
+
+end:
+ printf ("\n};\n");
+
+abort:
+ exit (0);
+}
diff --git a/debian/grub-extras/ntldr-img/g2hdr.S b/debian/grub-extras/ntldr-img/g2hdr.S
new file mode 100644
index 0000000..4b8e0e6
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/g2hdr.S
@@ -0,0 +1,98 @@
+/*
+ * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
+ * Copyright (C) 2007 Bean (bean123@126.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/kernel.h>
+
+ .file "g2hdr.S"
+
+ .text
+
+ .code16
+
+ .globl start, _start
+
+start:
+_start:
+
+ // We are at 0x2000:0
+ // Move itself to 0x800:0
+ // Don't modify dx
+
+ cld
+ movw %cs, %ax
+ movw %ax, %ds
+ movw $0x800, %ax
+ movw %ax, %es
+ xorw %si, %si
+ movw %si, %di
+ movw $0x80, %cx
+
+ rep
+ movsl
+
+ ljmp $0, $(jump_start-start+0x8000)
+
+jump_start:
+ // Move data from 0x2040:0 to 0x820:0
+
+ movw $0x2040, %ax
+ movw %ax, %ds
+ movw $0x820, %ax
+ movw %ax, %es
+ xorl %eax, %eax
+ movb %dh, (GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2)
+ movl GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE, %eax
+ addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %eax
+ xorl %ecx, %ecx
+
+1:
+ xorw %si, %si
+ movw %si, %di
+
+ movw $0x8000, %cx
+ cmpl %ecx, %eax
+ jae 2f
+ movw %ax, %cx
+2:
+
+ pushw %cx
+ addw $3, %cx
+ shrw $2, %cx
+
+ rep
+ movsl
+
+ popw %cx
+
+ movw %ds, %si
+ addw $0x800, %si
+ movw %si, %ds
+
+ movw %es, %si
+ addw $0x800, %si
+ movw %si, %es
+
+ subl %ecx, %eax
+ jnz 1b
+
+ ljmp $0, $(0x8000 + 0x200)
+
+ . = _start + 0x200 - 2
+
+ .word 0xAA55
diff --git a/debian/grub-extras/ntldr-img/grldrstart.S b/debian/grub-extras/ntldr-img/grldrstart.S
new file mode 100644
index 0000000..1751338
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/grldrstart.S
@@ -0,0 +1,5793 @@
+/*
+ * grldrstart.S -- Startup code for GRLDR
+ * Copyright (C) 2004-2007 Tinybit(tinybit@tom.com)
+ * Copyright (C) 2007 Bean(bean@windrv.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This program is used to generate the GRLDR file.
+ *
+ * Use the following shell command to generate the GRLDR file:
+ *
+ * cat grldrstart pre_stage2 > grldr
+ *
+ */
+
+#ifndef STAGE1_5
+//#include <stage2_size.h>
+#else
+#error cannot compile with STAGE1_5
+#endif
+
+#ifdef GRLDR_MBR
+ .file "mbrstart.S"
+#elif defined(GRLDR_INSTALL)
+ .file "bootlacestart.S"
+#else
+ .file "grldrstart.S"
+#endif
+
+#ifdef GRLDR_INSTALL
+ //.data
+#else
+ .text
+
+ .globl start, _start
+
+start:
+_start:
+#endif
+
+_start1:
+
+ /* Tell GAS to generate 16-bit real mode instructions */
+
+ .code16
+
+ . = _start1 + 0x00
+
+ /* 1 byte at offset 0x00 will be overwritten for the EBIOS indicator
+ * later. This is safe because the jmp instruction only get executed
+ * once. The write happens after the jmp instruction have got
+ * executed.
+ *
+ * The value written would be 0x42 for EBIOS present(LBA) and 0x02
+ * for non-present(CHS).
+ *
+ */
+
+ /* No cli, we use stack! BIOS or caller usually sets SS:SP=0000:0400 */
+
+ jmp 1f /* FAT32/NTFS routine comes to offset 0 */
+
+ . = _start1 + 0x02
+
+ .byte 0x80 /* bit0=1: disable GRLDR search on floppy */
+ /* bit1=1: disable the boot of the previous MBR with
+ * invalid partition table */
+ /* bit2=1: disable the feature of unconditional
+ * entrance to the command-line */
+ /* bit7=1: disable the boot of the previous MBR prior
+ to the search for GRLDR */
+
+ /* GRLDR.MBR uses offset 0x03 to indicate a timer counter. */
+
+ /* 0xff indicates waiting forever,
+ * other value specifies the time in seconds to wait */
+
+ . = _start1 + 0x03
+
+ .byte 5
+
+ /* a key press to wait. if AX returned from int16 equals this word,
+ * the desired action will occur. */
+
+ . = _start1 + 0x04
+
+ .word 0x3920 /* the space bar */
+
+ . = _start1 + 0x06
+
+ .byte 0xff /* preferred boot drive number, 0xff for no-drive(i.e., drive not defined) */
+ .byte 0xff /* preferred partition number, 0xff for whole drive(a floppy that has no partition table) */
+
+ . = _start1 + 8
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ /* filled in by mkisofs using the -boot-info-table option */
+
+#;bi_pvd: .long 0xDEADBEEF /* LBA of primary volume descript */
+#;bi_file: .long 0xDEADBEEF /* LBA of boot file */
+#;bi_length: .long 0xDEADBEEF /* Length of boot file */
+#;bi_csum: .long 0xDEADBEEF /* Checksum of boot file */
+#;bi_reserved: .space (10*4) /* Reserved */
+
+ . = _start1 + 0x40
+
+#else
+
+ /* filled in with BPB in case the drive(typically USB) is treated as floppy by buggy BIOSes */
+
+ . = _start1 + 0x60
+
+#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */
+
+1:
+ call 1f
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ . = _start1 + 0x43
+
+#else
+
+ . = _start1 + 0x63
+
+#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */
+
+1:
+ popw %bx /* Instruction Pointer of 1b */
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ subw $(1b - _start1), %bx /* CS:BX=_start1 */
+
+#else
+
+ subw $(1b - _start1), %bx /* CS:BX=_start1 */
+
+#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */
+
+ shrw $4, %bx
+ movw %cs, %ax
+ addw %ax, %bx /* BX:0000=_start1 */
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ /* we are booted from BOOT.INI, or whole GRLDR image already loaded */
+
+ pushw %bx /* BX:0000=_start1 */
+ addw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 4) >> 4), %bx
+ movw %bx, %ds
+
+ cmpl $0xCE1A02B0, ((STAGE2_SIZE - 4) & 0x0F)
+ popw %ds /* DS:0000=_start1 */
+ je grldr_real_start /* whole image loaded. boot it! */
+
+ /* bad! we might be loaded by a buggy BIOS with a no-emulation-mode
+ * bootable CD. The buggy BIOS might load only 1 CD-ROM sector(2048
+ * bytes) of our grldr image. So we need this check.
+ */
+
+ /* Our cdrom_check code begins at 0x1BE and overlaps the partition
+ * table. Just in case someone replace it with a partition table and
+ * use this sector as an MBR, we do this additional test for safety.
+ */
+
+ /* We should avoid using opcode 0x00 and 0x80 at cdrom_check. */
+
+ /* Note that if cdrom_check code is present, then we are booting from
+ * no-emulation mode cdrom.
+ */
+
+ testb $0x7F, cdrom_check - _start1 /* is it 0x00 or 0x80? */
+ jz 1f /* yes, cdrom_check not found */
+ call cdrom_check /* no, cdrom_check is present */
+1:
+ /* DS:0000=_start1 */
+
+ /* Let CS:0000=_start1 */
+ pushw %ds
+
+ #;pushw $(1f - _start1)
+ .byte 0x6A, (1f - _start1)
+
+ lret
+ . = . - (. - _start1) / 0x80
+1:
+#else
+ /* BX:0000=_start1 */
+
+ movw %bx, %ds
+
+ /* Let CS:0000=_start1 */
+ pushw %bx
+
+ #;pushw $(1f - _start1)
+ .byte 0x6A, (1f - _start1)
+
+ lret
+ . = . - (. - _start1) / 0x80
+1:
+ testb $0x04, 0x02
+ jz 1f
+
+ /* set the DUCE indicator */
+ xorw %ax, %ax
+ movw %ax, %es
+ movw $0x5FC, %di
+ movl $0x45435544, %eax
+ stosl
+1:
+#endif
+
+ /* CS:0000=DS:0000=_start1 */
+
+ /* we are loaded by BIOS or another boot loader */
+
+#define GRLDR_CS 0x2000 /* grldr code segment */
+ /* hope this segment never be used by all */
+ /* subsequent partition boot records */
+#if 0
+ /* for single sector boot record */
+#define MONITOR 0x7e10
+#else
+ /* for 4-sector NTFS boot record */
+#define MONITOR 0x8410
+#endif
+
+// cli
+ pushw $GRLDR_CS
+ popw %ss
+ movw $0x9000, %sp /* SS:SP=0x9d000, keep away from EBDA data */
+// sti
+
+ /* Extended BIOS Data Area should not take up space below 0x9d000 */
+
+ /*
+ * 0x07c00-0x07dff This sector. Another boot loader load us here
+ * 0x0d000-0x14dff partition/floppy boot track(bootsector,etc)
+ * 0x94000-0x9bdff master boot track(MBR,etc,usually 63 sectors)
+ * 0x9be00-0x9c3ff 3 sectors for temp extended partition entries
+ * 0x9c400-0x9cfff 6 sectors for stack
+ */
+
+#define FS_BOOT 0xd00 /* segment of partition boot track */
+
+ xorw %cx, %cx
+ pushw %cx /* CX=0 */
+ movw $0x0080, %dx
+ pushw %dx
+ movb $8, %ah /* read drive parameters changes DX,ES,DI */
+ stc
+ int $0x13
+ popw %dx
+ popw %ax /* AX=0 */
+
+ pushw %ss /* SS=0x9400 */
+ popw %es /* ES=0x9400 */
+
+ jc Error1
+
+ andb $63, %cl /* AL=sectors per track, CF cleared */
+
+ stc
+ jz Error1
+
+ xchgw %ax, %cx /* this moves CL to AL, and CX=0 */
+ movb $0x02, %ah
+ movw %ax, %bp /* save AX to BP: read 1 track */
+ xorw %bx, %bx /* ES already has a known value of 0x9400 */
+ incw %cx
+ pushw %dx
+ stc
+ int $0x13 /* read master boot track to ES:0000 */
+ popw %dx
+ jc Error1
+ negb %ah /* set CF=1 if non-zero */
+Error1:
+ pushw %cs /* DS=0 */
+ popw %ds /* DS=CS */
+ pushfw /* CF=1 on error */
+
+ /* CS=DS=old segment. ES=SS=new segment. */
+
+ /* Move the code and error messages from DS:0000 to 9400:0000, do not
+ * touch the partition table
+ */
+ xorw %si, %si
+ xorw %di, %di
+ movw $223, %cx /* 223 words = 446 bytes = 0x1be bytes */
+ cld
+ repz movsw /* SI=DI=0x1be, CX=0 */
+
+ movw $(grldr_signature - _start1), %bx
+
+ /* if the boot loader has loaded more than one sector, we use them */
+ movl $0xAA555247, %eax /* "GR" 0x55 0xAA */
+//#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+ cmpl %eax, (%bx) /* DS=old segment! */
+ jne 1f
+
+ /* The MOVE_HELPER code is in the old segment! */
+
+ call move_helper /* SI=0x1be, CX=0 */
+1:
+//#endif
+
+ /* Jump to new segment! */
+#if 1
+ ljmp $GRLDR_CS, $(1f - _start1)
+#else
+ pushw %ss /* 0x9400 */
+
+ //pushw $(1f - _start1)
+ .byte 0x6A, (1f - _start1)
+
+ lret
+ . = . - (. - _start1) / 0x80
+#endif
+1:
+
+ /* We are at the new segment. CS=ES=SS=new segment. */
+
+ /* But DS is still old segment. */
+
+ pushw %ss
+ popw %ds
+
+ /* CS=DS=ES=SS=new segment. */
+
+ //movw $0x01be, %si
+
+ /* check the existence of helper */
+ cmpl %eax, (%bx)
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ jne Error_or_prev_MBR /* Missing helper */
+
+#else
+
+ je 1f
+
+ /* try to load helper from floppy */
+
+ pushal
+
+ movw 0x18, %ax /* BPB sectors per track at offset 0x18 */
+
+ cmpw $0x3F, %ax
+ ja 3f
+
+ cmpb $((pre_stage2_start - _start1) >> 9), %al
+ jb 3f
+
+ decw %ax /* skip the first sector already loaded */
+
+ movw $3, %di /* retry 3 times on read failure */
+2:
+ movb $2, %ah /* BIOS disk read */
+ cwd /* DX=0 for floppy head 0 */
+ movw $0x200, %bx /* ES:BX immediately follow this sector */
+ movw $2, %cx /* skip the first sector already loaded */
+
+ pushaw
+ int $0x13
+ popaw
+
+ jnc 3f
+
+ pushaw
+ xorw %ax, %ax
+ int $0x13
+ popaw
+
+ decw %di
+ jnz 2b
+3:
+ popal
+ cmpl %eax, (%bx) /* helper loaded? */
+
+ jne Error_or_prev_MBR /* Missing helper */
+
+1:
+#endif
+
+ popfw /* CF=1 on error */
+ jc try_floppy /* harddisk (hd0) failed, try floppy (fd0) */
+1:
+ pushw %cs
+ popw %ds
+ lodsw
+ movb %ah, %dh /* head number */
+ lodsw
+ movw %ax, %cx /* sector and cylinder number */
+ andb $63, %al
+ //stc
+ jz helper_call_c
+
+ /* use BP to calculate the sectors to read within 1 track */
+ subw %bp, %ax
+ decw %ax /* decb %al */
+ negb %al /* AL=sectors upto the end of the track */
+7:
+ movw $3, %di /* retry 3 times on read failure */
+2:
+ movb $2, %ah
+ pushw $FS_BOOT
+ popw %es /* ES=FS_BOOT */
+ xorw %bx, %bx
+
+ pushaw
+ int $0x13 /* read partition boot track to FS_BOOT:0000 */
+ popaw
+
+ jnc helper_call
+
+ pushaw
+ xorw %ax, %ax
+ int $0x13
+ popaw
+
+ decw %di
+ jnz 2b
+
+helper_call_c:
+
+ stc
+
+helper_call:
+ /* find GRLDR in this partition
+ * before the call:
+ * CF=1 : indicates an invalid or corrupt entry
+ * CF=0 : indicates a valid entry
+ *
+ * on return:
+ * CF=1 : means "below", try next entry
+ * CF=0,ZF=1 : means "equal", helper did nothing, so we need
+ * a further try to boot via NT bootsector
+ * CF=0,ZF=0 : means "above", helper succeeded, boot it now
+ */
+ call helper_start /* change to jmp 6f if helper not present */
+ ja filesystem_boot /* helper succeeded, directly boot it */
+6:
+
+add_sub_si:
+
+ /* extended partition check routine will adjust this to
+ *
+ * 0x83, 0xEE, 0x04 for "subw $4, %si"
+ *
+ * or
+ *
+ * 0x83, 0xC6, 0xFC for "addw $-4, %si"
+ *
+ * so that SI keeps the value 0x1fe.
+ */
+ addw $12, %si /* 0x83, 0xC6, 0x0C */
+
+ . = add_sub_si + 3
+
+ /* extended partition check routine will adjust the word 0x1fe at
+ * (add_sub_si + 5). The value 0x1ff or greater indicates there are
+ * entries need to be treated. The value 0x1fe indicates no entries
+ * left, and the floppy should be checked.
+ */
+
+ cmpw $0x01fe, %si /* 0x81, 0xFE, 0xfe, 0x01 */
+ /* All entries checked done? */
+ jb 1b /* No, check the next entry */
+ ja 5f /* floppy already checked. Fail and hang */
+
+try_floppy:
+
+ movw $0x31b2, %si /* a value big enough */
+ movb $0x08, %ah /* read drive parameters changes DX,ES,DI */
+ cwd /* DL=0 for floppy */
+ pushw %dx /* DX=0 */
+ int $0x13
+ popw %ax /* AX=0 */
+ jc 5f /* floppy failure, issue "Error" and hang */
+ cwd /* DX=0 */
+ xchgw %ax, %cx /* this moves CL to AL, and CX=0 */
+ andb $63, %al /* AL=sectors per track */
+ jz 5f /* invalid value. floppy failure. hangs */
+ //movw $1, %cx
+ incw %cx
+ jmp 7b
+
+5:
+Error_or_prev_MBR:
+
+ /* GRLDR not found, print "Error" or launch previous MBR */
+ movw $(message_string - _start1), %si
+Error2:
+ call print_message /* CS:SI points to message string */
+3: jmp 3b
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+filesystem_boot:
+ /* The partition boot record successfully modified, just boot it */
+
+ /*
+ * The boot might fail, but we want to take back the control.
+ * So we save the registers now.
+ */
+ pushw %ds
+ pushw %es
+ pushal
+
+ /* DS=CS=GRLDR_CS, ES=FS_BOOT */
+
+ /* save GRLDR_CS */
+
+ movw %es, %bx # save old ES to BX
+
+ cli
+ lgdt gdt - _start1
+ movl %cr0, %eax
+ orb $1, %al
+ movl %eax, %cr0
+
+ movw $8, %si
+ movw %si, %es
+
+ xorl %esi, %esi
+ xorl %edi, %edi
+ movl $(0x9000 / 4), %ecx
+
+ cld
+ repz movsl
+
+ movw $16, %si
+ movw %si, %es
+
+ andb $0xfe, %al
+ movl %eax, %cr0
+
+ movw %bx, %es # restore ES from BX
+
+ /* move FS_BOOT:0000 to 0:7c00 */
+#if 0
+ /* for single sector boot record */
+ movw $0x0200, %cx /* move 2 sectors, the old FS_BOOT:0000 will
+ * keep untouched. */
+#else
+ /* for 4-sector NTFS boot record */
+ movw $0x0400, %cx /* move 4 sectors, the old FS_BOOT:0000 will
+ * keep untouched. */
+#endif
+ xorw %si, %si
+ pushw %si /* SI=0, for the segment of 0000:7c00 */
+ movw $0x7c00, %di
+ pushw %di /* DI=0x7c00, for the offset of 0000:7c00 */
+ pushw %es /* ES=FS_BOOT */
+ popw %ds /* DS=FS_BOOT */
+ pushw %si /* SI=0 */
+ popw %es /* ES=0 */
+ cld
+ repz movsw
+
+ movw $MONITOR, %di
+ movw $(restore_GRLDR_CS - _start1), %si
+ movw $((gdt_end - restore_GRLDR_CS) / 4), %cx
+ cld
+ repz cs movsl /* CS segment override prefix(=0x2E) */
+
+ pushw %es /* ES=0 */
+ popw %ds /* DS=0 */
+ sti
+ lret //ljmp $0, $0x7c00
+#endif
+
+try_next_partition:
+
+ cli
+ movw $GRLDR_CS, %ax
+ movw %ax, %ss
+ movw $(0x9000-36), %sp
+ sti
+
+ /* restore the registers and continue */
+ popal
+ popw %es
+ popw %ds
+ jmp add_sub_si
+
+ /* prints string CS:SI (modifies AX BX SI) */
+3:
+ //xorw %bx, %bx /* video page 0 */
+ movb $0x0e, %ah /* print char in AL */
+ int $0x10 /* via TTY mode */
+
+print_message:
+
+ lodsb %cs:(%si), %al /* get token */
+ cmpb $0, %al /* end of string? */
+ jne 3b
+ ret
+
+message_string:
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+ .ascii "\r\nMissing helper.\0"
+#else
+ .ascii "\r\nMissing MBR-helper.\0"
+#endif
+
+#;buggy_bios_string:
+#;
+#; .ascii "\r\nBuggy BIOS!\0"
+
+ /* Make sure the above code does not occupy the partition table */
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+ /* offset value here must be less than or equal to 0x1be */
+ . = . - ((. - _start1) / 0x1bf)
+#else
+ /* offset value here must be less than or equal to 0x1b8 */
+ . = . - ((. - _start1) / 0x1b9)
+#endif
+
+ /* The following code may occupy the same area as the partition table */
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ /* we are not booted from MBR. So we can reuse the area of partition
+ * table for our code.
+ */
+
+ . = _start1 + 0x1be
+
+cdrom_check:
+
+ /* DS points to the sector start, but CS does not. */
+
+ /* BX segment points to near the end of GRLDR image. */
+
+ popw %ax /* old return IP */
+
+ /* set BX as the new safe stack. */
+ movw %bx, %ss
+ movw $0xFFF0, %sp
+
+ pushw %ax /* old return IP */
+
+ /* check if DL is no-emulation-mode bootable CDROM. */
+ pushw %ds
+
+ cmpb $0x80, %dl
+ jb 1f /* not a valid no-emulation-mode cdrom drive number */
+
+ cmpw $0xAA55, 0x7FE /* 2048 bytes loaded? */
+ jne 1f
+
+// cmpw $0xAA55, 0x5FE /* 2048 bytes loaded? */
+// jne 1f
+
+ movw $0x0180, %si
+ movw $0x4B01, %ax
+ pushw $0x0040
+ //.byte 0x6A, 0x40
+ popw %ds
+ pushw %ds
+ popw %es
+ movb $0x13, (%si)
+ int $0x13
+
+ /* ignore CF */
+#; jc 2f /* not in emulation mode */
+ xorl %eax, %eax
+ xorw %bp, %bp
+ testb $0x0F, 1(%si) /* boot media type is No Emulation? */
+ jnz 2f /* no, it simulates floppy or hard disk. */
+ cmpb %dl, 2(%si) /* drive number */
+ jnz 2f /* invalid drive */
+
+ /* OK! it is no-emulation-mode cdrom drive. */
+ movl 4(%si), %eax /* LBA of GRLDR */
+ incw %bp
+
+2:
+ jmp cdrom_helper
+1:
+ popw %ds
+ ret
+
+
+#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */
+
+ . = _start1 + 0x1fe /* boot signature */
+
+/* partition entries in the extended partitions will overwrite code here upto
+ * 0x3fd.
+ *
+ * the extended partition entries will occupy a temp area at 0x9be00-0x9c3ff
+ */
+
+#if (defined(GRLDR_MBR)) || (defined(GRLDR_INSTALL))
+ .word 0xaa55
+#endif
+
+ . = _start1 + 0x200
+
+/* if it is in the Master Boot Track, the second sector can be used to backup
+ * the previously working MBR, typically, the MS MBR. if the backup copy of
+ * the MBR cannot boot(because, e.g., it depends on another sector of code
+ * that does not exist for now), then please do not set the ending signature
+ * to 0xAA55, that is to say, if the signature is already 0xAA55, you should
+ * change it to another value(for example, 0x0000).
+ */
+
+#if (! defined(GRLDR_INSTALL))
+#if 0
+print_cl:
+ pushaw
+
+ movw %cx, %ax
+ movb $16, %cl
+ divb %cl # quo=AL, rem=AH
+ orw $0x3030, %ax
+
+ cmpb $0x39, %ah
+ jbe 1f
+ addb $7, %ah
+1:
+ cmpb $0x39, %al
+ jbe 1f
+ addb $7, %al
+1:
+ movb %ah, %cl
+
+ xorw %bx, %bx
+
+ movb $0x0e, %ah
+ int $0x10
+
+ movb $0x0e, %ah
+ movb %cl, %al
+ int $0x10
+
+ movw $0x0e20, %ax
+ int $0x10
+
+ popaw
+ ret
+#else
+#if 0
+ .word 5, 0x47, 0x52, 0x4c, 0x44, 0x52, 4, 0x24
+ .word 0x49, 0x33, 0x30, 0xe000, 0, 0x3000, 0, 0
+#else
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+#endif
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+#endif
+ . = _start1 + 0x256 /* cmdcons comes here */
+
+#if 0
+ jmp 1f
+#else
+ .byte 0x90, 0x90
+#endif
+
+ . = _start1 + 0x258
+
+ .byte 0x90, 0x90
+
+ . = _start1 + 0x25a
+
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+ .byte 0x90, 0x90
+
+ . = _start1 + 0x26a
+1:
+ //movw %cs, %ax
+ //movw %ax, %ds
+ //jmp single_boot_sector
+
+ /* a value < 0x80 here means we are not booted from no-emulation-mode
+ * bootable CD.
+ */
+ movb $0x7F, %dl
+ jmp _start1
+
+#endif /* (! defined(GRLDR_INSTALL)) */
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+cdrom_helper:
+
+ /* IP and old_DS is on the stack. */
+
+ /* DS=ES=40h */
+
+ /* Stack is high and safe. */
+
+ /* EAX is LBA. if EAX==0, LBA is unknown. */
+
+ /* check if the first sector is the same as the current one */
+
+ /* load the first sector onto the sector immediately follows */
+1:
+ popw %bx /* BX = old_DS = load_segment */
+ pushw %bx
+ movw %bx, %es
+ addw $0x0080, %bx /* buffer segment */
+ call load_cd_sector
+
+ /* compare the two sectors */
+ movw $0x200, %cx
+ movw %bx, %ds
+ xorw %si, %si
+ xorw %di, %di
+ cld
+ repz cmpsl
+ je load_the_rest /* 1st sector is ok, continue */
+not_grldr:
+ testw %bp, %bp
+ jz 2f
+ xorw %bp, %bp
+ xorl %eax, %eax
+2:
+ incl %eax
+ jnz 1b /* try next */
+
+cd_no_grldr:
+
+ popw %ds /* DS=load_segment */
+
+ # Here we use error message and routine in FAT32 boot sector
+ # which is also inside the 2048-byte CD sector.
+
+ movw $(msg_BootError_32 - _start1), %si
+ jmp boot_error_32
+
+load_cd_sector:
+ /* input: EAX LBA
+ * BX buffer segment(buffer offset=0)
+ * DS 0x40 (or another safe one)
+ */
+
+ movw $0x1A0, %si
+
+ /* disk address packet */
+ movl $0x00010010, (%si) /* load 1 sector each time. */
+ movw $0, 4(%si) /* buffer offset=0 */
+ movw %bx, 6(%si) /* buffer segment */
+ movl %eax, 8(%si) /* LBA lo 32 bits */
+ movl $0, 12(%si) /* LBA hi 32 bits */
+
+ pushal
+ movb $0x42, %ah
+ int $0x13
+ popal
+ ret
+
+load_the_rest:
+
+ /* load all sectors (except the first one) */
+
+ /* EAX = first sector(LBA) of GRLDR */
+
+ popw %bx /* BX = old_DS = load_segment */
+ pushw %bx
+ movw %bx, %es
+ /* 6144 = 0x1800 = 3 sectors > 4KB, this is for the additional 4KB-preset-menu at the end of grldr */
+ movw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 1 + 6144) / 2048), %cx /* sectors to load */
+1:
+ incl %eax /* next sector */
+ addw $0x0080, %bx /* buffer segment */
+
+ call load_cd_sector
+
+ loop 1b
+
+ /* loading is completed. BX=segment of the last sector. */
+
+ subw $0x0181, %bx /* decw %bx */
+ movw %bx, %ds
+
+ /* check the ending signature */
+ cmpl $0xCE1A02B0, ((grldr_signature - _start1 + 4 + STAGE2_SIZE - 1) % 2048) + 13
+ jne not_grldr
+#; je grldr_real_start /* yes. boot it! */
+
+#; /* it is not our grldr image, return and use MBR-helper. */
+#;
+#;4:
+#; //jmp grldr_real_start
+#; popw %ds
+#; ret
+
+grldr_real_start:
+
+ #; FAT_12_16 no longer be used. So comment out.
+ #;je 1f /* jc 1f */
+ #;//ZF=0 /* CF cleared, so we are coming from FAT_12_16 */
+ #;popw %dx /* discard the cluster number */
+ #;popw %dx /* this is our boot_drive/boot_partition */
+ #;1:
+
+ #; The partition number for no-emulation-mode bootable CDROM will be
+ #; set to 0xFF later(in common.c). So comment out.
+ #;cli
+ #;movw %cs, %ax
+ #;cmpw $0x1000, %ax
+ #;jne 1f
+ #;
+ #;/* CS=0x1000, may be booted from ext2 or no-emulation-mode CDROM */
+ #;
+ #;cmpw $0x1000, %di
+ #;jne 2f
+ #;cmpw $0x7c00, %bp
+ #;jne 2f
+ #;movw %es, %ax
+ #;cmpw $0x1000, %ax
+ #;jbe 2f
+ #;cmpw $0x7c00, %si
+ #;jbe 2f
+ #;movl %edx, %eax
+ #;shrl $16, %eax
+ #;jnz 2f
+ #;jecxz 1f // booted from ext2 partition
+ #;2:
+ #;// booted from no-emulation-mode bootable CDROM
+ #;movb $0xff, %dh // partition 0xff means whole drive(for CDROM)
+ #; #; if needed, 0xfe can be used as an indicator
+ #; #; here for the bootable CDROM and changed to
+ #; #; 0xff later.
+ #;1:
+ #;
+ #;//if not booted from CDROM, don't touch the boot partition number(dh)
+
+ cli
+ xorw %ax, %ax
+ movw %ax, %ss
+ movw $0x0400, %sp /* tmp use real-mode IDT as stack */
+ movw %cs, %bp /* save CS to BP */
+ call 1f
+1:
+ popw %bx /* BX=Instruction Pointer of 1b */
+ subw $(1b - _start1), %bx
+ movw %bx, %cx
+ shrw $4, %bx
+ addw %bp, %bx
+ pushw %bx /* new CS */
+ andw $0x000f, %cx
+ addw $(1f - _start1), %cx
+ pushw %cx /* new IP */
+ lret
+1:
+ pushw %cs
+ popw %ds
+
+ /* CS=DS=BX, CS:0000 = _start1 */
+
+ addw $((pre_stage2_start - _start1) >> 4), %bx
+
+ /* BX:0000 = pre_stage2_start */
+
+ cmpw $0x820, %bx
+ jb 2f
+
+ movw $((0x8200 - (pre_stage2_start - _start1) - 0x400) >> 4), %cx
+
+ /* Now CS(=DS) >= CX+0x40 */
+
+ movw %cx, %es
+ xorw %di, %di
+ xorw %si, %si
+
+ /////////////////////////////////////////////////////////////
+ //
+ // CS
+ // DS 0x820 BX
+ // _start1---------------pre_stage2_start
+ // CX+0x40---------------0x820
+ // CX
+ // ES
+ //
+ /////////////////////////////////////////////////////////////
+
+ movw $0x200, %cx /* move 2 sectors */
+ cld
+ repz movsw
+
+ pushw %es /* ES:0000 = _start */
+ pushw $(1f - _start)
+ lret /* CS=ES, CS:0000 = _start1 */
+1:
+
+ /* move BX:0000 to 0820:0000 upward since BX >= 0x820 */
+
+ cld
+
+ movw %bx, %ds
+ movw $0x820, %bx
+ movw %bx, %es
+
+ xorw %si, %si
+ xorw %di, %di
+
+ movw $6, %bx /* 64K pages: 0x20000 - 0x7ffff */
+1:
+ movw $0x8000, %cx
+ repz movsw
+ movw %ds, %ax
+ addw $0x1000, %ax
+ movw %ax, %ds
+ movw %es, %ax
+ addw $0x1000, %ax
+ movw %ax, %es
+ decw %bx
+ jnz 1b
+
+ jmp 3f
+2:
+
+ /* move BX:0000 to 0820:0000 downward since BX < 0x820 */
+
+ std
+
+ addw $0x7000, %bx
+ movw %bx, %ds
+ movw $0x7820, %bx
+ movw %bx, %es
+
+ movw $0xfffe, %si
+ movw %si, %di
+
+ movw $8, %bx /* 64K pages: 0x08200 - 0x881ff */
+1:
+ movw $0x8000, %cx
+ repz movsw
+ movw %ds, %ax
+ subw $0x1000, %ax
+ movw %ax, %ds
+ movw %es, %ax
+ subw $0x1000, %ax
+ movw %ax, %es
+ decw %bx
+ jnz 1b
+
+ cld
+
+3:
+
+ /* put the config file name */
+ xorw %ax, %ax
+ movw %ax, %es
+ movw %ax, %ds
+
+ xorl %ebp, %ebp
+
+ movb %dh, 0x820A /* this is the boot partition number */
+
+ #; clear saved_entryno so that force_cdrom_as_boot_device be cleared
+ #; later in common.c
+
+ movl %ebp, 0x820C /* EBP=0, clear saved_entryno */
+
+ movw $0x0010, %cx /* set max length of grub version string */
+ movw $0x8212, %di /* version string */
+ cld
+ /* AL is already 0. Locate the end of version string */
+ repnz scasb /* find the location of the default config file name */
+
+ jcxz 1f /* failed, will not use the default config file name */
+
+ movw $0x4e, %cx /* max length of config file name */
+
+ movw %cs, %si /* CS:0000 = _start1 */
+ shlw $4, %si /* 0000:SI = _start1 */
+
+ addw $(default_config_file - _start1), %si
+
+ //movw $(default_config_file + 0x8200 - pre_stage2_start), %si
+ cld
+ repz movsb /* move file name to the config-file field of stage2 */
+1:
+
+ movw $0x0003, %ax /* set display mode: 80*25 color text */
+ int $0x10
+
+ xorw %bx, %bx
+ movw $(launch_pre_stage2 - _start1), %si
+ call print_message /* CS:SI points to message string */
+
+ xorw %ax, %ax
+ movw %ax, %ss
+ movw $0x2000, %sp
+
+ sti
+
+ ljmp $0, $0x8200
+
+launch_pre_stage2:
+ .ascii "\r\n\r\nBooting GRLDR...\r\n"
+
+ .byte 0 /* mark the end of ascii zero string */
+
+default_config_file:
+//#ifndef PRESET_MENU_STRING
+ .ascii "/menu.lst"
+//#else
+// .ascii "[default menu is disabled]"
+//#endif
+
+ .byte 0 /* mark the end of ascii zero string */
+#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */
+
+ . = _start1 + 0x400
+
+#define ALTERNATIVE_KERNEL
+
+
+/*
+ * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004
+ *
+ * Merges LBA and CHS boot sectors to ONE FAT32 boot sector!
+ *
+ * Memory layout for GRLDR FAT32 single stage boot process:
+ *
+ * ...
+ * |-------| 1FE0:7E00
+ * |BOOTSEC| (GRUB does not use this relocation area)
+ * |RELOC. | (overwritten by kernel loaded)
+ * |-------| 1FE0:7C00
+ * ...
+ * |-------|
+ * |KERNEL | (overwrites bootsec reloc.)
+ * |LOADED | (holds 1 sector directory buffer before kernel load)
+ * |-------| 2000:0000
+ * ...
+ * |-------| 0000:7E00
+ * |BOOTSEC| GRUB always run inside this sector,
+ * |ORIGIN | no relocation.
+ * |-------| 0000:7C00
+ * ...
+ * |-------| 0060:0200
+ * | FAT | (only 1 sector buffered)
+ * |-------| 0060:0000
+ * ...
+ *
+ */
+
+/*
+; This is an LBA-enabled FreeDOS FAT32 boot sector (single sector!).
+; You can use and copy source code and binaries under the terms of the
+; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more.
+
+; Based on earlier work by FreeDOS kernel hackers, modified heavily by
+; Eric Auer and Jon Gentle in 7 / 2003.
+;
+; Features: Uses LBA and calculates all variables from BPB/EBPB data,
+; thus making partition move / resize / image-restore easier. FreeDOS
+; can boot from FAT32 partitions which start > 8 GB boundary with this
+; boot sector. Disk geometry knowledge is not needed for booting.
+;
+; Windows uses 2-3 sectors for booting (sector stage, statistics sector,
+; filesystem stage). Only using 1 sector for FreeDOS makes multi-booting
+; of FreeDOS and Windows on the same filesystem easier.
+;
+; Requirements: LBA BIOS and 386 or better CPU. Use the older CHS-only
+; boot sector if you want FAT32 on really old PCs (problems: you cannot
+; boot from > 8 GB boundary, cannot move / resize / ... without applying
+; SYS again if you use the CHS-only FAT32 boot sector).
+;
+; FAT12 / FAT16 hints: Use the older CHS-only boot sector unless you
+; have to boot from > 8 GB. The LBA-and-CHS FAT12 / FAT16 boot sector
+; needs applying SYS again after move / resize / ... a variant of that
+; boot sector without CHS support but with better move / resize / ...
+; support would be good for use on LBA harddisks.
+
+
+; Memory layout for the FreeDOS FAT32 single stage boot process:
+
+; ...
+; |-------| 1FE0:7E00
+; |BOOTSEC|
+; |RELOC. |
+; |-------| 1FE0:7C00
+; ...
+; |-------| 2000:0200
+; | FAT | (only 1 sector buffered)
+; |-------| 2000:0000
+; ...
+; |-------| 0000:7E00
+; |BOOTSEC| overwritten by the kernel, so the
+; |ORIGIN | bootsector relocates itself up...
+; |-------| 0000:7C00
+; ...
+; |-------|
+; |KERNEL | maximum size 134k (overwrites bootsec origin)
+; |LOADED | (holds 1 sector directory buffer before kernel load)
+; |-------| 0060:0000
+; ...
+*/
+
+#define BOOTGRUB /* undef this if compiled for loading FreeDOS */
+//#undef BOOTGRUB
+
+#ifdef BOOTGRUB
+#define LOADSEG 0x2000
+#define FATSEG 0x0060
+#else
+#define LOADSEG 0x0060
+#define FATSEG 0x2000
+#endif
+
+Entry_32:
+ jmp 1f
+
+ . = Entry_32 + 0x02
+
+ /* The default mode is CHS. This is for maximum compatiblity with
+ * small-sized disks, e.g., floppies.
+ *
+ * Valid values are 0x90 for CHS mode, or 0x0e for LBA mode.
+ *
+ * If the BIOS int13 supports LBA, this byte can be safely set to 0x0e.
+ *
+ * Some USB BIOSes might have bugs when using CHS mode, so the format
+ * program should set this byte to 0x0e. It seems that (generally) all
+ * USB BIOSes have LBA support.
+ *
+ * If the format program does not know whether the BIOS has LBA
+ * support, it may operate this way:
+ *
+ * if (partition_start + total_sectors_in_partition) exceeds the CHS
+ * addressing ability(especially when it is greater than 1024*256*63),
+ * the caller should set this byte to 0x0e, otherwise, set to 0x90.
+ */
+
+ .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */
+
+
+ . = Entry_32 + 0x03
+
+#ifdef BOOTGRUB
+ .ascii "GRLDR " /* OEM name string (of OS which formatted the disk). */
+#endif
+
+ . = Entry_32 + 0x0b
+
+ .word 0x200 /* bytes per sector. Must be 512 */
+
+ . = Entry_32 + 0x0d
+
+ /* Sectors per cluster. Valid values are 1, 2, 4, 8, 16, 32, 64 and 128.
+ * But a cluster size larger than 32K should not occur.
+ */
+
+ .byte 1 /* sectors per cluster */
+
+ . = Entry_32 + 0x0e
+
+ /* Reserved sectors(number of sectors before the first FAT,
+ * including the boot sector), usually 1.
+ */
+
+ .word 1 /* reserved sectors */
+
+ . = Entry_32 + 0x10
+
+ /* Number of FATs(nearly always 2). */
+
+ .byte 2 /* number of FATs */
+
+ . = Entry_32 + 0x11
+
+ /* (Maximum number of root directory entries)Must be 0. */
+
+ .word 0 /* Max dir entries for FAT12/FAT16 */
+
+ . = Entry_32 + 0x13
+
+ /* (Total number of sectors for small disks only)Must be 0. */
+
+ .word 0 /* total sectors for FAT12/FAT16 */
+
+ . = Entry_32 + 0x15
+
+ /* Media descriptor byte, pretty meaningless now. */
+
+ .byte 0xf8 /* media descriptor */
+
+ . = Entry_32 + 0x16
+
+ /* (Sectors per FAT)Must be 0. */
+
+ .word 0 /* sectors per FAT for FAT12/FAT16 */
+
+ . = Entry_32 + 0x18
+
+ .word 18 /* sectors per track */
+
+ . = Entry_32 + 0x1a
+
+ .word 2 /* number of heads */
+
+ . = Entry_32 + 0x1c
+
+ /* Number of hidden sectors (those preceding the boot sector).
+ * Also referred to as the starting sector of the partition.
+ * For floppies, it should be 0.
+ */
+
+ .long 0 /* hidden sectors */
+
+ . = Entry_32 + 0x20
+
+ /* Total number of sectors in the filesystem. */
+
+ .long 0 /* total sectors for FAT32 */
+
+ . = Entry_32 + 0x24
+
+ /* FAT32 sectors per FAT. */
+
+ .long 0
+
+ . = Entry_32 + 0x28
+
+ /* If bit 7 is clear then all FATs are updated, otherwise bits 0-3
+ * give the current active FAT, all other bits are reserved.
+ * This word is not used by grldr boot code.
+ */
+
+ .word 0
+
+ . = Entry_32 + 0x2a
+
+ /* High byte is major revision number, low byte is minor revision
+ * number, currently both are 0.
+ * This word is not used by grldr boot code.
+ */
+
+ .word 0
+
+ . = Entry_32 + 0x2c
+
+ /* Root directory starting cluster. */
+
+ .long 0
+
+ . = Entry_32 + 0x30
+
+ /* File system information sector number.
+ * This word is not used by grldr boot code.
+ */
+
+ .word 0
+
+ . = Entry_32 + 0x32
+
+ /* If non-zero this gives the sector which holds a copy of the
+ * boot record, usually 6.
+ * This word is not used by grldr boot code.
+ */
+
+ .word 6
+
+ . = Entry_32 + 0x34
+
+ /* Reserved, 12 bytes, set to 0. */
+
+ .long 0
+ .long 0
+ .long 0
+
+ . = Entry_32 + 0x40
+
+ /* drive number of the boot device.
+ * This byte is ignored for read. The program will write DL onto
+ * this byte. The caller should set drive number in DL.
+ * We assume all BIOSes pass correct drive number in DL.
+ * That is to say, buggy BIOSes are not supported!!
+ */
+
+ .byte 0
+
+ . = Entry_32 + 0x41
+
+ /* partition number of this filesystem in the boot drive.
+ * This byte is ignored for read. The boot code will write partition
+ * number onto this byte. See Entry + 0x5d below.
+ */
+
+ .byte 0
+
+ . = Entry_32 + 0x42
+
+ /* Signature (must be 28h or 29h to be recognised by NT). */
+
+ .byte 0x29 /* extended boot signature for FAT12/FAT16 */
+
+ . = Entry_32 + 0x43
+
+ .long 0x0AC4AF63 /* volume serial number */
+
+ . = Entry_32 + 0x47
+
+ .ascii "NO NAME " /* volume label, 11 bytes. */
+
+ . = Entry_32 + 0x52
+
+ .ascii "FAT32 " /* filesystem ID, 8 bytes. */
+
+/*
+; bp is initialized to 7c00h
+; %define bsOemName bp+0x03 ; OEM label (8)
+%define bsBytesPerSec bp+0x0b ; bytes/sector (dw)
+%define bsSecPerClust bp+0x0d ; sectors/allocation unit (db)
+%define bsResSectors bp+0x0e ; # reserved sectors (dw)
+%define bsFATs bp+0x10 ; # of fats (db)
+; %define bsRootDirEnts bp+0x11 ; # of root dir entries (dw, 0 for FAT32)
+ ; (FAT32 has root dir in a cluster chain)
+; %define bsSectors bp+0x13 ; # sectors total in image (dw, 0 for FAT32)
+ ; (if 0 use nSectorHuge even if FAT16)
+; %define bsMedia bp+0x15 ; media descriptor: fd=2side9sec, etc... (db)
+; %define sectPerFat bp+0x16 ; # sectors in a fat (dw, 0 for FAT32)
+ ; (FAT32 always uses xsectPerFat)
+%define sectPerTrack bp+0x18 ; # sectors/track
+; %define nHeads bp+0x1a ; # heads (dw)
+%define nHidden bp+0x1c ; # hidden sectors (dd)
+; %define nSectorHuge bp+0x20 ; # sectors if > 65536 (dd)
+%define xsectPerFat bp+0x24 ; Sectors/Fat (dd)
+ ; +0x28 dw flags (for fat mirroring)
+ ; +0x2a dw filesystem version (usually 0)
+%define xrootClst bp+0x2c ; Starting cluster of root directory (dd)
+ ; +0x30 dw -1 or sector number of fs.-info sector
+ ; +0x32 dw -1 or sector number of boot sector backup
+ ; (+0x34 .. +0x3f reserved)
+%define drive bp+0x40 ; Drive number
+ bp+0x41 ; partition number for GRLDR
+
+%define fat_sector bp+0x44 ; last accessed FAT sector (dd)
+ ; (overwriting unused bytes)
+%define fat_start bp+0x48 ; first FAT sector (dd)
+ ; (overwriting unused bytes)
+%define data_start bp+0x4c ; first data sector (dd)
+ ; (overwriting unused bytes)
+
+*/
+ /* not used: [0x42] = byte 0x29 (ext boot param flag)
+ * [0x43] = dword serial
+ * [0x47] = label (padded with 00, 11 bytes)
+ * [0x52] = "FAT32",32,32,32 (not used by Windows)
+ * ([0x5a] is where FreeDOS parts start)
+ */
+
+ . = Entry_32 + 0x5a
+1:
+ cli
+ cld
+
+#ifdef BOOTGRUB
+
+ . = Entry_32 + 0x5c
+
+ /* the byte at offset 0x5d stores the real partition number for read.
+ * the format program or the caller should set it to a correct value.
+ * For floppies, it should be 0xff, which stands for whole drive.
+ */
+
+ movb $0xff, %dh /* boot partition number */
+
+ cmpb $0xff, %dh /* is floppy? */
+ jne 1f
+ movb $0, %dl /* yes, let drive number = 0 */
+1:
+#endif
+
+ xorw %ax, %ax
+ movw %ax, %ds
+ movw $0x7c00, %bp
+
+#ifdef BOOTGRUB
+ movw %ax, %es
+#else
+ movw $0x1fe0, %ax
+ movw %ax, %es
+ movw %bp, %si /* move from 0000:7c00 */
+ movw %bp, %di /* move to 1fe0:7c00 */
+ movw $0x0100, %cx /* one sector to move */
+ repz movsw
+ ljmp $0x1fe0, $(1f - Entry_32 + 0x7c00)
+1:
+ movw %ax, %ds
+#endif
+ movw %ax, %ss /* stack and BP-relative moves up, too */
+ leaw -0x20(%bp), %sp
+ sti
+ movw %dx, 0x40(%bp) /* BIOS passes drive number in DL */
+
+ movb $0x41, %ah
+ movw $0x55AA, %bx
+ int $0x13
+ jc 1f /* No EBIOS */
+ cmpw $0xAA55, %bx
+ jne 1f /* No EBIOS */
+ testb $1, %cl
+ jz 1f /* No EBIOS */
+ /* EBIOS supported */
+ movb $0x42, (ebios_32 - 1 - Entry_32 + 0x7c00)
+1:
+
+/* figure out where FAT and DATA area starts
+ * (modifies EAX EDX, sets fat_start and data_start variables)
+ */
+ xorl %eax, %eax
+ movl %eax, 0x44(%bp) /* init buffer status */
+
+ /* first, find fat_start */
+ movw 0x0e(%bp), %ax /* reserved sectors */
+ addl 0x1c(%bp), %eax /* hidden sectors */
+ movl %eax, 0x48(%bp) /* first FAT sector */
+ movl %eax, 0x4c(%bp) /* first data sector, initial value */
+
+ /* next, find data_start */
+ movl 0x10(%bp), %eax /* number of fats, no movzbl needed: the
+ 2 words after 0x10(%bp) are 0 for fat32 */
+ mull 0x24(%bp) /* sectors per fat (EDX=0) */
+ addl %eax, 0x4c(%bp) /* first DATA sector */
+
+/* Searches for the file in the root directory.
+ * Returns: EAX = first cluster of file
+ */
+
+ movl 0x2c(%bp), %eax /* root dir cluster */
+
+1:
+ pushl %eax /* save cluster */
+ call cluster_to_lba_32
+ /* EDX is sectors per cluster, EAX is sector number */
+ movw $(msg_BootError_32 - Entry_32 + 0x7c00), %si
+ jc boot_error_32 /* EOC encountered */
+
+2:
+ lesw (loadseg_off_32 - Entry_32)(%bp), %bx /* load to loadseg:0 */
+ call readDisk_32
+
+ xorw %di, %di
+
+ /* Search for kernel file name, and find start cluster */
+3:
+ movw $11, %cx
+ movw $(filename_32 - Entry_32 + 0x7c00), %si
+ repz cmpsb
+ jz 1f /* note that di now is at dirent+11 */
+
+ addw $0x20, %di
+ andw $-0x20, %di /* 0xffe0 */
+ cmp 0x0b(%bp), %di /* bytes per sector */
+ jnz 3b /* next directory entry */
+
+ decw %dx /* initially DX holds sectors per cluster */
+ jnz 2b /* loop over sectors in cluster */
+
+ popl %eax /* restore current cluster */
+ call next_cluster_32
+ jmp 1b /* read next cluster */
+
+#ifndef ALTERNATIVE_KERNEL
+loadseg_off_32:
+ .word 0
+ .word LOADSEG
+#endif
+
+1:
+ /* kernel directory entry is found */
+ pushw %es:(0x14-11)(%di) /* get cluster number HI */
+ pushw %es:(0x1a-11)(%di) /* get cluster number LO */
+ popl %eax /* convert to 32bit */
+
+ xorw %bx, %bx /* read kernel at ES:BX=LOADSEG:0 */
+
+/* read kernel */
+
+2:
+ pushl %eax
+ call cluster_to_lba_32
+ /* EDX is sectors per cluster, EAX is sector number */
+ jnc 1f
+
+ /* EOC encountered - done */
+#ifdef BOOTGRUB
+ movw 0x40(%bp), %dx /* boot_drive and boot_partition */
+#else
+ movb 0x40(%bp), %bl /* FreeDOS kernel uses BL, not DL, for drive */
+#endif
+ ljmp *(loadseg_off_32 - Entry_32)(%bp)
+
+1:
+ call readDisk_32
+ decw %dx /* initially DX holds sectors per cluster */
+ jnz 1b /* loop over sectors in cluster */
+
+ popl %eax
+ call next_cluster_32
+ jmp 2b
+
+/* given a cluster number, find the number of the next cluster in
+ * the FAT chain. Needs fat_start.
+ * input: EAX - cluster
+ * EDX = 0
+ * output: EAX - next cluster
+ * EDX = undefined
+ */
+
+next_cluster_32:
+ pushw %es
+ /* pushw %di */
+ pushw %bx /* hi word of EBX never used */
+
+#if 1
+ /* xorl %edx, %edx */
+ shll $2, %eax /* 32bit FAT */
+ movzwl 0x0b(%bp), %ebx /* bytes per sector */
+ divl %ebx /* residue is in EDX */
+ /* movw %dx, %di */
+#else
+ shll $2, %eax /* 32bit FAT */
+ ;xchgw %ax, %di /* movw %ax, %di */
+ movw %ax, %di
+ ;shlw $2, %di /* 32bit FAT */
+
+ pushw %cx
+ movw 0x0b(%bp), %bx /* bytes per sector */
+ bsfw %bx, %cx
+ ;decw %cx
+ ;decw %cx
+ decw %bx
+ andw %bx, %di /* mask to sector size */
+ shrl %cl, %eax
+ popw %cx
+#endif
+ addl 0x48(%bp), %eax /* add the first FAT sector number.
+ EAX is absolute sector number now */
+ movw $FATSEG, %bx
+ movw %bx, %es
+ xorw %bx, %bx
+
+ cmpl 0x44(%bp), %eax /* is it the last accessed and already buffered
+ FAT sector? */
+ jz 1f
+ movl %eax, 0x44(%bp) /* mark sector EAX as buffered */
+ call readDisk_32 /* read sector EAX to buffer */
+1:
+#if 1
+ //.byte 0x67, 0x26, 0x80, 0x62, 0x03, 0x0f
+ addr32 andb $0x0f, %es:3(%edx) /* mask out top 4 bits */
+
+ //.byte 0x67, 0x66, 0x26, 0x8b, 0x02
+ addr32 movl %es:(%edx), %eax /* read next cluster number */
+#else
+ andb $0x0f, %es:3(%di) /* mask out top 4 bits */
+ movl %es:(%di), %eax /* read next cluster number */
+#endif
+ popw %bx
+ /* popw %di */
+ popw %es
+ ret
+
+/* Convert cluster number to the absolute sector number
+ * ... or return carry if EndOfChain! Needs data_start.
+ * input: EAX - target cluster
+ * output: EAX - absolute sector
+ * EDX - [bsSectPerClust] (byte)
+ * carry clear
+ * (if carry set, EAX/EDX unchanged, end of chain)
+ */
+
+cluster_to_lba_32:
+ cmpl $0x0ffffff8, %eax /* check End Of Chain */
+ cmc
+ jb 1f /* carry is stored if EOC */
+
+ /* sector = (cluster-2) * clustersize + data_start */
+ decl %eax
+ decl %eax
+
+ movzbl 0x0d(%bp), %edx /* sectors per cluster */
+ pushw %dx /* only DX would change */
+ mull %edx /* EDX = 0 */
+ popw %dx
+ addl 0x4c(%bp), %eax /* data_start */
+ /* here, carry is cleared (unless parameters are wrong) */
+1:
+ ret
+
+/* Read a sector from disk, using LBA or CHS
+ * input: EAX - 32-bit DOS sector number
+ * ES:BX - destination buffer
+ * (will be filled with 1 sector of data)
+ * output: ES:BX points one byte after the last byte read.
+ * EAX - next sector
+ */
+
+readDisk_32:
+ pushal
+ xorl %edx, %edx /* EDX:EAX = LBA */
+ pushl %edx /* hi 32bit of sector number */
+ pushl %eax /* lo 32bit of sector number */
+ pushw %es /* buffer segment */
+ pushw %bx /* buffer offset */
+ pushw $1 /* 1 sector to read */
+ pushw $16 /* size of this parameter block */
+
+ xorl %ecx, %ecx
+ pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */
+ popw %cx /* ECX = sectors per track */
+ divl %ecx /* residue is in EDX */
+ /* quotient is in EAX */
+ incw %dx /* sector number in DL */
+ popw %cx /* ECX = number of heads */
+ pushw %dx /* push sector number into stack */
+ xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */
+ divl %ecx /* residue is in EDX, head number */
+ /* quotient is in EAX, cylinder number */
+ xchgb %dl, %dh /* head number should be in DH */
+ /* DL = 0 */
+ popw %cx /* pop sector number from stack */
+ xchgb %al, %ch /* lo 8bit cylinder should be in CH */
+ /* AL = 0 */
+ shlb $6, %ah /* hi 2bit cylinder ... */
+ orb %ah, %cl /* ... should be in CL */
+
+ movw $0x201, %ax /* read 1 sector */
+ebios_32: /* ebios_32 - 1 points to 0x02 that can be changed to 0x42 */
+
+// cmpb $0x0e, 2(%bp) /* force LBA? */
+// jnz 1f /* no, continue */
+// movb $0x42, %ah /* yes, use extended disk read */
+//1:
+ movw %sp, %si /* DS:SI points to disk address packet */
+ movb 0x40(%bp), %dl /* hard disk drive number */
+ int $0x13
+ popaw /* remove parameter block from stack */
+ popal
+ jc disk_error_32 /* disk read error, jc 1f if caller handles */
+ incl %eax /* next sector */
+ addw 0x0b(%bp), %bx /* bytes per sector */
+ jnc 1f /* 64K bound check */
+ pushw %dx
+ movw %es, %dx
+ addb $0x10, %dh /* add 1000h to ES */
+ /* here, carry is cleared */
+ movw %dx, %es
+ popw %dx
+1:
+ /* carry stored on disk read error */
+ ret
+
+ . = . - (. - readDisk_32)/91
+
+msg_DiskReadError_32:
+
+ .ascii "disk error\0"
+
+msg_BootError_32:
+
+ .ascii "No "
+
+filename_32:
+
+#ifdef BOOTGRUB2
+ .ascii "G2LDR \0"
+#elif defined (BOOTGRUB)
+ .ascii "GRLDR \0"
+#else
+ .ascii "KERNEL SYS\0"
+#endif
+
+#ifdef ALTERNATIVE_KERNEL
+filename_end_32:
+
+ . = Entry_32 + 0x1e8
+
+loadseg_off_32:
+ .word 0
+ .word LOADSEG
+
+ . = Entry_32 + 0x1ec
+
+boot_image_ofs_32:
+
+ .word (filename_32 - Entry_32)+(filename_end_32 - filename_32 - 1)*2048
+#endif
+
+ . = Entry_32 + 0x1ee
+
+disk_error_32:
+
+ movw $(msg_DiskReadError_32 - Entry_32 + 0x7c00), %si
+
+boot_error_32:
+
+/* prints string DS:SI (modifies AX BX SI) */
+
+//print_32:
+1:
+ lodsb (%si), %al /* get token */
+ //xorw %bx, %bx /* video page 0 */
+ movb $0x0e, %ah /* print it */
+ int $0x10 /* via TTY mode */
+ cmpb $0, %al /* end of string? */
+ jne 1b /* until done */
+
+ /* The caller will change this to
+ * ljmp $0x9400, $(try_next_partition - _start1)
+ */
+
+1: jmp 1b
+
+ . = Entry_32 + 0x1fc
+
+ .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */
+
+ . = Entry_32 + 0x200
+
+ . = _start1 + 0x600
+
+ //.arch i8086, nojumps
+ .arch i186, nojumps
+/*
+ * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004
+ *
+ * Merges FAT12 and FAT16 boot sectors to ONE FAT boot sector!
+ *
+ * Memory layout for GRLDR FAT single stage boot process:
+ *
+ * +--------+
+ * | |
+ * |GRLDR | also used as max 128k FAT buffer
+ * |LOADED | before GRLDR loading starts
+ * |--------| 2000:0000
+ * | |
+ * |--------| 0000:7E00
+ * |BOOTSECT|
+ * |ORIGIN |
+ * |--------| 0000:7C00
+ * | |
+ * |--------| 0000:3000
+ * |CLUSTER |
+ * |LIST |
+ * |--------| 0000:2000
+ * | |
+ * +--------+
+ */
+
+/*
+;
+; File:
+; boot.asm
+; Description:
+; DOS-C boot
+;
+; Copyright (c) 1997;
+; Svante Frey
+; All Rights Reserved
+;
+; This file is part of DOS-C.
+;
+; DOS-C is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation; either version
+; 2, or (at your option) any later version.
+;
+; DOS-C is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+; the GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public
+; License along with DOS-C; see the file COPYING. If not,
+; write to the Free Software Foundation, 675 Mass Ave,
+; Cambridge, MA 02139, USA.
+;
+;
+; +--------+ 1FE0:7E00
+; |BOOT SEC|
+; |RELOCATE|
+; |--------| 1FE0:7C00
+; | |
+; |--------| 1FE0:3000
+; | CLUSTER|
+; | LIST |
+; |--------| 1FE0:2000
+; | |
+; |--------| 0000:7E00
+; |BOOT SEC| overwritten by max 128k FAT buffer
+; |ORIGIN | and later by max 134k loaded kernel
+; |--------| 0000:7C00
+; | |
+; |--------|
+; |KERNEL | also used as max 128k FAT buffer
+; |LOADED | before kernel loading starts
+; |--------| 0060:0000
+; | |
+; +--------+
+*/
+
+#ifdef BOOTGRUB
+#define LOADSEG_12_16 0x2000
+#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */
+#else
+#define LOADSEG_12_16 0x0060
+#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */
+#endif
+
+Entry_12_16:
+ jmp 1f
+
+ . = Entry_12_16 + 0x02
+
+ /* The default mode is CHS. This is for maximum compatiblity with
+ * small-sized disks, e.g., floppies.
+ *
+ * Valid values are 0x90 for CHS mode, or 0x0e for LBA mode.
+ *
+ * If the BIOS int13 supports LBA, this byte can be safely set to 0x0e.
+ *
+ * Some USB BIOSes might have bugs when using CHS mode, so the format
+ * program should set this byte to 0x0e. It seems that (generally) all
+ * USB BIOSes have LBA support.
+ *
+ * If the format program does not know whether the BIOS has LBA
+ * support, it may operate this way:
+ *
+ * if (partition_start + total_sectors_in_partition) exceeds the CHS
+ * addressing ability(especially when it is greater than 1024*256*63),
+ * the caller should set this byte to 0x0e, otherwise, set to 0x90.
+ */
+
+ .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */
+
+
+ . = Entry_12_16 + 0x03
+
+#ifdef BOOTGRUB
+ .ascii "GRLDR "
+#endif
+
+ . = Entry_12_16 + 0x0b
+
+ .word 0x200 /* bytes per sector */
+
+ . = Entry_12_16 + 0x0d
+
+ .byte 1 /* sectors per cluster */
+
+ . = Entry_12_16 + 0x0e
+
+ .word 1 /* reserved sectors */
+
+ . = Entry_12_16 + 0x10
+
+ .byte 2 /* number of FATs */
+
+ . = Entry_12_16 + 0x11
+
+ .word 224 /* Max dir entries */
+
+ . = Entry_12_16 + 0x13
+
+ .word 2880 /* total sectors in the filesystem */
+
+ . = Entry_12_16 + 0x15
+
+ .byte 0xf0 /* media descriptor */
+
+ . = Entry_12_16 + 0x16
+
+ .word 9 /* sectors per FAT */
+
+ . = Entry_12_16 + 0x18
+
+ .word 18 /* sectors per track */
+
+ . = Entry_12_16 + 0x1a
+
+ .word 2 /* number of heads */
+
+ . = Entry_12_16 + 0x1c
+
+ .long 0 /* hidden sectors */
+
+ . = Entry_12_16 + 0x20
+
+ .long 0 /* total sectors for large partitions */
+
+ . = Entry_12_16 + 0x24
+
+ /* drive number of the boot device.
+ * This byte is ignored for read. The program will write DL onto
+ * this byte. The caller should set drive number in DL.
+ * We assume all BIOSes pass correct drive number in DL.
+ * That is to say, buggy BIOSes are not supported!!
+ */
+
+ .byte 0
+
+ . = Entry_12_16 + 0x25
+
+ /* partition number of this filesystem in the boot drive.
+ * This byte is ignored for read. The boot code will write partition
+ * number onto this byte. See Entry_12_16 + 0x41 below.
+ */
+
+ .byte 0
+
+ . = Entry_12_16 + 0x26
+
+ .byte 0x29 /* extended boot signature */
+
+ . = Entry_12_16 + 0x27
+
+ .long 0x0AC4AF63 /* volume serial number */
+
+ . = Entry_12_16 + 0x2b
+
+ .ascii "NO NAME " /* volume label */
+
+ . = Entry_12_16 + 0x36
+
+ .ascii "FAT12 " /* filesystem ID */
+
+/*
+; bp is initialized to 7c00h
+%define bsOemName bp+0x03 ; OEM label
+%define bsBytesPerSec bp+0x0b ; bytes/sector
+%define bsSecPerClust bp+0x0d ; sectors/allocation unit
+%define bsResSectors bp+0x0e ; # reserved sectors
+%define bsFATs bp+0x10 ; # of fats
+%define bsRootDirEnts bp+0x11 ; # of root dir entries
+%define bsSectors bp+0x13 ; # sectors total in image
+%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc...
+%define sectPerFat bp+0x16 ; # sectors in a fat
+%define sectPerTrack bp+0x18 ; # sectors/track
+%define nHeads bp+0x1a ; # heads
+%define nHidden bp+0x1c ; # hidden sectors
+%define nSectorHuge bp+0x20 ; # sectors if > 65536
+%define drive bp+0x24 ; drive number
+ bp+0x25 ; partition number for GRLDR
+%define extBoot bp+0x26 ; extended boot signature
+%define volid bp+0x27
+%define vollabel bp+0x2b
+%define filesys bp+0x36
+
+%define RootDirSecs bp+0x26 ; # of sectors root dir uses
+ ; (overwriting unused bytes)
+%define fat_start bp+0x28 ; first FAT sector
+ ; (overwriting unused bytes)
+%define root_dir_start bp+0x2c ; first root directory sector
+ ; (overwriting unused bytes)
+%define data_start bp+0x30 ; first data sector
+ ; (overwriting unused bytes)
+%define data_clusters bp+0x34 ; # of clusters in data area
+ ; (overwriting unused bytes)
+ bp+0x36 ; bytes per FAT( > 0x1800 means FAT16)
+ ; (overwriting unused bytes)
+*/
+ /* not used: [0x26] = byte 0x29 (ext boot param flag)
+ * [0x27] = dword serial
+ * [0x2b] = label (padded with 00, 11 bytes)
+ * [0x36] = "FAT12" or "FAT16",32,32,32 (not used by Windows)
+ * ([0x3e] is where FreeDOS parts start)
+ */
+
+ . = Entry_12_16 + 0x3e
+1:
+ cli
+ cld
+
+#ifdef BOOTGRUB
+
+ . = Entry_12_16 + 0x40
+
+ /* the byte at offset 0x41 stores the real partition number for read.
+ * the format program or the caller should set it to a correct value.
+ * For floppies, it should be 0xff, which stands for whole drive.
+ */
+
+ movb $0xff, %dh /* boot partition number */
+
+ cmpb $0xff, %dh /* is floppy? */
+ jne 1f
+ movb $0, %dl /* yes, let drive number = 0 */
+1:
+#endif
+
+ xorw %ax, %ax
+ movw %ax, %ds
+ movw $0x7c00, %bp
+
+#ifdef BOOTGRUB
+ movw %ax, %es
+ movw %ax, %ss /* stack and BP-relative moves up, too */
+ leaw -0x20(%bp), %sp
+ sti
+ movw %dx, 0x24(%bp) /* BIOS passes drive number in DL */
+ /* AX=0 */
+// xchgw %ax, %dx /* let DX = 0 */
+// xorw %cx, %cx /* CX = 0 */
+#else
+ movw %bp, %si /* move from 0000:7c00 */
+ movw %bp, %di /* move to 1fe0:7c00 */
+ movb %dl, 0x24(%si) /* BIOS passes drive number in DL */
+// xchgw %ax, %dx /* let DX = 0 */
+ movw $0x1fe0, %ax
+ movw %ax, %es
+ movw $0x0100, %cx /* one sector to move */
+ repz movsw
+ /* CX = 0 */
+ ljmp $0x1fe0, $(1f - Entry_12_16 + 0x7c00)
+1:
+ movw %ax, %ds
+ movw %ax, %ss /* stack and BP-relative moves up, too */
+ leaw -0x20(%bp), %sp
+ sti
+ /* AX=0x1fe0 */
+#endif
+
+ movb $0x41, %ah
+ movw $0x55AA, %bx
+ int $0x13
+ jc 1f /* No EBIOS */
+ cmpw $0xAA55, %bx
+ jne 1f /* No EBIOS */
+ testb $1, %cl
+ jz 1f /* No EBIOS */
+ /* EBIOS supported */
+ movb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00)
+1:
+// xorw %cx, %cx
+ xorw %ax, %ax
+
+ /* GET DRIVE PARMS: Calculate start of some disk areas */
+
+ movw 0x1c(%bp), %si /* number of hidden sectors(lo) */
+ movw 0x1e(%bp), %di /* number of hidden sectors(hi) */
+ addw 0x0e(%bp), %si /* number of reserved sectors */
+ adcw %ax, %di /* DI:SI = first FAT sector */
+ /* AX = 0 */
+
+ movw %si, 0x28(%bp) /* FAT start sector(lo) */
+ movw %di, 0x2a(%bp) /* FAT start sector(hi) */
+
+ //xchgw %ax, %dx /* let AX = 0 */
+ movb 0x10(%bp), %al /* number of FATs */
+ /* cbw */
+ mulw 0x16(%bp) /* sectors per FAT */
+ /* DX:AX = total number of FAT sectors */
+ /* DX = 0 since no too many FAT sectors */
+ addw %ax, %si
+ adcw %dx, %di /* DI:SI = root directory start sector */
+ movw %si, 0x2c(%bp) /* root directory starting sector(lo) */
+ movw %di, 0x2e(%bp) /* root directory starting sector(hi) */
+
+ /* Calculate how many sectors the root directory occupies */
+
+ movw 0x0b(%bp), %bx /* bytes per sector */
+ movb $5, %cl /* divide BX by 32 */
+ shrw %cl, %bx /* BX = directory entries per sector */
+
+ movw 0x11(%bp), %ax /* max number of root dir entries */
+ /* xorw %dx, %dx */ /* assuming DX = 0 */
+ divw %bx /* AX = sectors per root directory */
+ /* DX = 0 since normally no residue */
+
+ movw %ax, 0x26(%bp) /* number of sectors the root dir occupies */
+
+ addw %ax, %si /* DI:SI = first data sector */
+ adcw %dx, %di /* assuming DX = 0 */
+
+ movw %si, 0x30(%bp) /* data starting sector(lo) */
+ movw %di, 0x32(%bp) /* data starting sector(hi) */
+#ifdef USE_TOTAL_CLUSTERS
+ movw 0x13(%bp), %cx /* total sectors(small) */
+ jcxz 1f
+ movw %cx, 0x20(%bp) /* total sectors(large)(lo) */
+ movw %dx, 0x22(%bp) /* total sectors(large)(hi), assuming DX = 0 */
+1:
+ movw 0x20(%bp), %ax /* total sectors(large) */
+ movw 0x22(%bp), %bx
+ addw 0x1c(%bp), %ax /* number of hidden sectors */
+ adcw 0x1e(%bp), %bx
+ subw %si, %ax /* data starting sector */
+ sbbw %di, %bx /* BX:AX = total sectors in the data area */
+ movb 0x0d(%bp), %dl /* sectors per cluster(DH=0) */
+ xchgw %bx, %dx /* DX:AX = total sectors in the data area */
+ /* BX = sectors per cluster */
+ divw %bx /* AX = total clusters in the data area */
+ movw %ax, 0x34(%bp) /* total clusters in the data area */
+#else
+ movw $0xffff, 0x36(%bp)
+ movw 0x16(%bp), %ax /* sectors per FAT */
+ mulw 0x0b(%bp) /* bytes per sector */
+ jc 1f
+ movw %ax, 0x36(%bp)
+1:
+#endif
+ /* Searches for the file in the root directory
+ *
+ * Returns:
+ * AX = first cluster of file
+ */
+
+ /* First, read the whole root directory into the temporary buffer */
+
+ movw 0x2c(%bp), %ax /* root directory starting sector(lo) */
+ movw 0x2e(%bp), %dx /* root directory starting sector(hi) */
+ movw 0x26(%bp), %di /* number of sectors the root dir occupies */
+ lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx
+ /* ES:BX = loadseg:0 */
+ call readDisk_12_16
+
+ lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %di
+ /* ES:DI = loadseg:0 */
+
+
+ /* Search for kernel file name, and find start cluster */
+
+1:
+ movw $11, %cx
+ movw $(filename_12_16 - Entry_12_16 + 0x7c00), %si
+ pushw %di
+ repz cmpsb
+ popw %di
+ movw %es:0x1a(%di), %ax /* get cluster number from dir entry */
+ jz 1f
+
+ addw $0x20, %di /* go to next directory entry */
+ cmpb %ch, %es:(%di) /* if the first byte of the name is 0, */
+ /* there is no more files in the directory */
+ /* assuming CH = 0 */
+ jnz 1b
+ movw $(msg_BootError_12_16 - Entry_12_16 + 0x7c00), %si
+ jmp boot_error_12_16 /* fail if not found */
+
+#ifndef ALTERNATIVE_KERNEL
+loadseg_off_12_16: .word 0
+loadseg_seg_12_16: .word LOADSEG_12_16
+#endif
+
+1:
+ pushw %ax /* store first cluster number */
+ /* CX = 0 */
+
+
+ /* Reads the FAT chain and stores it in a temporary buffer in the first
+ * 64KB. The FAT chain is stored an array of 16-bit cluster numbers,
+ * ending with 0.
+ *
+ * The file must fit in conventional memory, so it can't be larger than
+ * 640KB. The sector size must be at least 512 bytes, so the FAT chain
+ * can't be larger than around 3KB.
+ *
+ * Call with: AX = first cluster in chain
+ */
+
+ /* Load the complete FAT into memory. The FAT can't be larger
+ * than 128 kb, so it should fit in the temporary buffer.
+ */
+
+ lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx
+ /* ES:BX = loadseg:0 */
+ movw 0x16(%bp), %di /* sectors per FAT */
+ movw 0x28(%bp), %ax /* FAT start sector(lo) */
+ movw 0x2a(%bp), %dx /* FAT start sector(hi) */
+ call readDisk_12_16
+ popw %ax /* restore first cluster number */
+
+ /* Set ES:DI to the temporary storage for the FAT chain */
+ pushw %ds
+ popw %es
+ movw (loadseg_seg_12_16 - Entry_12_16)(%bp), %ds
+ movw $FATBUF, %di
+
+2:
+ stosw /* store cluster number */
+ movw %ax, %si /* SI = cluster number */
+ addw %si, %si /* multiply cluster number by two */
+ movw (loadseg_seg_12_16 - Entry_12_16)(%bp), %dx
+ /* segment for FAT16 */
+ jnc 1f
+ addb $0x10, %dh /* overflow. Add 0x1000 to segment value */
+1:
+
+#ifdef USE_TOTAL_CLUSTERS
+ cmpw $0x0ff7, 0x34(%bp) /* total clusters in the data area */
+#else
+ cmpw $0x1801, 0x36(%bp) /* bytes per FAT */
+#endif
+ jnb 3f
+
+ /* This is a FAT12 disk */
+
+ addw %ax, %si /* multiply cluster number by 3 ... */
+ shrw $1, %si /* ... and divide by 2 */
+ lodsw
+
+ /* If the cluster number was even, the cluster value is now in
+ * bits 0-11 of AX. If the cluster number was odd, the cluster
+ * value is in bits 4-15, and must be shifted right 4 bits. If
+ * the number was odd, CF was set in the last shift instruction.
+ */
+
+ jnc 1f
+ movb $4, %cl
+ shrw %cl, %ax
+1:
+ andb $0x0f, %ah /* mask off the highest 4 bits */
+ cmpw $0x0ff7, %ax /* check for EOF */
+ jmp 4f
+
+3:
+ /* This is a FAT16 disk. The maximal size of a 16bit FAT
+ * is 128KB, so it may not fit within a single 64KB segment
+ */
+
+ movw %dx, %ds /* DS:SI points to next cluster */
+ lodsw /* AX = next cluster */
+
+ cmpw $0xfff7, %ax /* check for EOF */
+4:
+ jbe 2b /* continue if not EOF */
+
+ /* Mark end of FAT chain with 0, so we have a single
+ * EOF marker for both FAT12 and FAT16 systems.
+ */
+
+ xorw %ax, %ax
+ stosw
+
+ pushw %cs
+ popw %ds
+
+ /* Loads the file into memory, one cluster at a time */
+
+ lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx
+ /* ES:BX = loadseg:0 */
+ movw $FATBUF, %si /* set DS:SI to the FAT chain */
+
+2:
+ lodsw /* AX = next cluster to read */
+ orw %ax, %ax
+ jnz 1f
+
+ /* EOC encountered - done */
+#ifdef BOOTGRUB
+ movw 0x24(%bp), %dx /* boot_drive and boot_partition */
+#else
+ movb 0x24(%bp), %bl /* FreeDOS kernel uses BL, not DL, for drive */
+#endif
+ ljmp *(loadseg_off_12_16 - Entry_12_16)(%bp) /* boot it! */
+
+1:
+ decw %ax /* cluster numbers start with 2 */
+ decw %ax
+
+ movw 0x0d(%bp), %di /* sectors per cluster */
+ andw $0xff, %di /* DI = sectors per cluster */
+ mulw %di
+ addw 0x30(%bp), %ax /* data starting sector(lo) */
+ adcw 0x32(%bp), %dx /* data starting sector(hi) */
+ /* DX:AX = first sector to read */
+ call readDisk_12_16
+ jmp 2b /* read next cluster */
+
+/* Reads a number of sectors into memory.
+ *
+ * Call with: DX:AX = 32-bit DOS sector number
+ * DI = number of sectors to read
+ * ES:BX = destination buffer
+ *
+ * Returns: CF set on error
+ * ES:BX points one byte after the last byte read.
+ * DX:AX = next sector number after read
+ */
+
+readDisk_12_16:
+2:
+ pushaw
+ xorw %cx, %cx
+ pushw %cx
+ pushw %cx
+ pushw %dx
+ pushw %ax
+ pushw %es /* buffer segment */
+ pushw %bx /* buffer offset */
+ incw %cx
+ pushw %cx /* 1 sector to read */
+ movb $16, %cl
+ pushw %cx /* size of this parameter block */
+
+ xchgw %ax, %cx /* save AX to CX */
+
+ /*
+ * translate sector number to BIOS parameters
+ *
+ * LBA = sector-1 offset in track
+ * + head * sectPerTrack offset in cylinder
+ * + cyl * sectPerTrack * nHeads offset in platter
+ *
+ */
+ pushw %bx
+ movw 0x18(%bp), %ax /* sectors per track */
+ movw %ax, %bx
+ mulb 0x1a(%bp) /* nHeads, but maybe a word value 0x100 */
+ jnz 1f
+ movb %bl, %ah /* nHeads=0x100, so AX=sectPerTrack*0x100 */
+1:
+ xchgw %ax, %cx /* restore AX from CX, and save AX to CX */
+ /* DX:AX = LBA, CX = nHeads * sectPerTrack <= 256*63 */
+ divw %cx /* AX = cyl, DX = sector-1 + head * sectPerTrack */
+ xchgw %ax, %dx /* DX = cyl, AX = sector-1 + head * sectPerTrack */
+ divb %bl /* sectors per track */
+ /* DX = cyl, AL = head, AH = sector-1 */
+#if 1
+ xchgb %al, %ah /* DX = cyl, AH = head, AL = sector-1 */
+ incw %ax /* DX = cyl, AH = head, AL = sector */
+ xchgw %ax, %dx /* AX = cyl, DH = head, DL = sector */
+ xchgw %ax, %cx /* CX = cyl, DH = head, DL = sector */
+ xchgb %cl, %ch /* set cyl number low 8 bits in CH */
+ rorb $1, %cl /* move cyl high bits into bits 7-6 */
+ rorb $1, %cl /* (assumes top = 0) */
+ orb %dl, %cl /* merge sector into cylinder */
+#else
+ movw %dx, %cx /* CX = cyl, AL = head, AH = sector-1 */
+
+ /*
+ * the following manipulations are necessary in order to properly place
+ * parameters into registers.
+ * CH = cylinder number low 8 bits
+ * CL<7-6> = cylinder high two bits
+ * CL<5-0> = sector
+ */
+ movb %al, %dh /* save head into DH for BIOS */
+ xchgb %cl, %ch /* set cyl number low 8 bits in CH */
+ rorb $1, %cl /* move cyl high bits into bits 7-6 */
+ rorb $1, %cl /* (assumes top = 0) */
+ incb %ah /* AH = sector number */
+ orb %ah, %cl /* merge sector into cylinder */
+#endif
+ popw %bx
+
+ movw $0x0201, %ax /* read 1 sector */
+ebios_12_16: /* ebios_12_16 - 1 points to 0x02 that can be changed to 0x42 */
+
+// cmpb $0x0e, 2(%bp) /* force LBA? */
+// jnz 1f /* no, continue */
+// movb $0x42, %ah /* yes, use extended disk read */
+//1:
+ movw %sp, %si /* DS:SI points to disk address packet */
+ movb 0x24(%bp), %dl /* drive number */
+ int $0x13
+// stc #; only for testing the buggy Virtual PC
+ popaw /* remove parameter block from stack */
+ popaw
+ jc disk_error_12_16 /* disk read error, jc 1f if caller handles */
+ incw %ax /* next sector */
+ jnz 1f
+ incw %dx
+1:
+ addw 0x0b(%bp), %bx /* bytes per sector */
+ jnc 1f /* 64K bound check */
+ pushw %dx
+ movw %es, %dx
+ addb $0x10, %dh /* add 1000h to ES */
+ /* here, carry is cleared */
+ movw %dx, %es
+ popw %dx
+1:
+ decw %di
+ jnz 2b
+
+ /* carry stored on disk read error */
+ ret
+
+ . = . - (. - readDisk_12_16)/99
+
+msg_DiskReadError_12_16:
+
+ .ascii "disk error\0"
+
+msg_BootError_12_16:
+
+ .ascii "No "
+
+filename_12_16:
+
+#ifdef BOOTGRUB2
+ .ascii "G2LDR \0"
+#elif defined (BOOTGRUB)
+ .ascii "GRLDR \0"
+#else
+ .ascii "KERNEL SYS\0"
+#endif
+
+#ifdef ALTERNATIVE_KERNEL
+filename_end_12_16:
+
+ . = Entry_12_16 + 0x1e8
+
+loadseg_off_12_16: .word 0
+loadseg_seg_12_16: .word LOADSEG_12_16
+
+ . = Entry_12_16 + 0x1ec
+
+boot_image_ofs_12_16:
+
+ .word (filename_12_16 - Entry_12_16)+(filename_end_12_16 - filename_12_16 - 1)*2048
+#endif
+
+ . = Entry_12_16 + 0x1ee
+
+disk_error_12_16:
+
+ movw $(msg_DiskReadError_12_16 - Entry_12_16 + 0x7c00), %si
+
+boot_error_12_16:
+
+/* prints string DS:SI (modifies AX BX SI) */
+
+//print_12_16:
+1:
+ lodsb (%si), %al /* get token */
+ //xorw %bx, %bx /* video page 0 */
+ movb $0x0e, %ah /* print it */
+ int $0x10 /* via TTY mode */
+ cmpb $0, %al /* end of string? */
+ jne 1b /* until done */
+
+ /* The caller will change this to
+ * ljmp $0x9400, $(try_next_partition - _start1)
+ */
+
+1: jmp 1b
+
+ . = Entry_12_16 + 0x1fc
+
+ .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */
+
+ . = Entry_12_16 + 0x200
+
+ . = _start1 + 0x800
+
+
+
+
+ .arch i486, nojumps
+
+/*
+ #; Ext2 boot sector for GRLDR
+ */
+
+
+#define DEBUG call debug_print
+#undef DEBUG
+
+ //. = _start1 + 0x800
+
+Entry_ext2:
+
+ jmp 1f
+
+ . = Entry_ext2 + 0x02
+
+ /* The default mode is CHS. This is for maximum compatiblity with
+ * small-sized disks, e.g., floppies.
+ *
+ * Valid values are 0x02 for CHS mode, or 0x42 for LBA mode.
+ *
+ * If the BIOS int13 supports LBA, this byte can be safely set to 0x42.
+ *
+ * Some USB BIOSes might have bugs when using CHS mode, so the format
+ * program should set this byte to 0x42. It seems that (generally) all
+ * USB BIOSes have LBA support.
+ *
+ * If the format program does not know whether the BIOS has LBA
+ * support, it may operate this way:
+ *
+ * if (partition_start + total_sectors_in_partition) exceeds the CHS
+ * addressing ability(especially when it is greater than 1024*256*63),
+ * the caller should set this byte to 0x42, otherwise, set to 0x02.
+ */
+
+ .byte 0x02 /* for CHS. Another possible value is 0x42 for LBA */
+
+ . = Entry_ext2 + 0x03
+
+#if 0
+
+ .ascii "ext2 grldr"
+
+#else
+
+msg_DiskReadError_ext2:
+
+ .ascii "I/O error\0"
+
+#endif
+
+ . = Entry_ext2 + 0x0d
+
+ /* sectors per block. Valid values are 2, 4, 8, 16, 32. */
+
+ .byte 2
+
+ . = Entry_ext2 + 0x0e
+
+ /* bytes per block.
+ * Valid values are 0x400, 0x800, 0x1000, 0x2000, 0x4000.
+ */
+
+ .word 1024 /* bytes per block, at most 16K */
+
+ . = Entry_ext2 + 0x10
+
+ /* pointers in pointers-per-block blocks, that is, number of blocks
+ * covered by a double-indirect block.
+ * Valid values are 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000.
+ */
+
+ .long 0x10000 /* number of blocks covered by double-indirect block */
+ /* low word=0 */
+
+ . = Entry_ext2 + 0x14
+
+ /* pointers per block, that is, number of blocks covered by an indirect
+ * block. Valid values are 0x100, 0x200, 0x400, 0x800, 0x1000.
+ */
+
+ .long 0x100 /* high word=0, low byte=0 */
+
+ . = Entry_ext2 + 0x18
+
+ /* this is default for 1.44M floppy, the caller should set it to
+ * a correct value */
+
+ .word 18 /* sectors per track */
+
+ . = Entry_ext2 + 0x1a
+
+ /* this is default for 1.44M floppy, the caller should set it to
+ * a correct value */
+
+ .word 2 /* number of heads */
+
+ . = Entry_ext2 + 0x1c
+
+ /* this is default for 1.44M floppy, the caller should set it to
+ * a correct value */
+
+ .long 0 /* hidden sectors */
+
+ . = Entry_ext2 + 0x20
+
+ /* total sectors in the filesystem(or in the partition).
+ * This value is informative. The code does not use it.
+ */
+
+ /* this is default for 1.44M floppy, the caller should set it to
+ * a correct value */
+
+ .long 2880
+
+ . = Entry_ext2 + 0x24
+
+ /* This byte is ignored for read. The program will write DL onto
+ * this byte. The caller should set drive number in DL.
+ * We assume all BIOSes pass correct drive number in DL.
+ * That is to say, buggy BIOSes are not supported!!
+ */
+
+ .byte 0 /* drive number */
+
+ . = Entry_ext2 + 0x25
+
+ /* this is default for floppies, the caller should set it to
+ * a correct value for hard-drive partitions */
+
+ .byte 0xff /* partition number, 0xff for whole drive */
+
+ . = Entry_ext2 + 0x26
+
+ .word 0x80 /* inode size */
+
+ . = Entry_ext2 + 0x28
+
+ /* this is default for 1.44M floppy, the caller should set it to
+ * a correct value */
+
+ .long 2048 /* s_inodes_per_group */
+
+ . = Entry_ext2 + 0x2c
+
+ /* block number for group descriptors = s_first_data_block + 1.
+ * Valid values are 2 for 1024-byte blocks, and 1 for otherwise.
+ */
+
+ /* this is default for 1.44M floppy, the caller should set it to
+ * a correct value */
+
+ .long 2 /* block number for group descriptors */
+
+ . = Entry_ext2 + 0x30
+1:
+ cld /* 0xFC */
+
+ xorw %ax, %ax /* 0x31, 0xC0; CF=0, ZF=1 */
+
+ /* this byte `nop' will be changed to `cwd' by bootlace for floppy */
+ nop /* 0x90=nop, 0x99=cwd */
+ /* cwd will set DL=0 forcibly for floppy A: */
+
+ movw %ax, %ss /* constant SS=0 */
+ movw $0x7c00, %sp
+
+ movw %sp, %bp /* constant BP=0x7c00 */
+ movw %ax, %ds /* constant DS=0 */
+
+ pushw %ax /* 0x0000 at 0000:7bfe */
+ movw $0x1000, %bx
+ pushw %bx /* 0x1000 at 0000:7bfc */
+ pushw %ax /* 0x0000 at 0000:7bfa */
+ /* SP=0x7bfa */
+
+ /* the 6 bytes in the stack are used by read_block():
+ * 0000 ---- -2(%bp)
+ * 1000 ---- -4(%bp)
+ * 0000 ---- -6(%bp)
+ * Don't touch them!
+ */
+
+ movb %dl, 0x24(%bp) /* BIOS passes drive number in DL */
+
+ movb $0x41, %ah
+ movw $0x55AA, %bx
+ int $0x13
+#if 0
+ jnc 1f
+ /* No EBIOS */
+ movb $0x02, (ebios_ext2 - 1 - Entry_ext2 + 0x7c00)
+#else
+ jc 1f #; No EBIOS
+
+ //testb $1, %cl
+ //jz 1f #; No EBIOS
+#if 0
+ /* gcc-4.0.1 does not generate 2-byte code. */
+ rcrb $1, %cl #; also can be rorb $1, %cl
+#else
+ .byte 0xD0, 0xD9 #; ror cl: D0 C9
+#endif
+ jnc 1f #; No EBIOS
+
+ movb $0x42, (ebios_ext2 - 1 - Entry_ext2 + 0x7c00)
+#endif
+1:
+ xorl %eax, %eax /* CF=0, ZF=1 */
+
+#if 0
+ /* the INC touches ZF flag, so use MOV instead */
+
+ incw %ax
+ incw %ax /* EAX=2=inode number for root dir */
+#else
+
+ /* MOV keeps all flags untouched, so it is better than INC */
+
+ movb $2, %al /* EAX=2=inode number for root dir */
+#endif
+
+ /* CF=0, ZF=1 because MOV and PUSH do not touch Flags */
+
+ /* read root dir to 0000:1000, and grldr to 1000:0000 */
+
+4:
+ /* EAX holds the inode number: for root dir or grldr */
+
+ /* These 3 PUSHes is intended to place 1000:0000 onto the stack for
+ * grldr. For root dir, the stack is not used since CF is cleared.
+ * Although there is no corresponding POPs, this is safe enough
+ * because the program comes here only twice: the first is for
+ * the root dir, and the second is for grldr.
+ *
+ * For root dir, CF=0 and ZF=1. For grldr, CF=1.
+ */
+
+ pushw %di /* 0x1000, see "jz 4b" below. */
+ pushw %ss /* 0x0000 */
+ pushfw
+
+ /* SP=0x7bf4 for root dir, or 0x7bee for grldr */
+
+ decl %eax /* EAX=(inode - 1) */
+
+ /* inode numbers are far less than 0x7fffffff, so it is safe to
+ * initialise EDX with CDQ */
+
+ cdq /* let EDX=0 */
+
+ divl 0x28(%bp) /* s_inodes_per_group */
+ /* EAX=group number */
+ pushl %edx /* EDX=inode number in the group */
+
+ /* group numbers are far less than 0x7fffffff, so it is safe to
+ * initialise EDX with CDQ */
+
+ cdq /* let EDX=0 */
+ shll $5, %eax /* EAX=relative displacement of the group descriptor */
+ divl 0x0e(%bp) /* bytes per block */
+ /* EAX=relative block number for the group descriptor */
+ /* DX=displacement in the block */
+ /* EDX high=0 */
+
+ pushw %dx /* we don't care about EDX high word, because it is 0 */
+
+ addl 0x2c(%bp), %eax /* EAX=absolute block number for the group descriptor */
+ /* CF=0, ZF=0 */
+
+ call read_block /* 0000:1000 points to the block data containing the group descriptor */
+ /* ES changed and > 0, BX=0x1000 */
+ /* ECX=EDX=0 */
+ /* CF=0, ZF=0 */
+
+ popw %si /* DS:[BX+SI] points to the group descriptor */
+ /* DS:[BX+SI+8] points to the starting block number of the group inode table */
+
+ popl %eax /* inode number in the group */
+// shll $7, %eax /* inode struct size = 0x80 */
+// /* EAX=relative displacement of the inode struct */
+// /* EDX=0 */
+ movw 0x26(%bp), %dx /* EDX=inode size */
+ mull %edx /* EDX:EAX=relative displacement of the inode struct */
+
+ divl 0x0e(%bp) /* bytes per block */
+ /* EAX=relative block number for the inode struct */
+ pushw %dx /* DX=displacement of the inode struct in the block */
+ /* EDX high=0 */
+
+ addl 8(%bx, %si), %eax /* EAX=absolute block number for the inode struct */
+ /* CF=0, ZF=0 */
+
+ call read_block /* 0000:1000 points to the block data containing the inode struct */
+ /* ES changed and > 0, BX=0x1000 */
+ /* ECX=EDX=0 */
+ /* CF=0, ZF=0 */
+
+ popw %si /* DS:[BX+SI] points to the inode struct */
+
+ addw %bx, %si /* DS:SI points to the inode struct */
+
+ /* Move the inode struct to a known safe area(0000:0fa8 - 0000:0fff),
+ * that is, 0x58 bytes immediately before 0000:1000. We care about only
+ * the beginning 0x58 bytes of the 0x80-byte inode struct, the last
+ * 0x28 bytes are ignored. The area from 0xfa8+0x28 to 0xfa8+0x57
+ * stores 12 direct block pointers.
+ *
+ *
+ * At address Initial value Stores what?
+ * ========== ============= ======================================
+ * 0xfa8+0x04 (const) the size of the file in bytes
+ *
+ * 0xfa8+0x08 total blocks blocks left to read
+ *
+ * 0xfa8+0x0c 0 serial number of the block to read
+ *
+ */
+
+ pushw %ss
+ popw %es /* ES=0 */
+
+ leaw -0x58(%bx), %di /* BX=0x1000, so DI=0x0fa8 */
+ //movw $0x0fa8, %di
+ movb $0x2c, %cl /* 0x2c words = 0x58 bytes */
+
+ repz movsw /* now ECX=0, BX=0x1000=DI */
+
+ movl %ecx, (0x0c - 0x58)(%di) /* block serial number of the file */
+ /* ECX=0 means first block */
+ /* DI=0x1000 */
+
+ movl (0x04 - 0x58)(%di), %eax /* i_size, the file size */
+ decl %eax
+
+ divl 0x0e(%bp) /* bytes per block */
+ /* EDX=various */
+ incl %eax
+ movl %eax, (0x08 - 0x58)(%di) /* total blocks for file data */
+
+ /*
+ * 0000:1000 trebly indirect block
+ * 0000:8000 indirect block
+ * 0000:c000 double indirect block
+ * 1000:0000 the file data
+ */
+
+ /* now DS:SI points to indirect block number */
+
+ lodsl /* indirect block number */
+ testl %eax, %eax
+ jz 1f
+
+ //pushw %ss
+ //popw %es /* ES=0 */
+ movb $0x80, %bh /* ES:BX=0000:8000 */
+#if 0
+ stc
+ call read_block
+#else
+ call read_block_c
+#endif
+ /* ES changed and > 0, BX=0x8000 */
+ /* ECX=EDX=0 */
+ /* ZF=0, CF=0 */
+
+ /* now DS:SI points to double indirect block number */
+
+ lodsl /* double indirect block number */
+ testl %eax, %eax
+ jz 1f
+
+#if 0
+ pushw %ss
+ popw %es /* ES=0 */
+ movb $0xc0, %bh /* ES:BX=0000:c000 */
+ stc
+ call read_block
+#else
+ movb $0xc0, %bh /* ES:BX=0000:c000 */
+ call read_block_c
+#endif
+ /* ES changed and > 0, BX=0xc000 */
+ /* ECX=EDX=0 */
+ /* ZF=0, CF=0 */
+
+ /* now DS:SI points to trebly indirect block number */
+
+ lodsl /* trebly indirect block number */
+ testl %eax, %eax /* CF=0, TEST always clears CF */
+ jz 1f
+ /* ZF=0 */
+ //pushw %ss
+ //popw %es /* ES=0 */
+ //movb $0x10, %bh /* ES:BX=0000:1000 */
+ //stc
+ call read_block /* 0000:1000 points to the block data */
+ /* ES changed and > 0, BX=0x1000 */
+ /* ECX=EDX=0 */
+ /* ZF=0, CF=0 */
+
+ /* the block at 0000:1000, which contains the indirect block numbers,
+ * is just overwritten by the trebly indirect block */
+
+1:
+ /* get absolute block number by block serial number */
+
+ movl (0x0c - 0x58)(%di), %ebx /* block serial number of the file */
+ subl $12, %ebx
+ jc 3f /* direct block: block serial number < 12 */
+
+ pushw %bx
+ subl 0x14(%bp), %ebx
+ popw %ax
+ jnc 2f
+
+ /* indirect block: 12 <= block serial number < 12 + 0x14(%bp) */
+
+ //addw 0x14(%bp), %bx
+ addb $(0x70 / 4), %ah
+ //xchgw %ax, %bx
+ jmp 8f
+
+2:
+ pushl %ebx
+ subl 0x10(%bp), %ebx
+ jc 7f /* EBX on the stack is < 0x10(%bp). double indirect block:
+ * 12 + 0x14(%bp) <= block serial number < 12 + 0x14(%bp) + 0x10(%bp)
+ */
+
+ /* trebly indirect block: block serial number >= 12 + 0x14(%bp) + 0x10(%bp) */
+
+ popl %eax /* discard the stack */
+ xchgl %eax, %ebx /* move EBX to EAX */
+ /* EDX=0 */
+ divl 0x10(%bp)
+ /* EAX=indirect block number, < 0x14(%bp) */
+ /* EDX=block number, < 0x10(%bp) */
+
+ pushl %edx /* EDX < 0x10(%bp) */
+ testl %edx, %edx
+ jnz 7f
+
+ /* EDX=0, so we need to load the double indirect block */
+
+ shlw $2, %ax
+ xchgw %ax, %bx
+
+ /* get the double indirect block number from the trebly indirect
+ * block data */
+
+ movl (%bx, %di), %eax
+
+//6:
+ movw $0xc000, %bx /* ES:BX=0000:c000 */
+
+ //pushw %ss
+ //popw %es /* ES=0 */
+ //stc
+ call read_block_c /* 0000:c000 points to the block data */
+ /* ES changed and > 0, BX=0xc000 */
+ /* ECX=EDX=0 */
+ /* CF=0, ZF=0 */
+7:
+ popl %eax /* EAX < 0x10(%bp) */
+ cdq /* let EDX=0 (notice the above jc 7f and jnz 7f) */
+ divl 0x14(%bp)
+ /* EAX=indirect block number, < 0x14(%bp) */
+ /* EDX=block number, < 0x14(%bp) */
+
+ pushw %dx /* EDX < 0x14(%bp) */
+ testw %dx, %dx
+ jnz 7f
+
+ /* if DX=0, we need to load the indirect block */
+
+ //addb $(0xb0 / 4), %ah
+ shlw $2, %ax
+ xchgw %ax, %bx
+
+ /* get the indirect block number from the double indirect block data */
+
+ movl 0xb000(%bx, %di), %eax
+ //movl (%bx, %di), %eax
+//5:
+ movw $0x8000, %bx /* ES:BX=0000:8000 */
+
+ //pushw %ss
+ //popw %es /* ES=0 */
+ //stc
+ call read_block_c /* 0000:8000 points to the block data */
+ /* ES changed and > 0, BX=0x8000 */
+ /* ECX=EDX=0 */
+ /* CF=0, ZF=0 */
+7:
+ popw %ax /* AX < 0x14(%bp) */
+8:
+ xchgw %ax, %bx
+3:
+ shlw $2, %bx
+ movl (%bx, %di), %eax
+
+ /* got it! EAX=absolute block number */
+
+ /* read block data to 1000:0000. For root dir, read each block to
+ * 1000:0000(overwrite the previous read). For grldr, read blocks
+ * one by one to the area starting at 1000:0000.
+ */
+
+ popfw
+ popw %bx
+ popw %es
+ pushfw
+
+ /* CF=0 and ZF=1 for reading root dir, CF=1 for reading grldr */
+
+ call read_block /* 1000:0000 points to the block data */
+ /* ES changed and > 0x1000, BX=0 */
+ /* ECX=EDX=0 */
+ /* CF=0, ZF=0 */
+
+ popfw
+ pushw %es
+ pushw %bx
+ pushfw
+
+ jc 3f /* CF=1, we are reading grldr */
+
+ /* We have just read a block of the root dir to 1000:0000.
+ * So we check all dir entries in the block to see if anyone
+ * matches grldr.
+ */
+
+ xorw %si, %si
+ pushw %ss
+ popw %es /* ES=0 */
+
+2:
+ pushw %ds /* DS=0 */
+ movw %di, %ds /* DS=0x1000 */
+ movw $(filename_ext2 - Entry_ext2 + 0x7c00), %di
+
+ pushw %si
+ lodsl /* This is possible inode number for grldr */
+ pushl %eax /* This is possible inode number for grldr */
+ lodsw
+ xchgw %ax, %dx /* rec_len */
+ lodsw /* AL=name_len, should be 5 for grldr */
+ /* AH=file_type(1 for regular file) */
+#if 0
+ cmpw $0x0105, %ax
+ jnz 5f
+ movb %al, %cl /* CH is already 0 */
+ repz cmpsb
+#else
+ decb %ah
+ //jnz 5f
+ xchgw %ax, %cx /* CX=name_len */
+ repz cmpsb
+ jnz 5f
+ xchgw %ax, %cx /* movb $0, %al */
+ scasb
+#endif
+5:
+ popl %eax /* This is possible inode number for grldr */
+ popw %si
+
+ /* DS=0x1000, EAX=inode number */
+
+ movw %ds, %di /* DI=0x1000 */
+ popw %ds /* DS=0 */
+
+ stc /* indicates the new inode is for grldr */
+
+ jz 4b /* grldr is found with EAX=inode number */
+
+ addw %dx, %si
+ cmpw 0x0e(%bp), %si /* bytes per block */
+ jb 2b
+
+ /* file not found in this block, continue */
+
+ /* We are lucky that CF=0, which indicates we are dealing with
+ * the root dir.
+ */
+
+3:
+
+ /* CF=1 for grldr, CF=0 for root dir. */
+
+ incl (0x0c - 0x58)(%di)
+ decl (0x08 - 0x58)(%di)
+ jnz 1b
+
+#if 0
+ /* The above 2 instructions INC and DEC do not touch CF, so we
+ * can omit this POP-PUSH pair.
+ */
+
+ popfw
+ pushfw
+#endif
+
+ movw $(msg_No_grldr_ext2 - Entry_ext2 + 0x7c00), %si
+
+ jnc boot_error_ext2 /* grldr not found in the root dir */
+
+ /* All grldr blocks have been loaded to memory starting at 1000:0000,
+ * Before the boot, we pass boot_drive and boot_partition to grldr.
+ */
+
+ /* ES>0x1000, BX=0, ECX=EDX=0, DI=0x1000, SS=0, SI>0x7c00, DS=0
+ * BP=0x7c00, SP<=0x7c00
+ */
+
+ movw 0x24(%bp), %dx
+
+ /* boot it now! */
+
+ pushw %di /* 0x1000 */
+ pushw %ss /* 0x0000 */
+ lret
+
+read_block_c:
+
+ pushw %ss
+ popw %es /* ES=0 */
+ stc
+
+/* read_block - read a block
+ * input: CF - indicator for overlap or consecution
+ * EAX = block number
+ * ES:BX - buffer
+ *
+ * output: if CF is cleared on input, ES:BX is initialized to 0000:1000
+ * ES:BX - buffer filled with data
+ * ES, EAX - Changed
+ * ECX = 0
+ * EDX = 0
+ * ZF = 0
+ * CF = 0
+ */
+
+read_block:
+
+ jc 1f
+
+ .byte 0xC4, 0x5E, 0xFC /* lesw -4(%bp), %bx */
+ /* ES:BX=0000:1000 */
+ jnz 1f
+
+ //at this time, the gcc cannot generate 3 byte code
+ .byte 0xC4, 0x5E, 0xFA /* lesw -6(%bp), %bx */
+ /* ES:BX=1000:0000 */
+ //. = . - (. - read_block) / 6
+1:
+ movzbl 0x0d(%bp), %ecx /* CX=sectors per block */
+ /* ECX high=0 */
+ . = . - (. - 1b) / 6
+ mull %ecx /* EAX=relative sector number */
+ /* EDX=0 */
+ . = . - (. - 1b) / 9
+ addl 0x1c(%bp), %eax /* EAX=absolute sector number */
+
+#if 1
+ /* pass through, saving 4 bytes(call and ret) */
+#else
+ call readDisk_ext2
+ ret
+#endif
+
+/* Read sectors from disk, using LBA or CHS
+ * input: EAX = 32-bit LBA sector number
+ * CX = number of sectors to read
+ * ECX high word = 0
+ * ES:BX = destination buffer
+ *
+ * output: No return on error
+ * BX not changed
+ * ES = ES + 0x20 * CX
+ * EAX = EAX + CX
+ * ZF = 0
+ * CF = 0
+ */
+
+readDisk_ext2:
+2:
+ pushal
+ //xorl %edx, %edx /* EDX:EAX = LBA */
+ pushl %edx /* hi 32bit of sector number */
+ pushl %eax /* lo 32bit of sector number */
+ pushw %es /* buffer segment */
+ pushw %bx /* buffer offset */
+ pushw $1 /* 1 sector to read */
+ pushw $16 /* size of this parameter block */
+
+ //xorl %ecx, %ecx
+ pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */
+ popw %cx /* ECX = sectors per track */
+ divl %ecx /* residue is in EDX */
+ /* quotient is in EAX */
+ /* EDX high=0, DH=0 */
+ incw %dx /* DL=sector number */
+ popw %cx /* ECX = number of heads */
+ pushw %dx /* push sector number into stack */
+ xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */
+ divl %ecx /* residue is in EDX, head number */
+ /* quotient is in EAX, cylinder number */
+ /* EDX high=0, EAX high=0 */
+
+
+ xchgb %dl, %dh /* head number should be in DH */
+ /* DL = 0 */
+ popw %cx /* pop sector number from stack */
+ xchgb %al, %ch /* lo 8bit cylinder should be in CH */
+ /* AL = 0 */
+ shlb $6, %ah /* hi 2bit cylinder ... */
+ orb %ah, %cl /* ... should be in CL */
+
+ incw %ax /* AL=1, read 1 sector */
+
+ /* Instead of 0x0e, the LBA indicator at 2(%bp) is
+ *
+ * 0x42 for LBA
+ *
+ * and
+ *
+ * 0x02 for CHS
+ */
+#if 0
+ movb $0x42, %ah
+ /* ebios_ext2 - 1 points to 0x42 that can be changed to 0x02 */
+#else
+ movb $0x02, %ah
+ /* ebios_ext2 - 1 points to 0x02 that can be changed to 0x42 */
+#endif
+ebios_ext2:
+
+ //andb 2(%bp), %ah
+
+ movw %sp, %si /* DS:SI points to disk address packet */
+ movb 0x24(%bp), %dl /* drive number */
+ int $0x13
+ jc disk_error_ext2
+ movw %es, %ax
+ addw $0x20, %ax /* here, carry is cleared */
+ movw %ax, %es
+ popaw /* remove parameter block from stack */
+ popal
+ incl %eax /* next sector, here ZF=0 */
+ loop 2b
+ ret
+
+ //. = . - (. - readDisk_ext2)/74
+
+//msg_DiskReadError_ext2:
+//
+// .ascii "disk error\0"
+
+msg_No_grldr_ext2:
+
+ .ascii "No "
+
+filename_ext2:
+#ifdef BOOTGRUB2
+ .ascii "g2ldr\0"
+#else
+ .ascii "grldr\0"
+#endif
+ . = Entry_ext2 + 0x1ee
+
+filename_end_ext2:
+
+ .word (filename_ext2 - Entry_ext2)+(filename_end_ext2 - filename_ext2 - 1)*2048
+
+ . = Entry_ext2 + 0x1f0
+
+disk_error_ext2:
+
+ movw $(msg_DiskReadError_ext2 - Entry_ext2 + 0x7c00), %si
+
+boot_error_ext2:
+
+/* prints string DS:SI (modifies AX BX SI) */
+
+//print_ext2:
+1:
+ lodsb (%si), %al /* get token */
+ //xorw %bx, %bx /* video page 0 */
+ movb $0x0e, %ah /* print it */
+ int $0x10 /* via TTY mode */
+ cmpb $0, %al /* end of string? */
+ jne 1b /* until done */
+#if 1
+
+ /* The caller will change this to
+ * ljmp $0x9400, $(try_next_partition - _start1)
+ */
+
+1: jmp 1b
+
+#else
+ /* boot failed, try to hand over the control to supervisor */
+ ldsw (1f + 3 - Entry_ext2)(%bp), %si
+ lodsl
+ cmpl $0x9400b8fa, %eax
+1: jnz 1b /* no supervisor, hang up. */
+ ljmp $0x9400, $(try_next_partition - _start1)
+
+ //. = . - (. - disk_error_ext2) / 30
+#endif
+
+ . = Entry_ext2 + 0x1fe
+
+ .word 0xAA55
+
+ . = _start1 + 0xA00
+
+#define INSIDE_GRLDR
+
+#include "ntfsbs.S"
+
+ . = _start1 + 0x1200
+
+ .arch i586, jumps
+
+#ifdef DEBUG
+
+ . = Entry_ext2 + 0x201
+
+debug_print:
+
+ pushfl
+ pushal
+ movl %eax, %ebp
+ call 2f
+#if 0
+ popal
+ pushal
+ movl %ebx, %ebp
+ call 2f
+ popal
+ pushal
+ movl %ecx, %ebp
+ call 2f
+ popal
+ pushal
+ movl %edx, %ebp
+ call 2f
+ popal
+ pushal
+ movl %esi, %ebp
+ call 2f
+ popal
+ pushal
+ movl %edi, %ebp
+ call 2f
+ popal
+ popfl
+ pushfl
+ pushal
+ pushfl
+ popl %ebp /* flags */
+ call 2f
+ movw %ds, %bp
+ shll $16, %ebp
+ movw %es, %bp
+ call 2f
+ movw $0x0e0d, %ax /* print CR */
+ int $0x10 /* via TTY mode */
+ movw $0x0e0a, %ax /* print LF */
+ int $0x10 /* via TTY mode */
+#endif
+ popal
+ popfl
+ ret
+2:
+ movw $7, %cx
+1:
+ xorw %bx, %bx /* video page 0 */
+ movl %ebp, %eax
+ shrl %cl, %eax
+ shrl %cl, %eax
+ shrl %cl, %eax
+ shrl %cl, %eax
+ andb $0x0f, %al
+ addb $0x30, %al
+ movb $0x0e, %ah /* print char in AL */
+ int $0x10 /* via TTY mode */
+
+ decw %cx
+ testw %cx, %cx
+ jns 1b
+
+ movw $0x0e20, %ax /* print space */
+ int $0x10 /* via TTY mode */
+ ret
+#endif
+
+#if 1
+ /* restore GRLDR_CS */
+
+ /* this code is executed at 0000:MONITOR, which must be a 16-byte
+ * aligned address. The address 0000:MONITOR should be designed in
+ * a way that could avoid memory confliction with volume boot records
+ * (currently FAT12/16/32/NTFS/EXT2/3 are built in).
+ */
+
+ /* CS=code */
+
+ .align 16
+
+restore_GRLDR_CS:
+2:
+ call 1f
+1:
+ popw %bx # instruction pointer of 1b
+ movw %cs, %ax
+ shrw $4, %bx
+ addw %ax, %bx # BX=segment value of this code
+ pushw %bx
+ pushw $(1f - 2b)
+ lret
+1:
+ /* modify gdt base */
+ xorl %eax, %eax
+ movw %bx, %ax
+ shll $4, %eax
+ addl $(gdt -2b), %eax
+ movl %eax, %cs:(gdt - 2b + 2)
+
+ movw $GRLDR_CS, %bx
+ movw %bx, %es
+ movw %ds, %bx # save old DS to BX
+
+ cli
+ lgdt %cs:(gdt - 2b)
+ movl %cr0, %eax
+ orb $1, %al
+ movl %eax, %cr0
+
+ movw $8, %si
+ movw %si, %ds
+
+ xorl %esi, %esi
+ xorl %edi, %edi
+ movl $(0x9000 / 4), %ecx
+
+ cld
+ repz movsl
+
+ movw $16, %si
+ movw %si, %ds
+
+ andb $0xfe, %al
+ movl %eax, %cr0
+
+ movw %bx, %ds # restore DS from BX
+
+ ljmp $GRLDR_CS, $(try_next_partition - _start1)
+
+#endif
+
+# Descriptor tables
+#
+# NOTE: The intel manual says gdt should be sixteen bytes aligned for
+# efficiency reasons. However, there are machines which are known not
+# to boot with misaligned GDTs, so alter this at your peril! If you alter
+# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
+# empty GDT entries (one for NULL and one reserved).
+#
+# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
+# true for the Voyager Quad CPU card which will not boot without
+# This directive. 16 byte aligment is recommended by intel.
+#
+ .align 16
+gdt:
+ /* this is the default null entry in GDT */
+ .word gdt_end - gdt - 1 # gdt limit
+ .long (GRLDR_CS * 16 + gdt - _start1) # linear address of gdt
+ .word 0 # pad 2 bytes
+
+ /* real mode data segment base=0x200000 */
+ .word 0xFFFF, 0
+ .byte 0x20, 0x92, 0, 0
+
+ /* real mode data segment base=0 */
+ .word 0xFFFF, 0
+ .byte 0, 0x92, 0, 0
+
+gdt_end:
+
+helper_start:
+
+ /* helper function begins here
+ * before the call:
+ * CF=1 : indicates an invalid or corrupt entry
+ * CF=0 : indicates a valid entry
+ *
+ * on return:
+ * CF=1 : means "below", try next entry
+ * CF=0,ZF=1 : means "equal", helper did nothing, so we need
+ * a further try to boot via NT bootsector
+ * CF=0,ZF=0 : means "above", helper succeeded, boot it now
+ */
+
+ sti
+
+ /* DS=SS=0x9400 */
+ pushw %cs
+ popw %ds
+
+ pushw $FS_BOOT
+ popw %es
+
+ /* ES=FS_BOOT */
+
+ /* Format of partition information blocks.
+ *
+ * Offset Length in bytes Field
+ * 00h 1 Set to 80h if this partition is active.
+ * 01h 1 Partition's starting head.
+ * 02h 2 Partition's starting sector and track.
+ * 04h(SI) 1 Partition's ID number.
+ * 05h 1 Partition's ending head.
+ * 06h 2 Partition's ending sector and track.
+ * 08h 4 Starting LBA.
+ * 0Ch 4 Partition's length in sectors.
+ */
+
+ pushw %ds /* DS=0x9400 */
+ pushw %es /* ES=FS_BOOT */
+ pushal
+ pushfw
+
+ //pushw %si
+ //stc
+ //jc invalid_or_null /* invalid or null entry */
+#if 0
+ /* backup 63 sectors at FS_BOOT:0 to 63 sectors at FS_BOOT:8000
+ * this piece of code is no longer useful.
+ */
+ pushw %es
+ popw %ds
+ xorw %si, %si
+ movw $0x8000, %di
+ movw $0x3f00, %cx
+ cld
+ repz movsw
+#endif
+
+#if (defined(GRLDR_MBR)) || (defined(GRLDR_INSTALL))
+ testb $0x80, %cs:0x02 /* boot previous MBR first? */
+ jnz 2f /* no, continue to find GRLDR */
+
+ /* yes, call the routine for booting the previous MBR.
+ * it will not return on success.
+ * on failure, it will return here
+ */
+
+ /* before we call the routine, we will check if the user want to
+ * skip this step and continue to find the GRLDR
+ */
+#if 0
+ movw $(press_space_bar_string - _start1), %si
+ cmpw $0x3920, %cs:0x04
+ je 1f
+ movw $(press_hot_key_string - _start1), %si
+1:
+ /* if timeout==0, don't display the message */
+
+ cmpb $0, %cs:0x03
+ je 1f
+ call print_message /* CS:SI points to message string */
+ movw $(press_any_key_string - _start1), %si
+ call print_message /* CS:SI points to message string */
+#else
+ cmpb $0, %cs:0x03
+ je 1f
+ movw $(press_hot_key_pre - _start1), %si
+ call print_message
+ movw $(press_hot_key_name - _start1), %si
+ call print_message
+ movw $(press_hot_key_sub - _start1), %si
+ call print_message
+#endif
+1:
+ call sleep_5_seconds
+ jc 1f /* desired hot-key pressed */
+ call boot_prev_mbr //Error_modify
+1:
+ orb $0x80, %cs:0x02
+2:
+#endif
+ popfw
+ popal
+ popw %es
+ popw %ds
+
+ pushw %ds /* DS=0x9400 */
+ pushw %es /* ES=FS_BOOT */
+ pushal
+ pushfw
+
+ //cmpb $0x0e, 0x00 /* EBIOS previously checked OK? */
+ //jbe 1f /* yes, skip the check */
+ movb $0x02, 0x00 /* initialise this byte to 0x02 */
+ movb $0x41, %ah /* EBIOS check existence */
+ movw $0x55aa, %bx
+ int $0x13
+ jc 1f /* No EBIOS */
+ cmpw $0xaa55, %bx
+ jnz 1f /* No EBIOS */
+ testb $1, %cl
+ jz 1f /* No EBIOS */
+ movb $0x42, 0x00 /* LBA supported, save 0x42 to 9400:0000 */
+1:
+ popfw
+ popal
+ popw %es
+ popw %ds
+
+ pushw %ds /* DS=0x9400 */
+ pushw %es /* ES=FS_BOOT */
+ pushal
+ pushfw
+
+ pushaw
+ cmpw $0x1c2, %si
+ jne 1f
+ /* initialize partition number and partition entries end */
+ movw $0xffff, 0x1bc /* hd partition number */
+ movw $0x01fe, 0x1ba /* partition entries end */
+1:
+ pushw %dx
+ testb %dl, %dl
+ jns 1f /* floppy, use normal CHS mode */
+ cmpw $0x1f2, %si /* is it a primary partition? */
+ ja 2f /* no, it is an extended partition */
+ movl 4(%si), %eax
+ movl %eax, 8(%si) /* parent part_start saved here */
+ xorl %eax, %eax
+ movl %eax, 4(%si) /* current part_start(0) saved here */
+2:
+ //movl -4(%si), %eax
+ //cmpl $0xfffffe00, %eax /* check the starting CHS */
+ //jb 1f /* use normal CHS mode */
+
+ /* get CHS total number of sectors */
+ pushw %es
+ pushw %ds
+ movb $8, %ah /* read drive parameters changes DX,ES,DI */
+ //movb $0x80, %dl /* BIOS drive number is in DL */
+ int $0x13
+ popw %ds
+ popw %es
+ jc 3f
+ testb $63, %cl
+ jnz 2f
+3:
+ /* failed to get drive parameters, use maximum value */
+#if 0
+ popw %dx
+ pushw %dx
+ cmpb $0x80, %dl
+ jne 3f
+ pushw %ds
+ xorw %ax, %ax
+ movw %ax, %ds
+ cmpb $0, 0x475
+ popw %ds
+ je 3f
+
+3:
+#endif
+ movw $0xffff, %cx
+ movw %cx, %dx
+2:
+ //xorl %eax, %eax
+ movzbl %dh, %eax
+ incw %ax
+ movzbl %cl, %edx
+ andb $63, %dl
+ mulw %dx /* DX=0, AX=product */
+ shrb $6, %cl
+ xchgb %cl, %dh
+ xchgb %ch, %dl
+ incw %dx /* DX=total cylinders */
+ mull %edx /* EDX=0, EAX=product */
+
+ /* check the partition's starting LBA */
+ movl 4(%si), %ebx
+ addl 8(%si), %ebx /* EBX=start_LBA */
+
+ testl %ebx, %ebx
+ je 1f
+
+ ///* we always use LBA mode */
+ ////cmpl %eax, %ebx
+ ////jb 1f /* use normal CHS mode */
+ cmpb $0x42, 0x00 /* EBIOS present? */
+ jne 1f /* no, skip the LBA mode int13 call */
+
+ /* load partition boot track to FS_BOOT using LBA mode */
+ popw %ax /* AX=orig DX which holds drive number DL */
+ pushw %ax
+ pushl %edx /* EDX=0, higher 4 bytes of starting LBA */
+ pushl %ebx /* lower 4 bytes of starting LBA */
+ pushw %es /* ES=FS_BOOT */
+ pushw %dx /* DX=0, ES:0 is the buffer */
+ //pushl $0x003f0010 /* transfer 63 sectors */
+ pushw $0x3f /* transfer 63 sectors */
+ pushw $0x10 /* size of disk address packet */
+ xchgw %ax, %dx /* restore drive number DL from AL */
+ movb $0x42, %ah /* extended read */
+ movw %sp, %si /* DS:SI points to disk address packet */
+ int $0x13 /* ignore the read failure */
+ popaw /* adjust the stack */
+ jc 1f
+ popw %dx
+ popaw
+
+ //popw %ax /* discard flags in the stack */
+ popfw
+ clc
+
+ pushfw /* push new flags with CF=0 */
+ pushaw
+ pushw %dx
+1:
+ popw %dx
+ popaw
+
+ popfw
+ popal
+ popw %es
+ popw %ds
+
+ pushw %ds /* DS=0x9400 */
+ pushw %es /* ES=FS_BOOT */
+ pushal
+ pushfw
+
+ pushw %si
+
+ pushfw
+ pushw %es
+//---------------------------------------------------------
+ /* print "Try (hd0,n): " or "Try (fd0): "*/
+ pushw %ds
+ popw %es /* ES=DS=CS=0x9400 */
+
+ cld /* for stosb */
+ xorw %ax, %ax
+ testb %dl, %dl
+ jns 1f /* floppy */
+ /* hard drive */
+#if 0
+ movw %si, %ax
+ subw $0x1c2, %ax
+ shrw $4, %ax
+ cmpw $0x1fe, %si /* is in MBR? */
+ jb 1f /* yes */
+ /* no, it is an entry in an extended partition */
+ movb $0xFC, (add_sub_si + 2 - _start1) /* addw $-4, %si */
+ incw 0x1bc /* logical partition number */
+ movb 0x1bc, %al
+#else
+ incw 0x1bc /* logical partition number */
+ movw 0x1bc, %ax
+ cmpb $4, %al
+ jb 1f
+ movb $0xFC, (add_sub_si + 2 - _start1) /* addw $-4, %si */
+#endif
+1:
+ /* AL=partition number, AH=0 */
+ pushw %ax
+
+ movw $(partition_message - _start1 + 7), %di /* drive type */
+ movb %dl, %al
+ shrb $7, %al /* drive type: floppy=0, harddrive=1 */
+ shlb $1, %al
+ addw $0x6466, %ax /* "fd" or "hd" */
+ stosw
+ movb %dl, %al
+ andb $0x7f, %al /* drive number */
+ aam /* convert binary to decimal, AH=high, AL=low */
+ testb %ah, %ah
+ jz 1f
+ addb $0x30, %ah
+ movb %ah, (%di)
+ incw %di
+1:
+ addb $0x30, %al
+ stosb
+
+ popw %ax
+
+ testb %dl, %dl
+ jns 2f /* floppy */
+ /* this is a hard drive, the partition number is in AL */
+ movb $0x2c, (%di) /* "," */
+ incw %di
+ aam /* convert binary to decimal, AH=high, AL=low */
+ testb %ah, %ah
+ jz 1f
+ addb $0x30, %ah
+ movb %ah, (%di)
+ incw %di
+1:
+ addb $0x30, %al
+ stosb
+2:
+ movl $0x00203a29, (%di) /* "): \0" */
+
+ movw $(partition_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+//---------------------------------------------------------
+ popw %es
+ popfw
+ //stc
+ jc invalid_or_null /* invalid or null entry */
+
+ xorw %si, %si
+ pushw %es
+ popw %ds
+
+ /* DS=ES=FS_BOOT */
+
+ /* First, check for ext2 filesystem */
+
+ cmpw $0xEF53, 0x438 /* Magic signature */
+ jnz 1f
+ xorl %eax, %eax
+ cmpl %eax, 0x400 /* s_inodes_count */
+ jz 1f
+ cmpl %eax, 0x404 /* s_blocks_count */
+ jz 1f
+// cmpw %ax, 0x458 /* s_inode_size, usually 0x80 */
+// jz 1f
+ cmpl %eax, 0x420 /* s_blocks_per_group */
+ jz 1f
+ cmpl %eax, 0x428 /* s_inodes_per_group */
+ jz 1f
+ movl 0x414, %eax /* s_first_data_block */
+ movw %ax, %bx /* BX=1 for 1K block, 0 otherwise */
+ shrl $1, %eax /* must be 0 */
+ jnz 1f
+ movl 0x418, %ecx /* s_log_block_size */
+ cmpl $4, %ecx /* max size of block is 16K */
+ ja 1f
+ negw %cx /* CF=0 for 1K block, CF=1 otherwise */
+ adcw %ax, %bx /* EAX=0 */
+ decw %bx
+ jnz 1f
+
+ /* BX = 0 */
+ /* EAX= 0 */
+
+ movw $0x80, %ax /* EXT2_GOOD_OLD_INODE_SIZE */
+ movw %ax, %cs:0x826 /* inode size */
+ movl 0x44C, %ecx /* ECX=s_rev_level */
+ jecxz 3f /* EXT2_GOOD_OLD_REV */
+ movw 0x458, %ax /* AX=s_inode_size */
+ testw %ax, %ax
+ jz 1f /* invalid inode size */
+ pushw %ax
+ pushw %dx
+ movb 0x418, %cl /* s_log_block_size */
+ addb $10, %cl
+ xorw %dx, %dx /* DX=0 */
+ incw %dx /* DX=1 */
+ shlw %cl, %dx /* DX=block size in bytes */
+ xchgw %ax, %cx /* CX=s_inode_size */
+ xchgw %ax, %dx /* AX=block size in bytes */
+ xorw %dx, %dx /* DX:AX=block size in bytes */
+ divw %cx /* quo=AX, rem=DX */
+ testw %dx, %dx
+ popw %dx
+ popw %ax
+ jnz 1f /* invalid inode size */
+ movw %ax, %cs:0x826 /* inode size */
+3:
+ /* BX = 0 */
+
+ /* super block is sane */
+
+ //pushw %cs
+ //popw %ds
+ ///* DS=SS=0x9400 */
+ ///* ES=FS_BOOT */
+ cld
+ movw $0x800, %si
+ xorw %di, %di
+ movw $0x0200, %cx /* yes, we need 2 sectors if enable debug */
+
+ repz cs movsw /* CS segment override prefix(=0x2E) */
+
+ /* modify the boot partition number */
+
+ /* the boot partition number is at offset 0x25 for ext2 */
+
+ testb %dl, %dl
+ jns 3f /* no modification for floppy */
+ movw $0x25, %di
+ movw %cs:0x1bc, %ax /* partition number */
+ stosb
+3:
+ /* fix for ext2 partition: hidden_sectors, offset 0x1c */
+ popw %si /* DI points to old entry in MBR */
+ pushw %si
+ xorl %eax, %eax /* let hidden_sectors=0 for floppy */
+ testb %dl, %dl
+ jns 3f /* floppy */
+ movl %cs:4(%si), %eax
+ addl %cs:8(%si), %eax
+3:
+ /* BX = 0 */
+
+ movl %eax, %es:0x1c(%bx) /* adjust hidden_sectors for EXT2 */
+
+ /* fix for ext2 partition: EBIOS indicator, offset 0x02 */
+
+ movb %cs:0x00(%bx), %al
+ movb %al, %es:0x02(%bx)
+
+ /* fix for ext2 partition: sectors per block, offset 0x0d */
+ /* fix for ext2 partition: bytes per block, offset 0x0e */
+ /* fix for ext2 partition: dwords per block(dpb), offset 0x14 */
+ /* fix for ext2 partition: square of dpb, offset 0x10 */
+
+ movb %es:0x418, %cl /* s_log_block_size */
+ //incw %cx
+ movl $2, %eax
+ shlw %cl, %ax
+ movb %al, %es:0x0d(%bx)
+ shlw $9, %ax /* block size is word wide */
+ movw %ax, %es:0x0e(%bx)
+ shrw $2, %ax
+ movl %eax, %es:0x14(%bx)
+ addb $8, %cl
+ shll %cl, %eax
+ movl %eax, %es:0x10(%bx)
+
+
+ /* fix for ext2 partition: sectors per track, offset 0x18 */
+ /* fix for ext2 partition: number of heads, offset 0x1a */
+#if 1
+ pushw %ds
+ pushw %es
+ pushw %bx
+ pushw %dx
+ movb $8, %ah /* read drive parameters changes DX,ES,DI,BX */
+ movb $0x80, %dl /* BIOS drive number is in DL */
+ int $0x13
+ movw %dx, %ax
+ popw %dx
+ popw %bx
+ popw %es
+ popw %ds
+ jc 3f
+ andb $63, %cl
+ jz 3f
+ movb %cl, %es:0x18(%bx)
+ shrw $8, %ax
+ incw %ax
+ movw %ax, %es:0x1a(%bx)
+3:
+#else
+ testb %dl, %dl
+ jns 3f /* floppy */
+ popw %di /* DI points to old entry in MBR */
+ pushw %di
+ movw %cs:1(%di), %ax
+ andb $63, %ah
+ movb %ah, %es:0x18
+ xorb %ah, %ah
+ incw %ax
+ movw %ax, %es:0x1a
+3:
+#endif
+
+ /* fix for ext2 partition: s_inodes_per_group, offset 0x28 */
+ movl %es:0x428, %eax /* s_inodes_per_group */
+ movl %eax, %es:0x28(%bx)
+
+ /* fix for ext2 partition: block number for group descriptors, offset 0x2c */
+ /* At which block the group descriptors begin? */
+ movl %es:0x414, %eax /* s_first_data_block */
+ incw %ax
+ movl %eax, %es:0x2c(%bx)
+
+ /* fix for ext2 partition: on error go back to supervisor, offset 0x01fc */
+ movw $0x01fc, %si
+ movw %si, %di
+ lodsw
+ cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */
+ jnz 3f
+ decw %ax /* AL=0xEA, ljmp */
+ stosb
+ //movw $(try_next_partition - _start1), %ax
+ movw $MONITOR, %ax
+ stosw
+ //movw %cs, %ax /* AX=0x9400 */
+ xorw %ax, %ax
+ stosw /* the last byte 0x00 is in the next sector! */
+// addw $0x0f, %di
+// movw $(restore_GRLDR_CS - _start1), %si
+// movw $((gdt_end - restore_GRLDR_CS) / 4), %cx
+// .byte 0x2e /* %cs: prefix */
+// repz movsl
+3:
+
+ movw $(EXT2_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+
+ clc
+ jmp move_entries_and_return
+
+1:
+ #; It is not EXT2. Check for FAT12/16/32/NTFS.
+
+ /* DS=ES=FS_BOOT */
+
+ cmpw $0x200, 0x0b(%si) /* bytes per sector */
+ jne 1f /* not a normal BPB */
+ movb 0x0d(%si), %al /* sectors per cluster */
+ testb %al, %al
+ jz 1f /* invalid if = 0 */
+ movb %al, %cl
+ movw $128, %ax
+ divb %cl /* quo=AL, rem=AH */
+ testb %ah, %ah
+ jnz 1f /* invalid if not 2^n */
+ movw 0x18(%si), %ax /* sectors per track */
+ testw %ax, %ax
+ jz 1f /* invalid if = 0 */
+ cmpw $63, %ax
+ ja 1f /* invalid if > 63 */
+ movw 0x1a(%si), %ax /* number of heads */
+ decw %ax /* Max head number, should be a byte */
+ testb %ah, %ah /* should be 0 */
+ jnz 1f /* invalid if number of heads > 256 */
+ cmpb $0xf0, 0x15(%si) /* media descriptor */
+ jb 1f
+
+ cmpb $0x42, %cs:0x00 /* EBIOS present? */
+ jne 3f
+ //movb $0x41, %ah /* EBIOS check existence */
+ //movw $0x55aa, %bx
+ //int $0x13
+ //jc 3f /* No EBIOS */
+ //cmpw $0xaa55, %bx
+ //jnz 3f /* No EBIOS */
+ //testb $1, %cl
+ //jz 3f /* No EBIOS */
+ movb $0x0e, 0x02(%si) /* force LBA */
+3:
+ cld
+ movw $0x0600, %bx /* FAT12/FAT16 */
+ movw $0x003c, %cx /* FAT12/FAT16 */
+
+ movb 0x10(%si), %al /* number of FATs(NTFS:0, FAT:1,2) */
+ cmpb $2, %al
+ ja 1f /* abnormal FAT */
+ movw 0x11(%si), %ax /* max root entries */
+ testw %ax, %ax
+ jnz 2f /* FAT12/FAT16 */
+
+ /* FAT32 or NTFS */
+ movw 0x13(%si), %ax /* total sectors(small) */
+ testw %ax, %ax
+ jnz 1f /* invalid FAT32 BPB */
+ movw 0x16(%si), %ax /* sectors per FAT(small) */
+ testw %ax, %ax
+ jnz 1f /* invalid FAT32 BPB */
+ movb 0x10(%si), %al /* number of FATs(NTFS:0, FAT:1,2) */
+ testb %al, %al
+ jz 8f
+
+ /* FAT32 */
+ movl 0x20(%si), %eax /* FAT32 total sectors */
+ testl %eax, %eax
+ jz 1f
+ movl 0x24(%si), %eax /* FAT32 sectors per FAT */
+ testl %eax, %eax
+ jz 1f
+ movw $0x0400, %bx /* FAT32 */
+ movw $0x0058, %cx /* FAT32 */
+ movw $(FAT32_message - _start1), %si
+ jmp 7f
+8:
+ /* NTFS */
+ movl 0x20(%si), %eax /* FAT32 total sectors */
+ testl %eax, %eax
+ jnz 1f
+ //movw 0x11(%si), %ax /* max root entries */
+ //testw %ax, %ax
+ //jnz 1f
+ movw 0x0e(%si), %ax /* reserved sectors */
+ testw %ax, %ax
+ jnz 1f
+
+ /* BUG fix for extended NTFS partition */
+ popw %si /* SI points to old entry in MBR */
+ pushw %si
+ xorl %eax, %eax /* let hidden_sectors=0 for floppy */
+ testb %dl, %dl
+ jns 3f /* floppy */
+ movl %cs:4(%si), %eax
+ addl %cs:8(%si), %eax
+3:
+ movl %eax, 0x1c /* adjust hidden_sectors for NTFS */
+
+ movb %dl, 0x24 /* adjust drive number for NTFS */
+
+#if 1
+ // Load NTFS using internal boot sector at 0xA00
+
+ movw $(NTFS5_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+
+ movw $0xA00, %bx
+ movw $0x52, %cx
+
+ pushw %cs
+ popw %ds
+
+ /* DS=SS=0x9400 */
+ /* ES=FS_BOOT */
+
+ movw %bx, %si
+ xorw %di, %di
+ lodsw
+ stosw
+ addw %cx, %si
+ addw %cx, %di
+ movw $0x800, %cx
+ subw %di, %cx
+
+ repz movsb
+
+ /* modify the boot partition number */
+ movb %es:1, %al
+ addb $5, %al /* AL is less than 0x80 */
+ cbw /* AH=0 */
+ xchgw %ax, %di /* move AX to DI */
+ movb $0xff, %al /* partition=whole drive for floppy */
+ testb %dl, %dl
+ jns 3f /* no modification for floppy */
+ movb 0x1bc, %al /* partition number */
+3:
+ stosb
+
+ /* fix for NTFS partition: on error go back to supervisor, offset 0x01fa */
+
+ movw $0x01fa, %di
+ movw %es:(%di), %ax
+ cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */
+ jnz 3f
+ decw %ax /* AL=0xEA, ljmp */
+ stosb
+ //movw $(try_next_partition - _start1), %ax
+ movw $MONITOR, %ax
+ stosw
+
+ //movw %cs, %ax /* AX=0x9400 */
+ xorw %ax, %ax
+ stosw /* DI=0x01ff */
+3:
+ clc
+ jmp move_entries_and_return
+
+#else
+
+ /* modify the boot partition number */
+ movb $0xB6, %al /* 0xB6="MOV DH,imm8" */
+ movb %cs:0x1bc, %ah
+ testb %dl, %dl
+ js 3f
+ movb $0xff, %ah /* partition number for floppy is whole drive */
+3:
+ /* before the call:
+ * AH= partition number
+ * AL= 0xB6 ; 0xB6 is opcode of "MOV DH,imm8"
+ * DL= drive number
+ *
+ * on return: CF=0 if there is NTFS boot record;
+ * CF=1 otherwise.
+ * CF of flags_orig on the stack will set if CF=1
+ */
+
+ call modify_NTFS_boot_record
+ //jnc move_entries_and_return
+ //movw $(NTFS5_message - _start1), %si
+ ////jmp 4f
+ //call print_message /* CS:SI points to message string */
+ //stc
+ jmp move_entries_and_return
+
+#endif
+
+2:
+ /* FAT12/FAT16 */
+ movb 0x10(%si), %al /* number of FATs(NTFS:0, FAT:1,2) */
+ testb %al, %al
+ jz 1f
+ movw 0x16(%si), %ax /* sectors per FAT(small) */
+ testw %ax, %ax
+ jz 1f
+ movw $(FAT16_message - _start1), %si
+ cmpw $12, %ax
+ ja 7f
+ movw $(FAT12_message - _start1), %si
+7:
+ /* BUG fix for extended FAT12/16/32 partition */
+ popw %di /* DI points to old entry in MBR */
+ pushw %di
+ xorl %eax, %eax /* let hidden_sectors=0 for floppy */
+ testb %dl, %dl
+ jns 3f /* floppy */
+ movl %cs:4(%di), %eax
+ addl %cs:8(%di), %eax
+3:
+ movl %eax, 0x1c /* adjust hidden_sectors for FAT */
+
+ call print_message /* CS:SI points to message string */
+ pushw %cs
+ popw %ds
+ /* DS=SS=0x9400 */
+ /* ES=FS_BOOT */
+ movw %bx, %si
+ xorw %di, %di
+ lodsw
+ stosw
+ addw %cx, %si
+ addw %cx, %di
+ movw $0x0200, %cx
+ subw %di, %cx
+ repz movsb
+ /* modify the boot partition number */
+ movb %es:1, %al
+ addb $5, %al /* AL is less than 0x80 */
+ cbw /* AH=0 */
+ xchgw %ax, %di /* move AX to DI */
+ movb $0xff, %al /* partition=whole drive for floppy */
+ testb %dl, %dl
+ jns 3f /* no modification for floppy */
+ movb 0x1bc, %al /* partition number */
+3:
+ stosb
+
+ /* fix for FAT12/16/32 partition: on error go back to supervisor, offset 0x01fa */
+ //pushw %es
+ //popw %ds
+ movw $0x01fa, %di
+ //movw %di, %si
+ //lodsw
+ movw %es:(%di), %ax
+ cmpw $0xFEEB, %ax /* EB FE is jmp back to itself(infinite loop) */
+ jnz 3f
+ decw %ax /* AL=0xEA, ljmp */
+ stosb
+ //movw $(try_next_partition - _start1), %ax
+ movw $MONITOR, %ax
+ stosw
+ //movw %cs, %ax /* AX=0x9400 */
+ xorw %ax, %ax
+ stosw /* DI=0x01ff */
+3:
+
+ clc
+ jmp move_entries_and_return
+1:
+ #; It is not FAT12/16/32/NTFS. Check for extended partition.
+
+ /* DS=ES=FS_BOOT */
+
+ pushw %cs
+ popw %es
+
+ /* ES=SS=0x9400 */
+ /* DS=FS_BOOT */
+
+ popw %si
+ pushw %si
+ cmpb $0x05, %es:(%si) /* extended */
+ je 1f
+ cmpb $0x0f, %es:(%si) /* Win95 extended (LBA) */
+ je 1f
+ cmpb $0x15, %es:(%si) /* hidden extended */
+ je 1f
+ cmpb $0x1f, %es:(%si) /* hidden win95 extended (LBA) */
+ je 1f
+ cmpb $0x85, %es:(%si) /* Linux extended */
+ je 1f
+ movw $(non_MS_message - _start1), %si
+4:
+ call print_message /* CS:SI points to message string */
+ stc
+ jmp move_entries_and_return
+1:
+ /* extended partition entry */
+ cmpw $0x1fe, %si
+ jb 1f
+ decw %es:0x1bc /* count the partitions in extended zone */
+1:
+ movw $(extended_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+ movw $0x1be, %si
+ movw $4, %cx
+5:
+ //xorl %eax, %eax
+ //cmpl %eax, (%si)
+ //jnz 2f
+ movl (%si), %eax
+ cmpw 2(%si), %ax /* Is EAX high word equal to AX? */
+ jnz 2f
+ cmpb %al, %ah /* Is AL=AH? */
+ jnz 2f
+
+ /* now all 4 bytes in EAX are equal to each other. */
+ cmpl %eax, 4(%si)
+ jnz 2f
+ cmpl %eax, 8(%si)
+ jnz 2f
+ cmpl %eax, 12(%si)
+ jz 3f /* entry with 16 dups of a byte means empty entry */
+2:
+ movb (%si), %al
+ shlb $1, %al
+ jnz 1f
+ //jnz 3f /* invalid entry is treated as empty entry */
+ movb 2(%si), %al
+ and $63, %al /* starting sector number */
+ jz 1f
+ //jz 3f /* invalid entry is treated as empty entry */
+ movb 6(%si), %al
+ and $63, %al /* ending sector number */
+ jz 1f
+ //jz 3f /* invalid entry is treated as empty entry */
+ movl 8(%si), %eax /* starting LBA */
+ testl %eax, %eax
+ jz 1f
+ //jz 3f /* invalid entry is treated as empty entry */
+ movl 12(%si), %eax /* total number of sectors in partition */
+ testl %eax, %eax
+ jz 1f
+3:
+ addw $16, %si
+ loop 5b
+ cmpw $0xaa55, (%si)
+ jnz 1f
+
+ movw $0x1be, %si
+ movw $4, %cx
+ popw %bx /* the old SI points to extended partition ID in MBR */
+ pushw %bx
+5:
+#if 1
+ //xorl %eax, %eax
+ //cmpl %eax, (%si)
+ //jnz 2f
+ movl (%si), %eax
+ cmpw 2(%si), %ax /* Is EAX high word equal to AX? */
+ jnz 2f
+ cmpb %al, %ah /* Is AL=AH? */
+ jnz 2f
+
+ /* now all 4 bytes in EAX are equal to each other. */
+ cmpl %eax, 4(%si)
+ jnz 2f
+ cmpl %eax, 8(%si)
+ jnz 2f
+ cmpl %eax, 12(%si)
+ jz 3f /* entry with 16 dups of a byte means empty entry */
+2:
+ /* now it is an acceptable entry */
+ movw %es:0x1ba, %di /* partition entries end */
+ /* ensure our stack not to be overwritten by the partition entries */
+ cmpw $0x83f0, %di
+ ja 3f /* try next */
+ /* ensure our code not to be overwritten by the partition entries */
+ cmpw $0x3fe, %di
+ jne 6f
+ /* more entries stores at 0x9be00-0x9c3ff */
+ movw $0x7e00, %di
+ movw %di, %es:0x1ba
+6:
+ addw $16, %es:0x1ba /* increment partition entries end */
+
+ lodsl
+ stosl
+ lodsl
+ stosl
+
+ xchgw %ax, %dx /* save AL(the partition ID)to DL */
+
+ lodsl
+ xchgl %eax, %edx /* restore AL from DL(the partition ID)
+ * and save EAX to EDX */
+ cmpb $0x05, %al
+ je 6f
+ cmpb $0x0f, %al
+ je 6f
+ cmpb $0x15, %al
+ je 6f
+ cmpb $0x1f, %al
+ je 6f
+ cmpb $0x85, %al
+ je 6f
+ /* normal partition, copied to 0x941fe-0x943fb */
+ addl %es:4(%bx), %edx /* current partition start */
+6:
+ /* extended partition, copied to 0x941fe-0x943fb */
+ xchgl %eax, %edx /* restore or update EAX from EDX */
+ stosl
+ lodsl /* adjust SI only */
+ movl %es:8(%bx), %eax /* parent partition start ... */
+ stosl /* ... stored here */
+ jmp 2f
+3:
+ addw $16, %si
+#endif
+ //. = 5b + 0x7c
+2:
+ loop 5b
+
+ /* extended partition is not a normal one, so set carry to try next */
+ stc
+ jmp move_entries_and_return
+
+invalid_or_null:
+1:
+ movw $(invalid_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+ stc
+
+move_entries_and_return:
+ popw %si
+ pushfw
+ pushw %cs
+ popw %ds
+ pushw %cs
+ popw %es
+ pushw %si
+ cmpw $0x202, %si
+ jne 1f
+ /* move entries backward 1 entry */
+ movw $0x1fe, %di
+ movw $0x20e, %si
+ movw $0xf8, %cx /* 0x1f0 bytes = 0xf8 words */
+ cld /* move upward */
+ repz movsw
+ movw $0x3ee, %di
+ movw $0x7e00, %si
+ movw $0x8, %cx /* 0x10 bytes = 0x8 words */
+ cld /* move upward */
+ repz movsw
+ movw $0x7e00, %di
+ movw $0x7e10, %si
+ movw $0x2f8, %cx /* 0x5f0 bytes = 0x2f8 words */
+ cld /* move upward */
+ repz movsw
+ cmpw $0x7e10, 0x1ba
+ jne 2f
+ movw $0x40e, 0x1ba
+2:
+ subw $0x10, 0x1ba
+
+1:
+ popw %si
+ movw $0x1ff, (add_sub_si + 5 - _start1)
+ cmpw $0x1fe, 0x1ba
+ jne 1f
+ decw (add_sub_si + 5 - _start1)
+ cmpw $0x31b2, %si /* floppy? */
+ je 1f /* yes */
+ cmpw $0x1f2, %si
+ ja 2f /* logical partition */
+ jb 1f /* primary partition 0, 1, 2 */
+ /* primary partition 3 */
+ cmpw $0x0003, 0x1bc /* are there any logical partitions? */
+ ja 1f /* yes */
+2:
+inc_hard_drive:
+
+ /* all partitions on the drive have been checked, try next drive.
+ *
+ * the current stack is:
+ *
+ * SP + 38 : DS
+ * SP + 36 : ES
+ * SP + 32 : EAX
+ * SP + 28 : ECX
+ * SP + 24 : EDX
+ * SP + 20 : EBX
+ * SP + 16 : ESP_temp
+ * SP + 12 : EBP
+ * SP + 8 : ESI
+ * SP + 4 : EDI
+ * SP + 2 : flags_orig
+ * SP : flags
+ *
+ */
+
+ /* get total hard drives */
+ xorw %ax, %ax
+ movw %ax, %ds
+ movb 0x475, %dh
+ pushw %cs
+ popw %ds
+// cmpb $16, %dh
+// jnb 2f
+// movb $16, %dh
+//2:
+ orb $0x80, %dh /* CF=0, DH=Max harddrive number + 1 */
+ //xchgw %ax, %cx /* CL=Max harddrive number + 1, CH=0 */
+ movw %sp, %bp
+ movb 24(%bp), %dl /* BIOS drive number is in DL */
+2:
+ jnc 3f
+ call print_message /* CS:SI points to message string */
+ movw $(drive_number_string - _start1), %si
+ movb %dl, %al
+ andb $0x7f, %al
+ aam /* AH=high decimal, AL=low decimal */
+ addw $0x3030, %ax
+ xchgb %al, %ah
+ movw %ax, 9(%si)
+ call print_message /* CS:SI points to message string */
+3:
+ incw %dx
+ cmpb %dh, %dl
+ jnb 2f /* all drives checked, try floppy finally */
+
+ pushw %bx
+ pushw %dx
+ pushw %es
+ movb $8, %ah /* read drive parameters changes DX, ES, DI */
+ int $0x13
+ popw %es
+ jc 3f /* try next hard drive */
+ //xchgw %ax, %cx /* this moves CL to AL */
+ andb $63, %cl /* CL=sectors per track, CF cleared */
+ stc
+ jz 3f /* try next hard drive */
+ popw %dx /* get DL */
+ popw %bx
+ movb %dl, %ch /* DL saved at BP high byte in the stack */
+ pushw %cx /* push new BX onto stack */
+ pushw %dx
+ //movb $0x02, %ah
+ //movw %ax, %si /* save AX to SI: read 1 track */
+ movw $0x201, %ax /* read 1 sector */
+ movw $0x7e00, %bx /* read MBR to 9400:7e00 */
+ movw $1, %cx
+ //popw %dx
+ //pushw %dx
+ xorb %dh, %dh
+ stc
+ int $0x13
+ sti
+3:
+ popw %dx
+ popw %bx /* BL=sectors per track, BH=DL */
+
+ //movw %si, %bx /* BL=sectors per track */
+
+ movw $(Error_while_reading_string - _start1), %si
+ jc 2b /* read failure, try next hard drive */
+
+ /* on seccessful return, should be: ah=0 for OK, al=1 for 1 sector */
+ //decw %ax /* some BIOSes return incorrect AL */
+ testb %ah, %ah
+ stc
+ jnz 2b
+
+ /* The new partition table might be empty or invalid.
+ * Move the new partition table onto the old one while checking
+ */
+
+ //movb %dl, %bh /* DL saved at BP high byte in the stack */
+
+ movw $0x7fbe, %si
+ movw $0x01be, %di
+
+3:
+ cmpw $0x1fe, %di
+ jnb 3f
+
+ xorl %ecx, %ecx
+
+ lodsl
+ stosl
+ orl %eax, %ecx
+ lodsl
+ stosl
+ orl %eax, %ecx
+ lodsl
+ stosl
+ orl %eax, %ecx
+ lodsl
+ stosl
+ orl %eax, %ecx
+ jecxz 3b /* null entry, check next */
+
+ //lodsw
+ //stosw
+ movb -16(%si), %al
+ shlb $1, %al
+ stc
+ xchgw %ax, %si /* save SI to AX */
+ movw $(partition_boot_indicator_string - _start1), %si
+ jnz 2b
+ xchgw %ax, %si /* restore SI from AX */
+ //lodsw
+ //stosw
+ movb -14(%si), %al
+ andb $63, %al
+ stc
+ xchgw %ax, %si /* save SI to AX */
+ movw $(partition_sectors_per_track_string - _start1), %si
+ jz 2b
+ xchgw %ax, %si /* restore SI from AX */
+ //lodsw
+ //stosw
+ //lodsw
+ //stosw
+ movb -10(%si), %al
+ andb $63, %al
+ stc
+ xchgw %ax, %si /* save SI to AX */
+ movw $(partition_sectors_per_track_string - _start1), %si
+ jz 2b
+ xchgw %ax, %si /* restore SI from AX */
+ //lodsl
+ //stosl
+ movl -8(%si), %eax
+ testl %eax, %eax
+ stc
+ xchgw %ax, %si /* save SI to AX */
+ movw $(partition_start_sector_string - _start1), %si
+ jz 2b
+ xchgw %ax, %si /* restore SI from AX */
+
+ //lodsl
+ //stosl
+ movl -4(%si), %eax
+ testl %eax, %eax
+ stc
+ xchgw %ax, %si /* save SI to AX */
+ movw $(partition_end_sector_string - _start1), %si
+ jz 2b
+ xchgw %ax, %si /* restore SI from AX */
+
+ jmp 3b
+3:
+ cmpw $0xAA55, (%si)
+ stc
+ xchgw %ax, %si /* save SI to AX */
+ movw $(no_boot_signature_string - _start1), %si
+ jnz 2b
+ xchgw %ax, %si /* restore SI from AX */
+ //lodsw
+ //stosw /* store boot signature */
+
+ /* Now the partition table is OK */
+
+ movw %bx, 12(%bp) /* adjust BP in the stack */
+
+ movw $0x1b2, 8(%bp) /* adjust SI in the stack */
+
+ /* temp change the code: call self_modify_once
+ *
+ * "call self_modify_once" at add_sub_si is:
+ *
+ * .byte 0xE8
+ * .word (self_modify_once - add_sub_si - 3)
+ *
+ */
+ movb $0xE8, (add_sub_si - _start1)
+ movw $(self_modify_once - add_sub_si - 3), (add_sub_si + 1 - _start1)
+
+ /* initialize partition number and partition entries end */
+ movw $0xffff, 0x1bc /* hd partition number */
+ movw $0x01fe, 0x1ba /* partition entries end */
+
+ jmp 1f
+2:
+ /* get here if all drives have been checked */
+#if 0
+ movw $0x202, 8(%bp) /* adjust SI in the stack */
+
+ /* restore the original code: addw $-4, %si */
+ movw $0xC683, (add_sub_si - _start1) /* 0x83, 0xC6 */
+ movb $0xFC, (add_sub_si + 2 - _start1) /* 0xFC */
+#endif
+ //--------------------------------------------------------------------
+ /* change the code: jmp Error_modify
+ *
+ * "jmp Error_modify" at Error_or_prev_MBR:
+ *
+ * .byte 0xE9
+ * .word (Error_modify - Error_or_prev_MBR - 3)
+ *
+ */
+ movb $0xE9, (Error_or_prev_MBR - _start1)
+ movw $(Error_modify - Error_or_prev_MBR - 3), (Error_or_prev_MBR + 1 - _start1)
+ //--------------------------------------------------------------------
+
+ //--------------------------------------------------------------------
+ /* floppy search disabled ? */
+#if 0
+ testb $1, 0x02 /* test bit0 of the third byte */
+ jz 1f /* zero means floppy search enabled */
+ /* 0x1fd or below means disable floppy search */
+ decw (add_sub_si + 5 - _start1)
+#else
+ movb 0x02, %al
+ andb $0x01, %al
+ subb %al, (add_sub_si + 5 - _start1)
+#endif
+ //--------------------------------------------------------------------
+
+1:
+#if 0
+ popfw
+ lahf /* Load Flags into AH Register. */
+ /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */
+ /* CF will be moved to ZF */
+ movb %ah, %al
+ andb $1, %al /* CF=0 */
+ shlb $6, %al /* move CF to ZF */
+ popfw
+ lahf /* Load Flags into AH Register. */
+ /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */
+ andb $0xbf, %ah /* 0xbf= binary 1011 1111. It clears ZF */
+ orb %al, %ah
+#else
+ popw %ax /* AX=Flags */
+ popfw /* Flags_orig */
+ lahf /* Load Flags_orig into AH Register. */
+ /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */
+ shlb $2, %ah
+ rorw $2, %ax /* move CF of Flags to ZF of Flags_orig */
+#endif
+
+ sahf /* update flags */
+ /* current CF is the CF of Flags_orig */
+ /* current ZF is the CF of Flags */
+ jc 1f /* CF=1 means failed in loading bootsector */
+ popal /* get drive number DL */
+ pushal
+ pushfw
+ cmpb $0xff, %cs:0x06
+ jz 2f
+ movb %cs:0x1bc, %dh
+ testb %dl, %dl
+ js 3f
+ movb $0xff, %dh /* partition # for floppy is "whole drive" */
+3:
+ cmpw %cs:0x06, %dx
+ jz 2f
+ popfw
+ stc
+ pushfw
+2:
+ popfw
+1:
+ popal
+ popw %es
+ popw %ds
+ ret
+
+self_modify_once:
+ /* when we get here, SI should be 0x1b2, and BP high holds DL */
+ addw $12, %si /* 0x83, 0xC6, 0x0C */
+ movw %bp, %ax
+ movb %ah, %dl
+
+ /* note: DS=0x9400 */
+
+ /* restore the original code: addw $12, %si */
+ movw $0xC683, (add_sub_si - _start1) /* 0x83, 0xC6 */
+ movb $0x0C, (add_sub_si + 2 - _start1) /* 0x0C */
+ ret
+
+Error_modify:
+ cmpb $0xff, %cs:0x06 /* preferred drive? */
+ jz 1f /* not active. Turn to the final step. */
+
+ /* preferred drive is already handled, so de-activate it now. */
+ movb $0xff, %cs:0x06
+
+ /* we will do the second pass, from drive 0x80. */
+ movb $0x7f, %dl /* this will become 0x80 after inc. */
+
+ /* pass "error" to PUSHF, simulating a load failure, in order
+ * to try the first entry after return from the helper function.
+ */
+
+ stc
+
+ pushw $(helper_call + 3 - _start1) /* return address */
+ pushw %cs /* 0x9400, it is for DS. */
+ pushw $FS_BOOT /* 0x0d00, it is for ES. */
+ pushal
+ //pushl %eax
+ //pushl %ecx
+ //pushl %edx
+ //pushl %ebx
+ //pushl %esp
+ //pushl %ebp
+ //pushl %esi
+ //pushl %edi
+ pushfw /* CF=1 */
+ pushfw
+
+ pushw %cs
+ popw %es /* ES=0x9400 */
+
+ /* redo from start: DL will be 0x80 after inc. */
+ jmp inc_hard_drive
+1:
+boot_prev_mbr:
+
+ /* prepare to boot the previous MBR */
+
+ /* at this moment DS=0x9400, ES=$FS_BOOT or ES=0x9400 */
+ xorw %ax, %ax
+ //pushw %ax /* AX=0, for the segment of 0000:7c00 */
+ movw %ax, %es /* ES=0x0000 */
+ movw %ax, %ds /* DS=0x0000 */
+ pushw %ds
+ pushw %es
+ movw $0x0202, %ax /* read 2 sectors ... */
+ movw $0x7A00, %bx /* ... to 0000:7A00 */
+ //pushw %bx /* BX=0x7c00, for the offset of 0000:7c00 */
+ movw $0x0001, %cx /* from the first sector ... */
+ movw $0x0080, %dx /* ... of the first hard drive */
+ stc
+ int $0x13
+ sti
+ popw %es
+ popw %ds
+ jc 1f
+ testb %ah, %ah
+ jnz 1f
+ cmpw $0xAA55, 0x7dfe
+ jne 1f
+ cmpw $0xAA55, 0x7bfe
+ jne 1f
+
+ /* has a valid partition table ? */
+ movw $0x7dbe, %si
+3:
+ cmpw $0x7dfe, %si
+ jnb 3f /* partition table is OK */
+ movw $4, %cx
+
+ movw %si, %di
+2:
+ lodsl
+ negl %eax
+ jc 2f
+ loop 2b
+ /* empty entry, check next */
+ jmp 3b
+2:
+ /* non-empty entry */
+ movw %di, %si
+
+ lodsw
+ shlb $1, %al
+ jnz 2f
+ lodsw
+ andb $63, %al
+ jz 2f
+ lodsw
+ lodsw
+ andb $63, %al
+ jz 2f
+ lodsl
+ negl %eax
+ jnc 2f
+ lodsl
+ negl %eax
+ jc 3b
+2:
+ stc /* invalid partition table */
+3:
+ pushfw
+
+ /* disable the boot of non-MBR bootsector ? */
+ testb $2, %cs:0x02 /* test bit1 of the third byte */
+ jz 2f /* zero means non-MBR enabled */
+ popfw
+ jc 1f /* invalid partition table, print "Error" */
+
+ /* the partition table is valid */
+ pushfw
+
+2:
+ /* the check passed, and the boot is permitted */
+ popfw
+
+ jc 2f /* invalid partition table */
+
+ /* use partition table in MBR instead */
+
+ /* copy 72 bytes at 0000:7bb8 to 0000:7db8 */
+
+ movw $0x7bb8, %si
+ movw $0x7db8, %di
+ movw $36, %cx
+ cld
+ repz movsw
+
+2:
+ testb $0x80, %cs:0x02 /* test bit 7 of the third byte */
+ jz 2f /* zero means boot prev-MBR first */
+
+ movw $(Cannot_find_GRLDR_string - _start1), %si
+ call print_message /* CS:SI points to message string */
+//#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+ movw $(press_space_bar_string - _start1), %si
+ cmpw $0x3920, %cs:0x04
+ je 3f
+ movw $0x3920, %cs:0x04
+ #;movw $(press_hot_key_string - _start1), %si
+3:
+ call print_message /* CS:SI points to message string */
+ movw $(prev_MBR_string - _start1), %si
+ call print_message /* CS:SI points to message string */
+//#else
+// movw $(press_hot_key_pre - _start1), %si
+// call print_message
+// movw $(press_hot_key_name - _start1), %si
+// call print_message
+// movw $(press_hot_key_sub - _start1), %si
+// call print_message
+//#endif
+3:
+ call sleep_5_seconds
+ /* if hot-key is pressed, wait forever until another key is pressed. */
+ movb $0xff, %cs:0x03
+ jc 3b /* desired hot-key is pressed */
+2:
+ /* boot the previous MBR */
+
+ /* clear the DUCE indicator */
+ movl $0, 0x5FC /* DS=ES=0 */
+
+ //movb $0x80, %dl
+ ljmp $0, $0x7c00
+1:
+ /* no previous MBR, print "Error" */
+ ///* Note the 0000:7C00 is on the stack */
+ //popw %ax /* AX=0x0000 */
+ //popw %ax /* AX=0x7C00 */
+
+ testb $0x80, %cs:0x02 /* are we called prior to the GRLDR search? */
+ jnz 1f /* no, it is a failure at last */
+ /* yes, so return to the caller */
+ movw $(continue_string - _start1), %si
+ call print_message /* CS:SI points to message string */
+ call sleep_5_seconds
+ ret
+1:
+ movw $(message_string_helper - _start1), %si
+ call print_message /* CS:SI points to message string */
+1: jmp 1b /* hang */
+
+sleep_5_seconds:
+ /* sleep 5 seconds */
+
+ /* sleep forever if %cs:0x03 is 0xff */
+
+ /* calculate the timeout ticks */
+
+ pushw %ds
+ pushl %esi
+ pushl %edx
+
+ movl $0xffffffff, %edx
+ movzbl %cs:0x03, %eax
+ cmpb $0xff, %al
+ je 1f
+ movl $18, %edx /* 18.2 ticks per second. We simply use 18. */
+ mulw %dx /* EDX=0, EAX=ticks */
+ xchgw %ax, %dx /* EAX=0, EDX=ticks */
+1:
+ xorw %ax, %ax
+ movw %ax, %ds
+ movl 0x46c, %eax /* initial tick */
+ movl %eax, %ecx /* ECX=initial tick */
+ testl %edx, %edx
+ js 1f
+ addl %edx, %eax /* EAX=timeout tick */
+ pushl %eax
+
+ movzbl %cs:0x03, %eax
+ orl %eax, %eax
+ jz 3f
+
+ movw $(hot_key_timeout_pre - _start1), %si
+ pushl %eax
+ call print_message
+ popl %eax
+
+ movw $(hot_key_timeout_num - _start1), %si
+ call print_decimal
+3:
+ movl %ecx, %esi
+ addl $18, %esi
+
+ popl %eax
+ jmp 3f
+1:
+ movl %edx, %eax /* EAX=0xffffffff */
+ movl %edx, %esi
+3:
+ movl 0x46c, %ebx /* EBX=current tick */
+ cmpl %ecx, %ebx
+ jnb 2f
+
+ /* current tick is less than initial tick, this means the ticks have
+ * overflowed to the next day, and EBX is rather small. */
+ xorl %ecx, %ecx
+ movl %edx, %eax
+ movl $18, %esi
+2:
+ /* check if there is any key press. */
+ pushl %eax
+ movb $1, %ah
+ int $0x16
+ pushw %ax
+ pushfw
+
+ movb $0x11, %ah
+ int $0x16
+ jnz 1f
+ popfw
+ jnz 2f
+
+ /* no, there is no key press. */
+
+ popw %ax
+ popl %eax
+
+ cmpl %esi, %ebx
+ jb 4f
+ pushl %esi
+ pushl %eax
+ pushl %edx
+
+
+ subl %esi, %eax
+ xorl %edx, %edx
+ movl $18, %esi
+ divl %esi
+
+ movw $(hot_key_timeout_num - _start1), %si
+ pushl %ebx
+ call print_decimal
+ popl %ebx
+
+ popl %edx
+ popl %eax
+ popl %esi
+ addl $18, %esi
+4:
+ cmpl %eax, %ebx /* timeout? */
+ jbe 3b /* no, continue to wait */
+
+ /* timeout reached, CF=0, no key pressed. */
+ popl %edx
+ popl %esi
+ popw %ds
+ ret
+1:
+ popfw
+2:
+ /* yes, there is a key press. */
+#if 0
+ /* clear the keyboard buffer */
+ movb $1, %ah
+ int $0x16
+ jz 1f /* no keys, end */
+ movb $0, %ah
+ int $0x16 /* discard the key */
+ jmp 1b
+1:
+#endif
+
+ /* check if it is the desired key. */
+
+ xorw %cs:0x04, %ax /* CF=0 */
+ popw %ax
+ je 1f
+ xorw %cs:0x04, %ax /* CF=0 */
+ jne 2f /* not desired, return CF=0 */
+
+ /* remove the desired key from the keyboard buffer. */
+
+ movb $0, %ah
+ int $0x16 /* discard the key */
+ jmp 3f
+1:
+ /* remove the desired key from the keyboard buffer. */
+
+ movb $0x10, %ah
+ int $0x16 /* discard the key */
+3:
+ stc /* CF=1, the desired key pressed */
+2:
+ popl %eax
+ popl %edx
+ popl %esi
+ popw %ds
+ ret
+
+out_decimal:
+ /*
+ * input: EAX = number, CS:SI = buffer
+ */
+
+ pushl %edx
+ pushl %ecx
+ pushw %bx
+
+ movl $10, %ecx
+ movw %si, %bx
+
+1:
+ xorl %edx, %edx
+ divl %ecx
+ addb $'0', %dl
+ movb %dl, %cs:(%si)
+ incw %si
+ orl %eax, %eax
+ jnz 1b
+
+ pushw %si
+
+1:
+ decw %si
+ cmpw %bx, %si
+ jbe 1f
+ movb %cs:(%si), %al
+ xchgb %al, %cs:(%bx)
+ movb %al, %cs:(%si)
+ incw %bx
+ jmp 1b
+1:
+
+ popw %si
+
+ popw %bx
+ popl %ecx
+ popl %edx
+ ret
+
+print_decimal:
+ pushw %si
+ call out_decimal
+
+1:
+ cmpb $'\b', %cs:(%si)
+ jz 2f
+ movb $' ', %cs:(%si)
+ incw %si
+ jmp 1b
+2:
+ popw %si
+ call print_message
+ ret
+
+#if 0
+modify_NTFS_boot_record:
+
+ /* before the call:
+ * AH= partition number
+ * AL= 0xB6 ; 0xB6 is opcode of "MOV DH,imm8"
+ * DL= drive number
+ *
+ * on return: CF=0 if there is NTFS boot record;
+ * CF=1 otherwise.
+ * CF of flags_orig on the stack will set if CF=1
+ */
+
+ /*
+ *
+ * the current stack is:
+ *
+ * SP + 40 : DS
+ * SP + 38 : ES
+ * SP + 34 : EAX
+ * SP + 30 : ECX
+ * SP + 26 : EDX
+ * SP + 22 : EBX
+ * SP + 18 : ESP_temp
+ * SP + 14 : EBP
+ * SP + 10 : ESI
+ * SP + 6 : EDI
+ * SP + 4 : flags_orig
+ * SP + 2 : SI ; SI points to old entry in MBR
+ * SP : return_IP
+ *
+ */
+
+ /* DS=ES=FS_BOOT */
+
+ /* change NTLDR to GRLDR */
+
+ /* check GR or NT or anything else */
+
+ pushw %ax
+
+ movw $0x200, %si
+ lodsw
+ cmpw $5, %ax
+ jne 1f /* failure */
+ lodsw
+ testb %ah, %ah /* high byte of unicode ASCII should be 0 */
+ jne 1f /* failure */
+
+ /* 'N' should be a capital letter */
+
+ cmpb $0x41, %al /* Less than 'A' */
+ jb 1f /* failure */
+ cmpb $0x5A, %al /* Greater than 'Z'*/
+ ja 1f /* failure */
+
+ xchgw %ax, %cx /* save AX to CX. CL='N' */
+
+ lodsw
+ testb %ah, %ah /* high byte of unicode ASCII should be 0 */
+ jne 1f /* failure */
+
+ /* 'T' should be a capital letter */
+
+ cmpb $0x41, %al /* Less than 'A' */
+ jb 1f /* failure */
+ cmpb $0x5A, %al /* Greater than 'Z'*/
+ ja 1f /* failure */
+
+ movb %al, %ch /* save AL to CH. CH='T' */
+
+ lodsw
+ cmpw $0x4C, %ax /* 'L' */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x44, %ax /* 'D' */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x52, %ax /* 'R' */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x04, %ax /* length of "$I30" */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x24, %ax /* '$' */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x49, %ax /* 'I' */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x33, %ax /* '3' */
+ jne 1f /* failure */
+ lodsw
+ cmpw $0x30, %ax /* '0' */
+ jne 1f /* failure */
+
+
+ /* assume it is NT bootsector. first, find "NTLDR". CX holds "NT" */
+ movw $0x0100, %di
+ movb %cl, %al /* AL="N" */
+ movb $1, %ah /* AH=Carry for SAHF below */
+ movl $0x52444c00, %ebx /* "LDR" */
+ movb %ch, %bl /* 'T' */
+ movw $0x00fa, %cx
+
+ /* now AL holds 'N' and BL holds 'T' */
+
+ //cld /* already upward */
+3:
+ repnz scasb /* find "N" */
+ jcxz 4f /* gets the end, exit */
+ cmpl %ebx, (%di) /* is it "NTLDR"? */
+ jnz 3b /* no, continue to find */
+
+ /* "NTLDR" is found, so we believe it is NT boot sector. */
+
+ movw $0x5247, -1(%di) /* change "NT" to "GR" */
+
+ /* CF=0 for now */
+
+ lahf /* Load Flags into AH */
+ /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */
+ /* AH = binary xxxxxxx0 */
+ jmp 3b
+4:
+ sahf /* Store AH into flags SF ZF xx AF xx PF xx CF */
+
+ /* CF=0 means "NTLDR" is found, CF=1 means "NTLDR" is not found. */
+
+ jc 1f /* failure */
+
+ movl $0x00520047, 0x202 /* change to "G R L D R" */
+
+ /* check NT 4.0 */
+
+ movw $0x406, %si
+ movl (%si), %ebx /* NT 4.0 */
+ cmpl $0x03E8B800, %ebx /* MOV AX, 03E8 */
+ jnz 3f
+
+ movl 0x84, %ebx
+ cmpl $0x680007E8, %ebx /* call 008e; push (0D00) */
+ jnz 3f
+
+// movw 0x154, %bx /* CR LF at end of "A disk read error occurred." */
+// cmpw $0x0A0D, %bx /* CR LF */
+// jnz 3f
+// movw 0x180, %bx /* CR LF at end of "A kernel file is missing from the disk." */
+// cmpw $0x0A0D, %bx /* CR LF */
+// jnz 3f
+// movw 0x1A8, %bx /* CR LF at end of "A kernel file is too discontiguous." */
+// cmpw $0x0A0D, %bx /* CR LF */
+// jnz 3f
+// movw 0x1F8, %bx /* CR LF at end of "NTLDR is compressed." */
+// cmpw $0x0A0D, %bx /* CR LF */
+// jnz 3f
+
+ movl 0xE8, %ebx
+ cmpl $0x13CD80B2, %ebx /* "B2 80"="mov DL, 80", "CD 13"="int 13" */
+ jnz 3f
+
+ popw %ax
+ movw %ax, 4(%si)
+
+ movl $0x68909090, %ebx /* nop;nop;nop;push (0D00) */
+ movl %ebx, 0x84
+
+// /* change CRLF in NTFS error messages to spaces */
+// movw $0x2020, %bx /* change CRLF to 2 spaces */
+// movw %bx, 0x154
+// movw %bx, 0x180
+// movw %bx, 0x1A8
+// movw %bx, 0x1F8
+
+ movb %dl, 0xE9 /* modify drive number */
+
+ /* modify NTFS boot record */
+ movb $0xea, %al /* ljmp, hand over the control to supervisor */
+ movb %al, 0x122
+ //movw $(try_next_partition - _start1), %ax /* offset for ljmp */
+ movw $MONITOR, %ax /* offset for ljmp */
+ movw %ax, 0x123
+ //movw %cs, %ax /* AX=0x9400, segment for ljmp */
+ xorw %ax, %ax
+ movw %ax, 0x125
+
+ movw $(NTFS4_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+ clc
+ ret
+3:
+ /* check NT 5.0 */
+
+ movw $0x44b, %si
+ movl (%si), %ebx /* NT 5.0 */
+ cmpl $0x03E8B800, %ebx /* MOV AX, 03E8 */
+ jz 2f
+
+ movw $0x479, %si
+ movl (%si), %ebx /* NT 5.1 SP2 */
+ cmpl $0x03E8B800, %ebx /* MOV AX, 03E8 */
+ jnz 1f
+2:
+ movl 0x71, %ebx
+ cmpl $0x680053E8, %ebx /* call 00C7; push (0D00) */
+ jnz 1f
+
+ //movw 0x183, %bx /* CR LF at begin of "A disk read error occurred." */
+ movb 0x1F8, %bl
+ movb $1, %bh
+ movw (%bx), %bx
+ cmpw $0x0A0D, %bx /* CR LF */
+ jnz 1f
+ //movw 0x1A0, %bx /* CR LF at begin of "NTLDR is missing." */
+ movb 0x1F9, %bl
+ movb $1, %bh
+ movw (%bx), %bx
+ cmpw $0x0A0D, %bx /* CR LF */
+ jnz 1f
+ //movw 0x1B3, %bx /* CR LF at begin of "NTLDR is compressed." */
+ movb 0x1FA, %bl
+ movb $1, %bh
+ movw (%bx), %bx
+ cmpw $0x0A0D, %bx /* CR LF */
+ jnz 1f
+
+ popw %ax
+ movw %ax, 4(%si)
+
+ movl $0x68909090, %ebx /* nop;nop;nop;push (0D00) */
+ movl %ebx, 0x71
+
+ /* change CRLF in NTFS error messages to spaces */
+ movw $0x2020, %ax
+ movb 0x1F8, %bl
+ movb $1, %bh
+ movw %ax, (%bx) // 0x183
+ movb 0x1F9, %bl
+ movb $1, %bh
+ movw %ax, (%bx) // 0x1A0
+ movb 0x1FA, %bl
+ movb $1, %bh
+ movw %ax, (%bx) // 0x1B3
+
+ /* modify NTFS boot record */
+ movb $0xEA, %al /* ljmp, hand over the control to supervisor */
+ movb %al, 0x167
+ //movw $(try_next_partition - _start1), %ax /* offset for ljmp */
+ movw $MONITOR, %ax /* offset for ljmp */
+ movw %ax, 0x168
+ //movw %cs, %ax /* AX=0x9400, segment for ljmp */
+ xorw %ax, %ax
+ movw %ax, 0x16A
+
+ cmpw $0x44b, %si
+ jne 2f
+ movw $(NTFS5_message - _start1), %si
+ jmp 3f
+2:
+ movw $(NTFS5p_message - _start1), %si
+3:
+ call print_message /* CS:SI points to message string */
+ clc
+ ret
+1:
+ /* NTFS boot record not found. */
+
+ movw $(NTFS_no_boot_record_message - _start1), %si
+ call print_message /* CS:SI points to message string */
+
+ popw %ax
+ popl %eax /* return_IP and SI */
+ popfw
+ stc
+ pushfw
+ pushl %eax /* return_IP and SI */
+ ret
+#endif
+
+//#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+move_helper:
+
+ /* called only once and only when the boot loader loaded this code */
+ pushw %si
+ pushw %bx
+ pushl %eax
+
+ movw $0x0003, %ax /* set display mode: 80*25 color text */
+ int $0x10
+
+ movw $0x200, %si
+ movw %si, %di
+ movw $0xf00, %cx
+ cld
+ repz movsw
+
+ popl %eax
+ popw %bx
+ popw %si
+ ret
+//#endif
+
+#if (defined(GRLDR_MBR)) || (defined(GRLDR_INSTALL))
+filesystem_boot:
+ /* The partition boot record successfully modified, just boot it */
+
+ /*
+ * The boot might fail, but we want to take back the control.
+ * So we save the registers now.
+ */
+ pushw %ds
+ pushw %es
+ pushal
+
+ /* DS=CS=GRLDR_CS, ES=FS_BOOT */
+
+ /* save GRLDR_CS */
+
+ movw %es, %bx # save old ES to BX
+
+ cli
+ lgdt gdt - _start1
+ movl %cr0, %eax
+ orb $1, %al
+ movl %eax, %cr0
+
+ movw $8, %si
+ movw %si, %es
+
+ xorl %esi, %esi
+ xorl %edi, %edi
+ movl $(0x9000 / 4), %ecx
+
+ cld
+ repz movsl
+
+ movw $16, %si
+ movw %si, %es
+
+ andb $0xfe, %al
+ movl %eax, %cr0
+
+ movw %bx, %es # restore ES from BX
+
+ /* move FS_BOOT:0000 to 0:7c00 */
+#if 0
+ /* for single sector boot record */
+ movw $0x0200, %cx /* move 2 sectors, the old FS_BOOT:0000 will
+ * keep untouched. */
+#else
+ /* for 4-sector NTFS boot record */
+ movw $0x0400, %cx /* move 4 sectors, the old FS_BOOT:0000 will
+ * keep untouched. */
+#endif
+ xorw %si, %si
+ pushw %si /* SI=0, for the segment of 0000:7c00 */
+ movw $0x7c00, %di
+ pushw %di /* DI=0x7c00, for the offset of 0000:7c00 */
+ pushw %es /* ES=FS_BOOT */
+ popw %ds /* DS=FS_BOOT */
+ pushw %si /* SI=0 */
+ popw %es /* ES=0 */
+ cld
+ repz movsw
+
+ movw $MONITOR, %di
+ movw $(restore_GRLDR_CS - _start1), %si
+ movw $((gdt_end - restore_GRLDR_CS) / 4), %cx
+ cld
+ repz cs movsl /* CS segment override prefix(=0x2E) */
+
+ pushw %es /* ES=0 */
+ popw %ds /* DS=0 */
+ sti
+ lret //ljmp $0, $0x7c00
+#endif
+
+press_space_bar_string:
+ .ascii "\r\nPress space bar\0"
+
+press_hot_key_pre:
+ .ascii "\r\nPress \0"
+
+press_hot_key_sub:
+ .ascii " to start GRUB, any other key to boot previous MBR ...\0"
+
+hot_key_timeout_pre:
+ .ascii "\r\nTimeout : \0"
+
+hot_key_timeout_num:
+ .ascii " \b\b\b\0"
+
+continue_string:
+ .ascii "\r\nInvalid previous MBR. Press any key to start GRUB ...\0"
+
+Cannot_find_GRLDR_string:
+ .ascii "\r\nCannot find GRLDR.\0"
+
+prev_MBR_string:
+ .ascii " to hold the screen, any other key to boot previous MBR ...\0"
+
+Error_while_reading_string:
+ .ascii "\r\nError while reading MBR of \0"
+
+drive_number_string:
+ .ascii "drive (hd0 ) \0"
+
+partition_boot_indicator_string:
+ .ascii "\r\nInvalid boot indicator in partition table of \0"
+
+partition_sectors_per_track_string:
+ .ascii "\r\nInvalid sectors_per_track in partition table of \0"
+
+partition_start_sector_string:
+ .ascii "\r\nInvalid start_sector in partition table of \0"
+
+partition_end_sector_string:
+ .ascii "\r\nInvalid end_sector in partition table of \0"
+
+no_boot_signature_string:
+ .ascii "\r\nNo boot signature in partition table of \0"
+
+message_string_helper:
+ .ascii "\r\nError: Cannot find GRLDR in all devices. Press Ctrl+Alt+Del to restart.\0"
+
+partition_message:
+ .ascii "\r\nTry (hd0,0 ) : \0"
+
+EXT2_message:
+ .ascii "EXT2: \0"
+NTFS4_message:
+ .ascii "NTFS4: \0"
+NTFS5_message:
+ .ascii "NTFS5: \0"
+NTFS5p_message:
+ .ascii "NTFS5p: \0"
+FAT32_message:
+ .ascii "FAT32: \0"
+FAT16_message:
+ .ascii "FAT16: \0"
+FAT12_message:
+ .ascii "FAT12: \0"
+non_MS_message:
+ .ascii "non-MS: skip \0"
+extended_message:
+ .ascii "Extended: \0"
+invalid_message:
+ .ascii "invalid or null \0"
+#if 0
+NTFS_no_boot_record_message:
+ .ascii "This partition is NTFS but with unknown boot record. Please\r\ninstall Microsoft NTFS boot sectors to this partition correctly, or create an\r\nFAT12/16/32 partition and place the same copy of GRLDR and MENU.LST there.\0"
+#endif
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+ . = _start1 + 0x1ffa
+#else
+ . = . + (0x3ec - ((. - _start1) % 0x200)) % 0x200
+
+press_hot_key_name:
+
+ /* hot key name, the address is (grldr_signature - 16) */
+
+ .ascii "hot-key\0"
+
+ . = press_hot_key_name + 14
+
+ //. = . + (0x3fa - ((. - _start1) % 0x200)) % 0x200
+#endif
+
+ /* version word of grldr.mbr, the address is (grldr_signature - 2) */
+
+ .word 2
+
+grldr_signature:
+ .byte 0x47, 0x52, 0x55, 0xaa /* signature for helper */
+
+ .align 0x200
+
+#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL))
+
+ /* pre_stage2 start at 0x2000 for grldr */
+
+ . = _start1 + 0x2000
+
+#endif
+
+#if defined(GRLDR_MBR)
+ /* if the size is less than 8192, let it be 8192 */
+ . = . + (0x2000 - (. - _start1)) * (0x4000 / (. - _start1 + 0x2001))
+#endif
+
+pre_stage2_start:
+
+
diff --git a/debian/grub-extras/ntldr-img/grubinst.c b/debian/grub-extras/ntldr-img/grubinst.c
new file mode 100644
index 0000000..2f7561a
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/grubinst.c
@@ -0,0 +1,1043 @@
+/*
+ * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
+ * Copyright (C) 2007 Bean (bean123@126.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifndef WIN32
+
+#define O_BINARY 0
+
+#endif
+
+#include "grub_mbr.h"
+#include "utils.h"
+#include "version.h"
+
+// Application flags, used by this program
+
+#define AFG_VERBOSE 1
+#define AFG_PAUSE 2
+#define AFG_READ_ONLY 4
+#define AFG_NO_BACKUP_MBR 8
+#define AFG_FORCE_BACKUP_MBR 16
+#define AFG_RESTORE_PREVMBR 32
+#define AFG_LIST_PART 64
+#define AFG_IS_FLOPPY 128
+#define AFG_LBA_MODE 256
+#define AFG_CHS_MODE 512
+#define AFG_OUTPUT 1024
+#define AFG_EDIT 2048
+
+// Grldr flags, this flag is used by grldr.mbr
+
+#define GFG_DISABLE_FLOPPY 1
+#define GFG_DISABLE_OSBR 2
+#define GFG_DUCE 4
+#define GFG_PREVMBR_LAST 128
+
+#define APP_NAME "grubinst: "
+
+#define print_pause if (afg & AFG_PAUSE) {fputs("Press <ENTER> to continue ...\n",stderr); fflush(stderr); fgetc(stdin);}
+
+#define print_apperr(a) { fprintf(stderr,APP_NAME "%s\n",a); print_pause; }
+#define print_syserr(a) { perror(APP_NAME a); print_pause; }
+
+static void help(void)
+{
+ fputs("Usage:\n"
+ "\tgrubinst [OPTIONS] DEVICE_OR_FILE\n\n"
+ "OPTIONS:\n\n"
+ "\t--help,-h\t\tShow usage information\n\n"
+ "\t--pause\t\t\tPause before exiting\n\n"
+ "\t--version\t\tShow version information\n\n"
+ "\t--verbose,-v\t\tVerbose output\n\n"
+ "\t--list-part,-l\t\tList all logical partitions in DEVICE_OR_FILE\n\n"
+ "\t--save=FN,-s=FN\t\tSave the orginal MBR/BS to FN\n\n"
+ "\t--restore=FN,-r=FN\tRestore MBR/BS from previously saved FN\n\n"
+ "\t--restore-prevmbr,-r\tRestore previous MBR saved in the second sector\n"
+ "\t\t\t\tof DEVICE_OR_FILE\n\n"
+ "\t--read-only,-t\t\tdo everything except the actual write to the\n"
+ "\t\t\t\tspecified DEVICE_OR_FILE. (test mode)\n\n"
+ "\t--no-backup-mbr\t\tdo not copy the old MBR to the second sector of\n"
+ "\t\t\t\tDEVICE_OR_FILE.\n\n"
+ "\t--force-backup-mbr\tforce the copy of old MBR to the second sector\n"
+ "\t\t\t\tof DEVICE_OR_FILE.(default)\n\n"
+ "\t--mbr-enable-floppy\tenable the search for GRLDR on floppy.(default)\n\n"
+ "\t--mbr-disable-floppy\tdisable the search for GRLDR on floppy.\n\n"
+ "\t--mbr-enable-osbr\tenable the boot of PREVIOUS MBR with invalid\n"
+ "\t\t\t\tpartition table (usually an OS boot sector).\n"
+ "\t\t\t\t(default)\n\n"
+ "\t--mbr-disable-osbr\tdisable the boot of PREVIOUS MBR with invalid\n"
+ "\t\t\t\tpartition table (usually an OS boot sector).\n\n"
+ "\t--duce\t\t\tdisable the feature of unconditional entrance\n"
+ "\t\t\t\tto the command-line.\n\n"
+ "\t--boot-prevmbr-first\ttry to boot PREVIOUS MBR before the search for\n"
+ "\t\t\t\tGRLDR.\n\n"
+ "\t--boot-prevmbr-last\ttry to boot PREVIOUS MBR after the search for\n"
+ "\t\t\t\tGRLDR.(default)\n\n"
+ "\t--preferred-drive=D\tpreferred boot drive number, 0 <= D < 255.\n\n"
+ "\t--preferred-partition=P\tpreferred partition number, 0 <= P < 255.\n\n"
+ "\t--time-out=T,-t=T\twait T seconds before booting PREVIOUS MBR. if\n"
+ "\t\t\t\tT is 0xff, wait forever. The default is 5.\n\n"
+ "\t\t\t\tbefore booting PREVIOUS MBR. K is a word\n"
+ "\t\t\t\tvalue, just as the value in AX register\n"
+ "\t\t\t\treturned from int16/AH=1. The high byte is the\n"
+ "\t\t\t\tscan code and the low byte is ASCII code. The\n"
+ "\t\t\t\tdefault is 0x3920 for space bar.\n\n"
+ "\t--key-name=S\t\tSpecify the name of the hot key.\n\n"
+ "\t--floppy,-f\t\tif DEVICE_OR_FILE is floppy, use this option.\n\n"
+ "\t--floppy=N\t\tif DEVICE_OR_FILE is a partition on a hard\n"
+ "\t\t\t\tdrive, use this option. N is used to specify\n"
+ "\t\t\t\tthe partition number: 0,1,2 and 3 for the\n"
+ "\t\t\t\tprimary partitions, and 4,5,6,... for the\n"
+ "\t\t\t\tlogical partitions.\n\n"
+ "\t--sectors-per-track=S\tspecifies sectors per track for --floppy.\n"
+ "\t\t\t\t1 <= S <= 63, default is 63.\n\n"
+ "\t--heads=H\t\tspecifies number of heads for --floppy.\n"
+ "\t\t\t\t1 <= H <= 256, default is 255.\n\n"
+ "\t--start-sector=B\tspecifies hidden sectors for --floppy=N.\n\n"
+ "\t--total-sectors=C\tspecifies total sectors for --floppy.\n"
+ "\t\t\t\tdefault is 0.\n\n"
+ "\t--lba\t\t\tuse lba mode for --floppy. If the floppy BIOS\n"
+ "\t\t\t\thas LBA support, you can specify --lba here.\n"
+ "\t\t\t\tIt is assumed that all floppy BIOSes have CHS\n"
+ "\t\t\t\tsupport. So you would rather specify --chs.\n"
+ "\t\t\t\tIf neither --chs nor --lba is specified, then\n"
+ "\t\t\t\tthe LBA indicator(i.e., the third byte of the\n"
+ "\t\t\t\tboot sector) will not be touched.\n\n"
+ "\t--chs\t\t\tuse chs mode for --floppy. You should specify\n"
+ "\t\t\t\t--chs if the floppy BIOS does not support LBA.\n"
+ "\t\t\t\tWe assume all floppy BIOSes have CHS support.\n"
+ "\t\t\t\tSo it is likely you want to specify --chs.\n"
+ "\t\t\t\tIf neither --chs nor --lba is specified, then\n"
+ "\t\t\t\tthe LBA indicator(i.e., the third byte of the\n"
+ "\t\t\t\tboot sector) will not be touched.\n\n"
+ "\t--install-partition=I\tInstall the boot record onto the boot area of\n"
+ "\t-p=I\t\t\tpartition number I of the specified hard drive\n"
+ "\t\t\t\tor harddrive image DEVICE_OR_FILE.\n\n"
+ "\t--boot-file=F,-b=F\tChange the name of boot file.\n\n"
+ "\t--load-seg=S\t\tChange load segment for boot file.\n\n"
+ "\t--grub2,-2\t\tLoad grub2 kernel g2ldr instead of grldr.\n\n"
+ "\t--output,-o\t\tSave embeded grldr.mbr to DEVICE_OR_FILE.\n\n"
+ "\t--edit,-e\t\tEdit external grldr/grldr.mbr.\n",
+ stderr);
+}
+
+int afg,gfg,def_drive,def_part,time_out,hot_key,part_num;
+int def_spt,def_hds,def_ssc,def_tsc;
+char *save_fn,*restore_fn,boot_file_83[12];
+const char *key_name;
+const char *boot_file;
+unsigned short load_seg;
+
+static char fn_buf[24];
+
+static char* get_disk_name(int n)
+{
+#if defined(WIN32)
+ sprintf(fn_buf,"\\\\.\\PhysicalDrive%d",n);
+#elif defined(LINUX)
+ sprintf(fn_buf,"/dev/hd%c",'a'+n);
+#elif defined(FREEBSD)
+ sprintf(fn_buf,"/dev/ad%d",n);
+#else
+ print_apperr("Disk device is not supported in your system");
+ return NULL;
+#endif
+ return fn_buf;
+}
+
+static char* get_flop_name(int n)
+{
+#if defined(WIN32)
+ if (n>1)
+ {
+ print_apperr("Only two floppy drives are supported");
+ return NULL;
+ }
+ sprintf(fn_buf,"\\\\.\\%c:",'A'+n);
+#elif defined(LINUX) || defined(FREEBSD)
+ sprintf(fn_buf,"/dev/fd%d",n);
+#else
+ print_apperr("Floppy device is not supported in your system");
+ return NULL;
+#endif
+ return fn_buf;
+}
+
+static char* parse_fname(char* fn)
+{
+ if ((afg & AFG_OUTPUT) && (fn[0]=='('))
+ {
+ print_apperr("Can\'t use device name while using --output option");
+ return NULL;
+ }
+ if ((! strncmp(fn,"(hd",3)) || (! strncmp(fn,"(fd",3)))
+ {
+ int n;
+ char *p;
+
+ n=strtol(&fn[3],&p,0);
+ if ((n<0) || (n>=MAX_DISKS))
+ {
+ print_apperr("Invalid device number");
+ return NULL;
+ }
+ if (*p==',')
+ {
+ part_num=strtol(p+1,&p,0);
+ if ((part_num<0) || (part_num>=MAX_PARTS))
+ {
+ print_apperr("Invalid partition number");
+ return NULL;
+ }
+ }
+ if ((*p!=')') || (*(p+1)!=0))
+ {
+ print_apperr("Invalid device name");
+ return NULL;
+ }
+ if (fn[1]=='h')
+ fn=get_disk_name(n);
+ else
+ {
+ fn=get_flop_name(n);
+ afg|=AFG_IS_FLOPPY;
+ }
+ }
+ return fn;
+}
+
+static char* str_upcase(char* str)
+{
+ int i;
+
+ for (i=0;str[i];i++)
+ if ((str[i]>='a') && (str[i]<='z'))
+ str[i]-='a'-'A';
+
+ return str;
+}
+
+static char* str_lowcase(char* str)
+{
+ int i;
+
+ for (i=0;str[i];i++)
+ if ((str[i]>='A') && (str[i]<='Z'))
+ str[i]+='a'-'A';
+
+ return str;
+}
+
+static int SetBootFile(char* fn)
+{
+ char* pc;
+
+ if (*fn==0)
+ return 1;
+ if (strlen(fn)>7)
+ return 1;
+ pc=strchr(fn,'.');
+ if (pc)
+ if ((pc==fn) || (pc-fn>8) || (strlen(pc+1)>3))
+ return 1;
+ str_upcase(fn);
+ memset(boot_file_83,' ',sizeof(boot_file_83)-1);
+ if (pc)
+ {
+ memcpy(boot_file_83,fn,pc-fn);
+ memcpy(&boot_file_83[8],pc+1,strlen(pc+1));
+ }
+ else
+ memcpy(boot_file_83,fn,strlen(fn));
+ str_lowcase(fn);
+ boot_file=fn;
+ return 0;
+}
+
+static void list(int hd)
+{
+ xde_t xe;
+
+ xe.cur=xe.nxt=0xFF;
+ fprintf(stderr," # id base leng\n");
+ while (! xd_enum(hd,&xe))
+ fprintf(stderr,"%2d %02" PRIX64 " %8" PRIX64 " %8" PRIX64 "\n",
+ xe.cur,
+ (uint64_t) xe.dfs,
+ (uint64_t) xe.bse,
+ (uint64_t) xe.len);
+}
+
+static int is_grldr_mbr(unsigned char* buf)
+{
+ int i,n;
+
+ i=0x1B7;
+ n=sizeof("Missing MBR-helper.")-1;
+
+ while ((i>n) && (buf[i]==0))
+ i--;
+ return (! memcmp(&buf[i-n+1],"Missing MBR-helper.", sizeof("Missing MBR-helper.")));
+}
+
+static int install(char* fn)
+{
+ int hd = -1,nn,fs,slen;
+ unsigned char prev_mbr[sizeof(grub_mbr)];
+ unsigned long ssec;
+
+ if (fn==NULL)
+ return 1;
+
+ if (afg & AFG_EDIT)
+ {
+ unsigned short r1,r2;
+
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Edit mode\n");
+ hd=open(fn,O_RDWR | O_BINARY,0644);
+ if (hd==-1)
+ {
+ print_syserr("open");
+ return errno;
+ }
+ r1=get16(&grub_mbr[0x1FFA],0);
+ nn=read(hd,grub_mbr,sizeof(grub_mbr));
+ if (nn==-1)
+ {
+ print_syserr("read");
+ close(hd);
+ return errno;
+ }
+ if (nn<(int)sizeof(grub_mbr))
+ {
+ print_apperr("The input file is too short");
+ close(hd);
+ return 1;
+ }
+ if (get32(&grub_mbr[0x1FFC],0)!=0xAA555247)
+ {
+ print_apperr("Invalid input file");
+ close(hd);
+ return 1;
+ }
+ r2=get16(&grub_mbr[0x1FFA],0);
+ if (r1!=r2)
+ {
+ char buf[80];
+
+ sprintf(buf,"Version number mismatched (old=%d new=%d)",r2,r1);
+ print_apperr(buf);
+ close(hd);
+ return 1;
+ }
+ go_sect(hd,0);
+ afg |= AFG_OUTPUT;
+ }
+
+ if (boot_file)
+ {
+ unsigned short ofs;
+
+ // Patching the FAT32 boot sector
+ ofs=get16(&grub_mbr,0x400+0x1EC) & 0x7FF;
+ strcpy((char *) &grub_mbr[0x400+ofs],boot_file_83);
+ if (load_seg)
+ set16(&grub_mbr,0x400+0x1EA,load_seg);
+
+ // Patching the FAT12/FAT16 boot sector
+ ofs=get16(&grub_mbr,0x600+0x1EC) & 0x7FF;
+ strcpy((char *) &grub_mbr[0x600+ofs],boot_file_83);
+ if (load_seg)
+ set16(&grub_mbr,0x600+0x1EA,load_seg);
+
+ // Patching the EXT2 boot sector
+ ofs=get16(grub_mbr,0x800+0x1EE) & 0x7FF;
+ strcpy((char *) &grub_mbr[0x800+ofs],boot_file);
+
+ // Patching the NTFS sector
+ ofs=get16(grub_mbr,0xA00+0x1EC) & 0x7FF;
+ strcpy((char *) &grub_mbr[0xA00+ofs],boot_file);
+ if (load_seg)
+ set16(grub_mbr,0xA00+0x1EA,load_seg);
+
+ if (afg & AFG_VERBOSE)
+ {
+ fprintf(stderr,"Boot file changed to %s\n",boot_file);
+ if (load_seg)
+ fprintf(stderr,"Load segment changed to %04X\n",load_seg);
+ }
+ }
+
+ if (afg & AFG_OUTPUT)
+ {
+ int mode;
+
+ mode=(! (afg & AFG_READ_ONLY))?(O_TRUNC | O_CREAT):0;
+ if (! (afg & AFG_EDIT))
+ {
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Extract mode\n");
+ hd=open(fn,O_RDWR | O_BINARY | mode,0644);
+ if (hd==-1)
+ {
+ print_syserr("open");
+ return errno;
+ }
+ }
+ if (! (afg & AFG_READ_ONLY))
+ if (write(hd,grub_mbr,sizeof(grub_mbr))!=sizeof(grub_mbr))
+ {
+ print_apperr("Write to output file fails");
+ close(hd);
+ return 1;
+ }
+ goto quit;
+ }
+
+ memset(&grub_mbr[512],0,512);
+ grub_mbr[2] = gfg;
+ grub_mbr[3]=time_out;
+ set16(&grub_mbr,4,hot_key);
+ grub_mbr[6] = def_drive;
+ grub_mbr[7] = def_part;
+ if ((key_name==NULL) && (hot_key==0x3920))
+ key_name="SPACE";
+ if (key_name)
+ strcpy((char *) &grub_mbr[0x1fec],key_name);
+
+ hd=open(fn,O_RDWR | O_BINARY,S_IREAD | S_IWRITE);
+ if (hd==-1)
+ {
+ print_syserr("open");
+ return errno;
+ }
+ if (afg & AFG_LIST_PART)
+ {
+ list(hd);
+ close(hd);
+ return 0;
+ }
+ if (part_num!=-1)
+ {
+ if (def_ssc!=-1)
+ ssec=def_ssc;
+ else
+ {
+ xde_t xe;
+
+ xe.cur=0xFF;
+ xe.nxt=part_num;
+ if (xd_enum(hd,&xe))
+ {
+ print_apperr("Partition not found");
+ close(hd);
+ return 1;
+ }
+ ssec=xe.bse;
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Part Fs: %02X (%s)\nPart Leng: %" PRIu64 "\n",xe.dfs,dfs2str(xe.dfs),
+ (uint64_t) xe.len);
+ }
+ }
+ else
+ ssec=0;
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Start sector: %" PRIu64 "\n", (uint64_t) ssec);
+ if ((ssec) && (go_sect(hd,ssec)))
+ {
+ print_apperr("Can\'t seek to the start sector");
+ close(hd);
+ return 1;
+ }
+ nn=read(hd,prev_mbr,sizeof(prev_mbr));
+ if (nn==-1)
+ {
+ print_syserr("read");
+ close(hd);
+ return errno;
+ }
+ if (nn<(int)sizeof(prev_mbr))
+ {
+ print_apperr("The input file is too short");
+ close(hd);
+ return 1;
+ }
+ fs=get_fstype(prev_mbr);
+ if (afg & AFG_VERBOSE)
+ {
+ fprintf(stderr,"Image type: %s\n",fst2str(fs));
+ if (fs==FST_MBR)
+ fprintf(stderr,"Num of heads: %d\nSectors per track: %d\n",mbr_nhd,mbr_spt);
+ }
+ if (fs==FST_OTHER)
+ {
+ print_apperr("Unknown image type");
+ close(hd);
+ return 1;
+ }
+ if (((part_num!=-1) || (afg & AFG_IS_FLOPPY)) && (fs==FST_MBR))
+ {
+ print_apperr("Should be a file system image");
+ close(hd);
+ return 1;
+ }
+ if ((part_num==-1) && ((afg & AFG_IS_FLOPPY)==0) && (fs!=FST_MBR))
+ {
+ print_apperr("Should be a disk image");
+ close(hd);
+ return 1;
+ }
+ if (fs==FST_MBR)
+ {
+ int n,nfs,sln;
+ unsigned long ofs;
+ unsigned char bs[1024];
+
+ ofs=0xFFFFFFFF;
+ for (n=0x1BE;n<0x1FE;n+=16)
+ if (prev_mbr[n+4])
+ {
+ if (ofs>get32(&prev_mbr[n],8))
+ ofs=get32(&prev_mbr[n],8);
+ }
+ if (ofs<(sizeof(prev_mbr)>>9))
+ {
+ print_apperr("Not enough room to install mbr");
+ close(hd);
+ return 1;
+ }
+ slen=sizeof(prev_mbr);
+ if (go_sect(hd,ofs))
+ {
+ print_apperr("Can\'t seek to the first partition");
+ close(hd);
+ return 1;
+ }
+ if (read(hd,bs,sizeof(bs))!=sizeof(bs))
+ {
+ print_apperr("Fail to read boot sector");
+ close(hd);
+ return 1;
+ }
+ nfs=get_fstype(bs);
+ if (nfs==FST_FAT32)
+ sln=0x5A - 0xB;
+ else if (nfs==FST_FAT16)
+ sln=0x3E - 0xB;
+ else
+ sln=0;
+ if (sln)
+ {
+ memcpy(&grub_mbr[0xB],&bs[0xB],sln);
+ set32(&grub_mbr[0],0x1C,0);
+ set16(&grub_mbr[0],0xE,get16(&grub_mbr[0],0xE) + ofs);
+ }
+ }
+ else if (fs==FST_NTFS)
+ slen=2048;
+ else
+ slen=512;
+
+ if (go_sect(hd,ssec))
+ {
+ print_apperr("Can\'t seek to the start sector");
+ close(hd);
+ return 1;
+ }
+
+ if (save_fn)
+ {
+ int h2;
+
+ h2=open(save_fn,O_CREAT | O_TRUNC | O_RDWR | O_BINARY,S_IREAD | S_IWRITE);
+ if (h2==-1)
+ {
+ print_syserr("open save file");
+ close(hd);
+ return errno;
+ }
+ nn=write(h2,prev_mbr,slen);
+ if (nn==-1)
+ {
+ print_syserr("write save file");
+ close(hd);
+ close(h2);
+ return errno;
+ }
+ if (nn<slen)
+ {
+ print_apperr("Can\'t write the whole MBR to the save file");
+ close(hd);
+ close(h2);
+ return 1;
+ }
+ close(h2);
+ }
+ if (afg & AFG_RESTORE_PREVMBR)
+ {
+ if (fs!=FST_MBR)
+ {
+ print_apperr("Not a disk image");
+ close(hd);
+ return 1;
+ }
+ if (memcmp(&prev_mbr[1024+3],"GRLDR",5))
+ {
+ print_apperr("GRLDR is not installed");
+ close(hd);
+ return 1;
+ }
+ if (get16(prev_mbr,512+510)!=0xAA55)
+ {
+ print_apperr("No previous saved MBR");
+ close(hd);
+ return 1;
+ }
+ memset(&grub_mbr,0,sizeof(grub_mbr));
+ memcpy(&grub_mbr,&prev_mbr[512],512);
+ memcpy(&grub_mbr[0x1b8],&prev_mbr[0x1b8],72);
+
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Restore previous MBR mode\n");
+ }
+ else
+ {
+ // Load MBR/BS from restore file or configure grub_mbr
+ if (restore_fn)
+ {
+ int h2;
+
+ h2=open(restore_fn,O_RDONLY | O_BINARY,S_IREAD);
+ if (h2==-1)
+ {
+ print_syserr("open restore file");
+ close(hd);
+ return errno;
+ }
+ nn=read(h2,grub_mbr,slen);
+ if (nn==-1)
+ {
+ print_syserr("read restore file");
+ close(hd);
+ close(h2);
+ return errno;
+ }
+ if ((nn<512) || ((nn & 0x1FF)!=0) ||
+ ((fs!=FST_EXT2) && (get16(grub_mbr,510)!=0xAA55)))
+ {
+ print_apperr("Invalid restore file");
+ close(hd);
+ close(h2);
+ return 1;
+ }
+ close(h2);
+ if (nn<slen)
+ memset(&grub_mbr[nn],0,slen-nn);
+
+ //if ((fs==FST_FAT16) || (fs==FST_FAT32) || (fs==FST_NTFS))
+ if (fs!=FST_EXT2)
+ {
+ int new_fs;
+
+ new_fs=get_fstype(grub_mbr);
+ if (new_fs!=fs)
+ {
+ print_apperr("Invalid restore file");
+ close(hd);
+ return 1;
+ }
+ }
+
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Restore mode\n");
+ }
+ else
+ {
+ if (fs==FST_MBR)
+ {
+ if (! (afg & AFG_NO_BACKUP_MBR))
+ {
+ int i;
+
+ if (afg & AFG_FORCE_BACKUP_MBR)
+ i=512;
+ else
+ for (i=1;i<512;i++)
+ if (prev_mbr[512+i]!=prev_mbr[512])
+ break;
+
+ if ((i==512) && (! is_grldr_mbr(prev_mbr)))
+ memcpy(&grub_mbr[512],prev_mbr,512);
+ else
+ memcpy(&grub_mbr[512],&prev_mbr[512],512);
+ }
+ memcpy(&grub_mbr[0x1b8],&prev_mbr[0x1b8],72);
+ }
+ else if (fs==FST_FAT16)
+ {
+ memcpy(grub_mbr,&grub_mbr[0x600],slen);
+ grub_mbr[0x41]=part_num;
+ }
+ else if (fs==FST_FAT32)
+ {
+ memcpy(grub_mbr,&grub_mbr[0x400],slen);
+ grub_mbr[0x5D]=part_num;
+ }
+ else if (fs==FST_NTFS)
+ {
+ memcpy(grub_mbr,&grub_mbr[0xA00],slen);
+ grub_mbr[0x57]=part_num;
+ }
+ else if (fs==FST_EXT2)
+ {
+ memcpy(&grub_mbr,&grub_mbr[0x800],slen);
+ grub_mbr[0x25]=part_num;
+ if (afg & AFG_LBA_MODE)
+ grub_mbr[2]=0x42;
+ else if (afg & AFG_CHS_MODE)
+ grub_mbr[2]=0x2;
+ if (def_spt!=-1)
+ set16(&grub_mbr,0x18,def_spt);
+ else if ((afg & AFG_IS_FLOPPY)==0)
+ set16(&grub_mbr,0x18,63);
+ if (def_hds!=-1)
+ set16(&grub_mbr,0x1A,def_hds);
+ else if ((afg & AFG_IS_FLOPPY)==0)
+ set16(&grub_mbr,0x1A,255);
+ if (def_tsc!=-1)
+ set32(&grub_mbr,0x20,def_tsc);
+ set32(&grub_mbr,0x1C,ssec);
+ // s_inode_size
+ if (prev_mbr[1024+0x4C]) // s_rev_level
+ set16(&grub_mbr,0x26,get16(&prev_mbr[1024],0x58));
+ else
+ set16(&grub_mbr,0x26,0x80);
+ // s_inodes_per_group
+ set32(&grub_mbr,0x28,get32(&prev_mbr[1024],0x28));
+ // s_first_data_block+1
+ set32(&grub_mbr,0x2C,get32(&prev_mbr[1024],0x14)+1);
+ }
+ else
+ {
+ // Shouldn't be here
+ print_apperr("Invalid file system");
+ close(hd);
+ return 1;
+ }
+ if ((fs==FST_FAT16) || (fs==FST_FAT32) || (fs==FST_NTFS))
+ {
+ if (afg & AFG_LBA_MODE)
+ grub_mbr[2]=0xe;
+ else if (afg & AFG_CHS_MODE)
+ grub_mbr[2]=0x90;
+ else
+ grub_mbr[2]=prev_mbr[2];
+ }
+
+ if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Install mode\n");
+ }
+ // Patch the new MBR/BS with information from prev_mbr
+ if (fs==FST_MBR)
+ memcpy(&grub_mbr[0x1b8],&prev_mbr[0x1b8],72);
+ else if (fs==FST_FAT16)
+ {
+ memcpy(&grub_mbr[0xB],&prev_mbr[0xB],0x3E - 0xB);
+ set32(grub_mbr,0x1C,ssec);
+ }
+ else if (fs==FST_FAT32)
+ {
+ memcpy(&grub_mbr[0xB],&prev_mbr[0xB],0x5A - 0xB);
+ set32(grub_mbr,0x1C,ssec);
+ }
+ else if (fs==FST_NTFS)
+ {
+ memcpy(&grub_mbr[0xB],&prev_mbr[0xB],0x54 - 0xB);
+ set32(grub_mbr,0x1C,ssec);
+ }
+ }
+ if (! (afg & AFG_READ_ONLY))
+ {
+ nn=write(hd,grub_mbr,slen);
+ if (nn==-1)
+ {
+ print_syserr("write");
+ close(hd);
+ return errno;
+ }
+ if (nn<slen)
+ {
+ print_apperr("Can\'t write the whole mbr");
+ close(hd);
+ return 1;
+ }
+ }
+ else if (afg & AFG_VERBOSE)
+ fprintf(stderr,"Read only mode\n");
+quit:
+ close(hd);
+ if (afg & AFG_PAUSE)
+ {
+ fputs("The MBR/BS has been successfully installed\n",stderr);
+ print_pause;
+ }
+ return 0;
+}
+
+int main(int argc,char** argv)
+{
+ int idx;
+
+ afg=gfg=0;
+ part_num=def_drive=def_part=def_spt=def_hds=def_ssc=def_tsc=-1;
+ afg=0;
+ gfg=GFG_PREVMBR_LAST;
+ time_out=5;
+ hot_key=0x3920;
+ save_fn=NULL;
+ restore_fn=NULL;
+ for (idx=1;idx<argc;idx++)
+ {
+ if (argv[idx][0]!='-')
+ break;
+ if ((! strcmp(argv[idx],"--help"))
+ || (! strcmp(argv[idx],"-h")))
+ {
+ help();
+ print_pause;
+ return 1;
+ }
+ else if (! strcmp(argv[idx],"--version"))
+ {
+ fprintf(stderr,"grubinst version : " VERSION "\n");
+ print_pause;
+ return 1;
+ }
+ else if ((! strcmp(argv[idx],"--verbose")) ||
+ (! strcmp(argv[idx],"-v")))
+ afg |=AFG_VERBOSE;
+ else if (! strcmp(argv[idx],"--pause"))
+ afg|=AFG_PAUSE;
+ else if ((! strcmp(argv[idx],"--read-only"))
+ || (! strcmp(argv[idx],"-t")))
+ afg|=AFG_READ_ONLY;
+ else if (! strcmp(argv[idx],"--no-backup-mbr"))
+ afg|=AFG_NO_BACKUP_MBR;
+ else if (! strcmp(argv[idx],"--force-backup-mbr"))
+ afg|=AFG_FORCE_BACKUP_MBR;
+ else if (! strcmp(argv[idx],"--mbr-enable-floppy"))
+ gfg&=~GFG_DISABLE_FLOPPY;
+ else if (! strcmp(argv[idx],"--mbr-disable-floppy"))
+ gfg|=GFG_DISABLE_FLOPPY;
+ else if (! strcmp(argv[idx],"--mbr-enable-osbr"))
+ gfg&=~GFG_DISABLE_OSBR;
+ else if (! strcmp(argv[idx],"--mbr-disable-osbr"))
+ gfg|=GFG_DISABLE_OSBR;
+ else if (! strcmp(argv[idx],"--duce"))
+ gfg|=GFG_DUCE;
+ else if (! strcmp(argv[idx],"--boot-prevmbr-first"))
+ gfg&=~GFG_PREVMBR_LAST;
+ else if (! strcmp(argv[idx],"--boot-prevmbr-last"))
+ gfg|=GFG_PREVMBR_LAST;
+ else if (! strncmp(argv[idx],"--preferred-drive=",18))
+ {
+ def_drive=strtol(&argv[idx][18],NULL,0);
+ if ((def_drive<0) || (def_drive>=255))
+ {
+ print_apperr("Invalid preferred drive number");
+ return 1;
+ }
+ }
+ else if (! strncmp(argv[idx],"--preferred-partition=",22))
+ {
+ def_part=strtol(&argv[idx][22],NULL,0);
+ if ((def_part<0) || (def_part>=255))
+ {
+ print_apperr("Invalid preferred partition number");
+ return 1;
+ }
+ }
+ else if ((! strncmp(argv[idx],"--time-out=",11)) ||
+ (! strncmp(argv[idx],"-t=",3)))
+ {
+ time_out=strtol((argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][11],NULL,0);
+ if ((time_out<0) || (time_out>255))
+ {
+ print_apperr("Invalid timeout value");
+ return 1;
+ }
+ }
+ else if ((! strncmp(argv[idx],"--key-name=",11)))
+ {
+ key_name=&argv[idx][11];
+ if (strlen(key_name)>13)
+ {
+ print_apperr("Key name too long");
+ return 1;
+ }
+ }
+ else if ((! strcmp(argv[idx],"--restore-prevmbr")) ||
+ (! strcmp(argv[idx],"-r")))
+ afg|=AFG_RESTORE_PREVMBR;
+ else if ((! strncmp(argv[idx],"--save=",7)) ||
+ (! strncmp(argv[idx],"-s=",3)))
+ {
+ save_fn=(argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][7];
+ if (*save_fn==0)
+ {
+ print_apperr("Empty filename");
+ return 1;
+ }
+ }
+ else if ((! strncmp(argv[idx],"--restore=",10)) ||
+ (! strncmp(argv[idx],"-r=",3)))
+ {
+ restore_fn=(argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][10];
+ if (*restore_fn==0)
+ {
+ print_apperr("Empty filename");
+ return 1;
+ }
+ }
+ else if ((! strcmp(argv[idx],"--list-part")) ||
+ (! strcmp(argv[idx],"-l")))
+ afg|=AFG_LIST_PART;
+ else if ((! strcmp(argv[idx],"--floppy")) ||
+ (! strcmp(argv[idx],"-f")))
+ afg|=AFG_IS_FLOPPY;
+ else if ((! strncmp(argv[idx],"--floppy=",9)) ||
+ (! strncmp(argv[idx],"--install-partition=",20)) ||
+ (! strncmp(argv[idx],"-p=",3)))
+ {
+ char *p;
+
+ if (argv[idx][2]=='f')
+ p=&argv[idx][9];
+ else if (argv[idx][2]=='i')
+ p=&argv[idx][20];
+ else
+ p=&argv[idx][3];
+ part_num=strtoul(p,NULL,0);
+ if ((part_num<0) || (part_num>=MAX_PARTS))
+ {
+ print_apperr("Invalid partition number");
+ return 1;
+ }
+ }
+ else if (! strcmp(argv[idx],"--lba"))
+ afg|=AFG_LBA_MODE;
+ else if (! strcmp(argv[idx],"--chs"))
+ afg|=AFG_CHS_MODE;
+ else if (! strncmp(argv[idx],"--sectors-per-track=",20))
+ {
+ def_spt=strtol(&argv[idx][10],NULL,0);
+ if ((def_spt<1) || (def_spt>63))
+ {
+ print_apperr("Invalid sector per track");
+ return 1;
+ }
+ }
+ else if (! strncmp(argv[idx],"--heads=",8))
+ {
+ def_hds=strtol(&argv[idx][8],NULL,0);
+ if ((def_hds<1) || (def_hds>255))
+ {
+ print_apperr("Invalid number of heads");
+ return 1;
+ }
+ }
+ else if (! strncmp(argv[idx],"--start-sector=",15))
+ {
+ def_spt=strtol(&argv[idx][15],NULL,0);
+ if (def_ssc<0)
+ {
+ print_apperr("Invalid start sector");
+ return 1;
+ }
+ }
+ else if (! strncmp(argv[idx],"--total-sectors=",16))
+ {
+ def_tsc=strtol(&argv[idx][16],NULL,0);
+ if (def_tsc<0)
+ {
+ print_apperr("Invalid total sectors");
+ return 1;
+ }
+ }
+ else if ((! strncmp(argv[idx],"--boot-file=",12)) ||
+ (! strncmp(argv[idx],"-b=",3)))
+ {
+ if (SetBootFile((argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][12]))
+ {
+ print_apperr("Invalid boot file name");
+ return 1;
+ }
+ }
+ else if (! strncmp(argv[idx],"--load-seg=",11))
+ {
+ load_seg=strtoul(&argv[idx][11],NULL,16);
+ if (load_seg<0x1000)
+ {
+ print_apperr("Load address too small");
+ return 1;
+ }
+ }
+ else if ((! strcmp(argv[idx],"--grub2")) ||
+ (! strcmp(argv[idx],"-2")))
+ {
+ if (! boot_file)
+ {
+ boot_file="g2ldr";
+ strcpy(boot_file_83,"G2LDR ");
+ }
+ }
+ else if ((! strcmp(argv[idx],"--output")) ||
+ (! strcmp(argv[idx],"-o")))
+ afg|=AFG_OUTPUT;
+ else if ((! strcmp(argv[idx],"--edit")) ||
+ (! strcmp(argv[idx],"-e")))
+ afg|=AFG_EDIT;
+ else
+ {
+ print_apperr("Invalid option, please use --help to see all valid options");
+ return 1;
+ }
+ }
+ if (idx>=argc)
+ {
+ print_apperr("No filename specified");
+ return 1;
+ }
+ if (idx<argc-1)
+ {
+ print_apperr("Extra parameters");
+ return 1;
+ }
+ return install(parse_fname(argv[idx]));
+}
diff --git a/debian/grub-extras/ntldr-img/ntfsbs.S b/debian/grub-extras/ntldr-img/ntfsbs.S
new file mode 100644
index 0000000..039caf3
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/ntfsbs.S
@@ -0,0 +1,1508 @@
+/*
+ * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
+ * Copyright (C) 2007 Bean (bean123@126.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* NTFS boot sector for loading GRLDR , written by bean
+ *
+ * This file can be compiled as standaolne boot sector, or it can be embeded in
+ * GRLDR.MBR at 0xA00 , right after the ext2 boot sector
+ *
+ * To compile the standalone ntfsbs.bin:
+ * gcc -c -o ntfsbs.o ntfsbs.S
+ * gcc -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 -o ntfsbs_exec ntfsbs.o
+ * objcopy -O binary ntfsbs_exec ntfsbs.bin
+ *
+ * To install the standalone ntfsbs.bin:
+ * grubinst --restore=ntfsbs.bin DEVICE_OR_FILE
+ *
+ * Where DEVICE_OR_FILE specify a NTFS partition
+ *
+ * Limitations:
+ * 1. Don't support >1K MFT record size, >4K INDEX record size
+ * 2. Don't support encrypted file
+ * 3. Don't support >4K non-resident attribute list and $BITMAP
+ *
+ */
+
+#ifndef INSIDE_GRLDR
+
+ .text
+
+ .code16
+#endif
+
+#define AT_STANDARD_INFORMATION 0x10
+#define AT_ATTRIBUTE_LIST 0x20
+#define AT_FILENAME 0x30
+#define AT_OBJECT_ID 0x40
+#define AT_SECURITY_DESCRIPTOR 0x50
+#define AT_VOLUME_NAME 0x60
+#define AT_VOLUME_INFORMATION 0x70
+#define AT_DATA 0x80
+#define AT_INDEX_ROOT 0x90
+#define AT_INDEX_ALLOCATION 0xA0
+#define AT_BITMAP 0xB0
+#define AT_SYMLINK 0xC0
+#define AT_EA_INFORMATION 0xD0
+#define AT_EA 0xE0
+
+#define MAX_MFT_SIZE 1 // 1<<(1+9) = 1024
+#define MAX_IDX_SIZE 3 // 1<<(3+9) = 4096
+
+#define LOADSEG_NT 0x2000
+
+#define MMFT_BASE 0x2000
+#define MMFT_EMFT (MMFT_BASE +1024)
+#define MMFT_EBUF (MMFT_BASE + 2048)
+
+#define CMFT_BASE (MMFT_BASE + 6144)
+#define CMFT_EMFT (CMFT_BASE + 1024)
+#define CMFT_EBUF (CMFT_BASE + 2048)
+
+#define INDX_BASE (CMFT_BASE + 6144)
+
+#define SBUF_BASE (INDX_BASE + 4096)
+
+#define NTFS_Large_Structure_Error_Code 1
+#define NTFS_Corrupt_Error_Code 2
+#define NTFS_Run_Overflow_Error_Code 3
+#define NTFS_No_Data_Error_Code 4
+#define NTFS_Decompress_Error_Code 5
+
+#define NT_FG_COMP 1
+#define NT_FG_MMFT 2
+#define NT_FG_ALST 4
+#define NT_FG_GPOS 8
+
+#define nt_boot_drive -2(%bp)
+#define nt_blocksize -4(%bp)
+#define nt_spc -5(%bp)
+#define nt_mft_size -6(%bp)
+#define nt_idx_size -7(%bp)
+#define nt_mft_start -12(%bp)
+#define nt_remain_len -16(%bp)
+//#define nt_file_count -18(%bp)
+
+#define nt_flag (%di)
+#define nt_attr_cur 2(%di)
+#define nt_attr_nxt 4(%di)
+#define nt_attr_end 6(%di)
+#define nt_curr_vcn 8(%di)
+#define nt_curr_lcn 0x10(%di)
+#define nt_attr_ofs 0x14(%di)
+#define nt_target_vcn 0x18(%di)
+#define nt_read_count 0x1C(%di)
+#define nt_vcn_offset 0x20(%di)
+
+#define nt_emft_buf 1024(%di)
+#define nt_edat_buf 2048(%di)
+
+ .arch i586
+
+Entry_nt:
+ jmp 1f
+
+ . = Entry_nt + 0x02
+
+ .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */
+
+ .ascii "NTFS "
+
+ .word 0 /* 0B - Bytes per sector */
+ .byte 0 /* 0D - Sectors per cluster */
+ .word 0 /* 0E - reserved sectors, unused */
+ .byte 0 /* 10 - number of FATs, unused */
+ .word 0 /* 11 - Max dir entries for FAT12/FAT16, unused */
+ .word 0 /* 13 - total sectors for FAT12/FAT16, unused */
+ .byte 0xF8 /* 15 - Media descriptor */
+ .word 0 /* 16 - sectors per FAT for FAT12/FAT16, unused */
+ .word 255 /* 18 - Sectors per track */
+ .word 63 /* 1A - Number of heads */
+nt_part_ofs:
+ .long 0 /* 1C - hidden sectors */
+ .long 0 /* 20 - total sectors for FAT32, unused */
+ .long 0x800080
+ /* 24 - Usually 80 00 80 00, A value of 80 00 00 00 has
+ * been seen on a USB thumb drive which is formatted
+ * with NTFS under Windows XP. Note this is removable
+ * media and is not partitioned, the drive as a whole
+ * is NTFS formatted.
+ */
+ .long 0,0 /* 28 - Number of sectors in the volume */
+ .long 0,0 /* 30 - LCN of VCN 0 of the $MFT */
+ .long 0,0 /* 38 - LCN of VCN 0 of the $MFTMirr */
+ .long 0 /* 40 - Clusters per MFT Record */
+ .long 4 /* 44 - Clusters per Index Record */
+ .long 0,0 /* 48 - Volume serial number */
+ .long 0 /* 50 - Checksum, usually 0 */
+
+1:
+
+ . = Entry_nt + 0x54
+
+ cli
+ cld
+
+ . = Entry_nt + 0x56
+
+ /* the byte at offset 0x57 stores the real partition number for read.
+ * the format program or the caller should set it to a correct value.
+ * For floppies, it should be 0xff, which stands for whole drive.
+ */
+
+ movb $0xff, %dh /* boot partition number */
+
+ xorw %ax, %ax
+ movw %ax, %ds
+ movw $0x7c00, %bp
+ movw %ax, %es
+
+ movw %ax, %ss /* stack and BP-relative moves up, too */
+ leaw -0x20(%bp), %sp
+ sti
+
+ movw %dx, nt_boot_drive
+
+ /* Test if your BIOS support LBA mode */
+ movb $0x41, %ah
+ movw $0x55AA, %bx
+ int $0x13
+ jc 1f /* No EBIOS */
+ cmpw $0xAA55, %bx
+ jne 1f /* No EBIOS */
+ testb $1, %cl
+ jz 1f /* No EBIOS */
+ /* EBIOS supported */
+ movb $0x42, (ebios_nt - 1 - Entry_nt)(%bp)
+1:
+
+ cmpl $0x42555247, (nt_sector_mark - Entry_nt)(%bp)
+ jz 1f // Must be called from GRLDR.MBR
+
+ movw $0x7E00, %bx
+ movl (nt_part_ofs - Entry_nt)(%bp), %eax
+ incl %eax
+ call readDisk_nt // Load the second sector from disk
+ call readDisk_nt // Load the third sector from disk
+ call readDisk_nt
+1:
+
+ xorl %eax, %eax
+ movw 0xb(%bp), %ax // Bytes per sector (blocksize)
+ movw %ax, nt_blocksize
+
+ call convert_to_power_2
+ movb %cl, %bl
+ movb 0xd(%bp), %al // Sectors per cluster
+ call convert_to_power_2
+ movb %cl, %ch
+ addb %bl, %ch
+ subb $9, %ch // 1<<ch = sectors per cluster
+ movb %ch, nt_spc
+ movb 0x44(%bp), %al // Index record size (high bits of eax is 0)
+ call convert_size
+
+ cmpb $MAX_IDX_SIZE, %cl
+ jbe 1f
+
+NTFS_Large_Structure_Error:
+ movb $NTFS_Large_Structure_Error_Code, %al
+ jmp NTFS_Error
+
+1:
+ movb %cl, nt_idx_size
+
+ movb 0x40(%bp), %al // MFT record size
+ call convert_size
+
+ cmpb $MAX_MFT_SIZE, %cl
+ jnz NTFS_Large_Structure_Error
+
+ movb %cl, nt_mft_size
+
+ movl 0x30(%bp), %eax
+ movl 0x34(%bp), %edx
+
+ movb %ch, %cl // ch still contains nt_spc
+
+ shldl %cl, %eax, %edx
+ orl %edx, %edx
+ jnz NTFS_Large_Structure_Error
+
+ shll %cl, %eax
+ addl (nt_part_ofs - Entry_nt)(%bp), %eax
+ movl %eax, nt_mft_start
+
+ movw $1, %dx
+ movb nt_mft_size, %cl
+ shlw %cl, %dx
+ movw %dx, %cx
+
+ movw $MMFT_BASE, %bx
+ pushw %bx
+1:
+ call readDisk_nt
+ loop 1b
+
+ popw %bx
+ cmpw $0x4946, (%bx) // "FI"
+ jnz NTFS_Corrupt_Error
+
+ // dx should still contain the number of sectors in the MFT record
+ movw %dx, %cx
+ call ntfs_fixup
+
+ movw %bx, %di
+ movb $AT_DATA, %al // find $DATA
+
+ call ntfs_locate_attr
+ jc NTFS_Corrupt_Error
+
+ movw $CMFT_BASE, %bx
+ xorl %eax, %eax
+ movb $0x5, %al
+ call ntfs_read_mft
+ movw %bx, %di
+
+ jmp ntfs_search
+
+// Convert the size of MFT and IDX block
+// Input:
+// eax: size
+// ch: spc
+// Output:
+// cl: convert value
+convert_size:
+ orb %al, %al
+ js 1f
+ movb %ch, %cl
+ jmp 2f // Jump to 2 in convert_to_power_2
+1:
+ negb %al
+ subb $9, %al
+ movb %al, %cl
+ ret
+
+// Convert number to a power of 2
+// Input:
+// eax
+// Output:
+// cl: 1<<cl = eax
+// eax: 0
+
+convert_to_power_2:
+ xorb %cl, %cl
+2:
+ incb %cl
+ shrl $1, %eax
+ jnc 2b
+ decb %cl
+ ret
+
+// Fixup the "FILE" and "INDX" record
+// Input:
+// DS:BX - data buffer
+// CX - buffer length in sectors
+//
+
+ntfs_fixup:
+ push %bx
+ push %di
+ movw %bx, %di
+
+ movw 6(%bx), %ax // Size of Update Sequence
+ decw %ax
+ movw %ax, %bx
+
+ mulw nt_blocksize
+ shlw $9, %cx
+ cmpw %ax, %cx
+ jnz NTFS_Corrupt_Error // blocksize * count != size
+
+ movw %bx, %cx // cx = count
+
+ movw %di, %bx
+ addw 4(%bx), %bx // Offset to the update sequence
+ movw (%bx), %ax // Update Sequence Number
+ subw $2, %di
+
+1:
+ addw nt_blocksize, %di
+ addw $2, %bx
+ cmpw (%di), %ax
+ jnz NTFS_Corrupt_Error
+ movw (%bx), %dx
+ movw %dx, (%di)
+ loop 1b
+
+ popw %di
+ popw %bx
+ ret
+
+NTFS_Corrupt_Error:
+ movb $NTFS_Corrupt_Error_Code, %al
+ jmp NTFS_Error
+
+/* Read a sector from disk, using LBA or CHS
+ * input: EAX - 32-bit DOS sector number
+ * ES:BX - destination buffer
+ * (will be filled with 1 sector of data)
+ * output: ES:BX points one byte after the last byte read.
+ * EAX - next sector
+ */
+
+readDisk_nt:
+
+ pushal
+ xorl %edx, %edx /* EDX:EAX = LBA */
+ pushl %edx /* hi 32bit of sector number */
+ pushl %eax /* lo 32bit of sector number */
+ pushw %es /* buffer segment */
+ pushw %bx /* buffer offset */
+ pushw $1 /* 1 sector to read */
+ pushw $16 /* size of this parameter block */
+
+ xorl %ecx, %ecx
+ pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */
+ popw %cx /* ECX = sectors per track */
+ divl %ecx /* residue is in EDX */
+ /* quotient is in EAX */
+ incw %dx /* sector number in DL */
+ popw %cx /* ECX = number of heads */
+ pushw %dx /* push sector number into stack */
+ xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */
+ divl %ecx /* residue is in EDX, head number */
+ /* quotient is in EAX, cylinder number */
+ xchgb %dl, %dh /* head number should be in DH */
+ /* DL = 0 */
+ popw %cx /* pop sector number from stack */
+ xchgb %al, %ch /* lo 8bit cylinder should be in CH */
+ /* AL = 0 */
+ shlb $6, %ah /* hi 2bit cylinder ... */
+ orb %ah, %cl /* ... should be in CL */
+
+ movw $0x201, %ax /* read 1 sector */
+ebios_nt: /* ebios_nt - 1 points to 0x02 that can be changed to 0x42 */
+
+// cmpb $0x0e, 2(%bp) /* force LBA? */
+// jnz 1f /* no, continue */
+// movb $0x42, %ah /* yes, use extended disk read */
+//1:
+ movw %sp, %si /* DS:SI points to disk address packet */
+ movb nt_boot_drive, %dl /* hard disk drive number */
+
+ int $0x13
+
+ popaw /* remove parameter block from stack */
+ popal
+ jc disk_error_nt /* disk read error, jc 1f if caller handles */
+ incl %eax /* next sector */
+ addw 0x0b(%bp), %bx /* bytes per sector */
+ jnc 1f /* 64K bound check */
+ pushw %dx
+ movw %es, %dx
+ addb $0x10, %dh /* add 1000h to ES */
+ /* here, carry is cleared */
+ movw %dx, %es
+ popw %dx
+1:
+ /* carry stored on disk read error */
+ ret
+
+msg_DiskReadError_nt:
+
+ .ascii "0\0"
+
+msg_NTFS_Not_Found_Error:
+ .ascii "No "
+
+nt_boot_image:
+#ifdef BOOTGRUB2
+ .ascii "g2ldr\0"
+#else
+ .ascii "grldr\0"
+#endif
+
+ . = nt_boot_image + 8
+
+nt_boot_image_end:
+
+NTFS_Error:
+ addb %al, (msg_DiskReadError_nt - Entry_nt)(%bp)
+ jmp disk_error_nt
+
+// Kernel load address, located at 0x1E8
+ . = Entry_nt + 0x1e8
+
+nt_loadseg_off:
+ .word 0
+ .word LOADSEG_NT
+
+// Boot image offset and length, located at 0x1EE
+// Lower 11 bit is offset, higher 5 bit is length
+ . = Entry_nt + 0x1ec
+
+nt_boot_image_ofs:
+ .word (nt_boot_image - Entry_nt)+(nt_boot_image_end - nt_boot_image-1)*2048
+
+ . = Entry_nt + 0x1ee
+
+disk_error_nt:
+
+ movw $(msg_DiskReadError_nt - Entry_nt + 0x7c00), %si
+
+boot_error_nt:
+
+/* prints string DS:SI (modifies AX BX SI) */
+
+//print_32:
+1:
+ lodsb (%si), %al /* get token */
+ //xorw %bx, %bx /* video page 0 */
+ movb $0x0e, %ah /* print it */
+ int $0x10 /* via TTY mode */
+ cmpb $0, %al /* end of string? */
+ jne 1b /* until done */
+
+ /* The caller will change this to
+ * ljmp $0x9400, $(try_next_partition - _start1)
+ */
+
+1: jmp 1b
+
+ . = Entry_nt + 0x1fc
+
+ .word 0, 0xAA55
+
+// Here starts sector #2
+
+// Input:
+// DI - current mft
+ntfs_search:
+ //movw $0, nt_file_count
+ call ntfs_init_attr
+ movb $AT_INDEX_ROOT, %al
+
+1:
+ call ntfs_find_attr
+ jc NTFS_Not_Found_Error
+
+ cmpl $0x180400, 8(%si) // resident
+ // namelen = 4
+ // name offset = 0x18
+ jnz 1b
+ //cmpl $0x490024, 0x18(%si) // "$I"
+ //jnz 1b
+ //cmpl $0x300033, 0x1C(%si)
+ //jnz 1b // "30"
+ //testw $0xC001, 12(%si) // not compressed, encrypted or sparse
+ //jnz 1b
+
+ addw 0x14(%si), %si // jump to attribute
+ cmpb $0x30, (%si)
+ jnz 1b // test if it index filenames
+
+ addw $0x10, %si // skip the index root
+ addw (%si), %si
+
+ call ntfs_find_grldr
+ jnc ntfs_final
+
+ call ntfs_init_attr
+ movb $AT_BITMAP, %al
+1:
+ call ntfs_find_attr
+ jc NTFS_Not_Found_Error
+ movw 9(%si), %bx
+ cmpb $4, %bl
+ jnz 1b
+ //shrw $4, %bx
+ //cmpl $0x490024, (%bx, %si) // "$I"
+ //jnz 1b
+ cmpb $0, 8(%si)
+ jnz 1f
+ pushw 0x10(%si)
+ addw 0x14(%si), %si
+ pushw %si
+ jmp 2f
+1:
+ pushw 0x30(%si)
+ xorl %edx, %edx
+ movl 0x28(%si), %ecx
+ cmpw $4096, %cx
+ ja NTFS_Not_Found_Error
+ shrl $9, %ecx
+ movw $SBUF_BASE, %bx
+ pushw %bx
+ call ntfs_read_data
+2:
+
+ movb $AT_INDEX_ALLOCATION, %al
+
+1:
+ call ntfs_locate_attr
+ jc NTFS_Not_Found_Error
+
+ cmpl $0x400401, 8(%si) // non-resident
+ // namelen = 4
+ // name offset = 0x40
+ jnz 1b
+ //cmpl $0x490024, 0x40(%si) // "$I"
+ //jnz 1b
+ //cmpl $0x300033, 0x44(%si)
+ //jnz 1b // "30"
+ //testw $0xC001, 12(%si) // not compressed, encrypted or sparse
+ //jnz 1b
+
+ movb nt_idx_size, %cl
+ xorl %ebx, %ebx
+ movb $1, %bl
+ shll %cl, %ebx // ebx - index size
+ xorl %edx, %edx // edx - index offset
+
+
+ popw %si
+ popw %cx
+
+1:
+ pushw %cx
+ lodsb (%si), %al
+
+ movw $8, %cx
+2:
+ pushw %cx
+ pushw %ax
+ testb $1, %al
+ jz 3f
+ pushw %si
+ pushl %edx
+ pushl %ebx
+
+ movl %ebx, %ecx
+ movw $INDX_BASE, %bx
+ call ntfs_read_attr
+ jc NTFS_Not_Found_Error
+ cmpw $0x4E49, (%bx) // "IN"
+ jnz NTFS_Not_Found_Error
+ call ntfs_fixup
+ movw %bx, %si
+ addw $0x18, %si
+ addw (%si), %si
+
+ call ntfs_find_grldr
+ jnc ntfs_final_0
+
+ popl %ebx
+ popl %edx
+ popw %si
+
+3:
+ addl %ebx, %edx
+
+ popw %ax
+ shrb $1, %al
+ popw %cx
+ loop 2b
+
+ popw %cx
+ loop 1b
+
+ //pushw nt_file_count
+ //call hex_out
+
+NTFS_Not_Found_Error:
+ leaw (msg_NTFS_Not_Found_Error - Entry_nt)(%bp), %si
+ jmp boot_error_nt
+
+ntfs_final_0:
+ //addw $16, %sp
+
+// Input:
+// DI - current mft
+// SI - index entry
+ntfs_final:
+ cmpw $0, 4(%si)
+ jnz NTFS_Large_Structure_Error
+
+ movl (%si), %eax
+ movw %di, %bx
+ call ntfs_read_mft
+
+ movb $AT_DATA, %al
+ call ntfs_locate_attr
+ jc NTFS_No_Data_Error
+
+ cmpb $1, 8(%si) // non-resident / resident
+ jz 1f
+
+ movw 0x10(%si), %cx // Resident
+ lesw (nt_loadseg_off - Entry_nt)(%bp), %di
+ addw 0x14(%si), %si
+ rep movsb (%si), %es:(%di)
+ jmp 2f
+
+1:
+
+ xorl %edx, %edx
+ movl 0x28(%si), %ecx // Use allocate size instead of real size
+ shrl $9, %ecx
+
+ lesw (nt_loadseg_off - Entry_nt)(%bp), %bx
+ call ntfs_read_data
+
+
+2:
+
+ //movb $1, (do_pause - Entry_nt)(%bp)
+ //call pause
+
+ movw nt_boot_drive, %dx
+ ljmp *(nt_loadseg_off - Entry_nt)(%bp)
+
+NTFS_No_Data_Error:
+ movb $NTFS_No_Data_Error_Code, %al
+ jmp NTFS_Error
+
+// Try to find GRLDR in the index
+// Input:
+// DS:SI - points to index entry
+// Output:
+// CF - status
+
+ntfs_find_grldr:
+ movw %si, %bx
+ testb $2, 0xC(%bx)
+ jz 1f
+ stc
+ ret
+1:
+ //incw nt_file_count
+
+ xorb %ch, %ch
+
+ pushw %si
+ leaw (nt_boot_image - Entry_nt)(%bp), %si
+ addw $0x52, %bx // The value at 0xA(%bx) is wrong sometimes (0x4C)
+ movb -2(%bx), %cl
+1:
+ lodsb (%si), %al
+ movb (%bx), %ah
+ cmpb $'A', %ah
+ jb 2f
+ cmpb $'Z', %ah
+ ja 2f
+ addb $('a'-'A'), %ah // Convert to lowercase
+2:
+
+ cmpb %ah, %al
+ jnz 3f // Not match
+
+ incw %bx
+ incw %bx
+ loop 1b
+
+ cmpb $0,(%si)
+ jnz 3f
+
+ popw %si
+ clc
+ ret // Match found
+
+3:
+
+ popw %si
+ addw 8(%si), %si
+
+ jmp ntfs_find_grldr
+
+// Locate an attribute
+// Input:
+// DI - pointer to buffer
+// AL - attribute
+ntfs_locate_attr:
+ call ntfs_init_attr
+ call ntfs_find_attr
+ jc 1f
+2:
+ testb $NT_FG_ALST, nt_flag
+ jnz 2f
+ call ntfs_find_attr
+ jnc 2b
+ call ntfs_init_attr
+ call ntfs_find_attr
+2:
+ clc
+1:
+ ret
+
+// Prepare to find attribute
+// Input:
+// DI - pointer to buffer
+ntfs_init_attr:
+ pushw %ax
+ xorw %ax, %ax
+ movw %ax, nt_flag
+ movw %ax, nt_attr_end
+ movw nt_attr_ofs, %ax
+ addw %di, %ax
+ movw %ax, nt_attr_nxt
+ popw %ax
+ cmpw $MMFT_BASE, %di
+ jnz 1f
+ orb $NT_FG_MMFT, nt_flag
+1:
+ ret
+
+// Find an attribute
+// Input:
+// DI - pointer to buffer
+// AL - attribute
+// Output:
+// SI - current item
+// CF - status
+ntfs_find_attr:
+ movw nt_attr_nxt, %bx
+ testb $NT_FG_ALST, nt_flag
+ jnz 6f
+1:
+ movw %bx, %si
+ cmpb $0xFF, (%si)
+ jz 3f
+
+ cmpb $AT_ATTRIBUTE_LIST, (%si)
+ jnz 2f
+ movw %si, nt_attr_end
+2:
+ addw 4(%bx), %bx
+ cmpb %al, (%si)
+ jnz 1b
+ movw %bx, nt_attr_nxt
+ movw %si, nt_attr_cur
+2:
+ ret
+3:
+ cmpw $1, nt_attr_end
+ jb 2b
+ movw nt_attr_end, %si
+ cmpb $0, 8(%si)
+ jnz 4f
+ movw %si, %bx
+ addw 0x14(%bx), %bx
+ addw 4(%si), %si
+ jmp 5f
+4:
+ movl 0x28(%si), %ecx
+ shrl $9, %ecx
+ cmpw $8, %cx
+ ja NTFS_Corrupt_Error
+ leaw nt_edat_buf, %bx
+ pushw %ax
+ xorl %edx, %edx
+ call ntfs_read_data
+ popw %ax
+ jc 2b
+ movw 0x30(%si), %si
+ addw %bx, %si
+5:
+ movw %si, nt_attr_end
+ orb $NT_FG_ALST, nt_flag
+ testb $NT_FG_MMFT, nt_flag
+ jz 6f
+ cmpb $AT_DATA, %al
+ jnz 6f
+ call ntfs_fix_mmft
+6:
+ movw %bx, %si
+ cmpw nt_attr_end, %bx
+ jb 1f
+7:
+ stc
+ ret
+1:
+ addw 4(%bx), %bx
+ cmpb %al, (%si)
+ jnz 6b
+
+ pushw %ax
+ pushw %es
+ pushw %ds
+ popw %es
+ movw %si, nt_attr_cur
+ movw %bx, nt_attr_nxt
+ movl 0x10(%si), %eax
+ leaw nt_emft_buf, %bx
+ testb $NT_FG_MMFT, nt_flag
+ jnz 2f
+ call ntfs_read_mft
+ jmp 3f
+2:
+ pushw %bx
+ call readDisk_nt
+ movl 0x14(%si), %eax
+ call readDisk_nt
+ popw %bx
+ cmpw $0x4946, (%bx) // "FI"
+ jnz NTFS_Corrupt_Error
+ movw $2, %cx
+ call ntfs_fixup
+3:
+ popw %es
+ popw %ax
+ addw 0x14(%bx), %bx
+4:
+ cmpb $0xFF, (%bx)
+ jz 7b
+ cmpb %al, (%bx)
+ jz 5f
+ addw 4(%bx), %bx
+ jmp 4b
+5:
+ movw %bx, %si
+ ret
+
+// Fix $MFT
+// Input:
+// DI - pointer to buffer
+// BX - attr cur
+ntfs_fix_mmft:
+ pushw %ax
+ orb $NT_FG_GPOS, nt_flag
+
+1:
+ cmpw nt_attr_end, %bx
+ jae NTFS_Corrupt_Error
+ cmpb %al, (%bx)
+ jz 2f
+ addw 4(%bx), %bx
+ jmp 1b
+2:
+
+ movw %bx, nt_attr_cur
+
+ movl nt_mft_start, %eax
+ movl %eax, 0x10(%bx)
+ incl %eax
+ movl %eax, 0x14(%bx)
+1:
+ addw 4(%bx), %bx
+
+ cmpw nt_attr_end, %bx
+ jae 2f
+ cmpb $AT_DATA, (%bx)
+ jnz 2f
+
+ movl 0x10(%bx), %edx
+ movb nt_mft_size, %cl
+ shll %cl, %edx
+
+ call ntfs_read_attr
+
+ orl %eax, %eax
+ jz NTFS_Corrupt_Error
+ movl %eax, 0x10(%bx)
+ movl %edx, 0x14(%bx)
+ jmp 1b
+2:
+ movw nt_attr_cur, %bx
+ andb $(~NT_FG_GPOS), nt_flag
+ popw %ax
+
+ ret
+
+// Read MFT record
+// Input:
+// DS:BX - buffer
+// EAX - mft number
+ntfs_read_mft:
+ pushw %di
+ movw $MMFT_BASE, %di
+ movb nt_mft_size, %cl
+ shll %cl, %eax
+ movl %eax, %edx
+ movl $1, %eax
+ shll %cl, %eax
+ movl %eax, %ecx
+ call ntfs_read_attr
+ jc NTFS_Corrupt_Error
+ cmpw $0x4946, (%bx) // "FI"
+ jnz NTFS_Corrupt_Error
+ call ntfs_fixup
+ popw %di
+ ret
+
+// Read attribute
+// Input:
+// DI - pointer to buffer
+// ES:BX - buffer
+// EDX - start sector
+// ECX - sector count
+// Output:
+// CF - status
+ntfs_read_attr:
+ pushw nt_attr_cur
+ pushl %edx
+ pushl %ecx
+ pushw %bx
+
+ movw nt_attr_cur, %si
+ movb (%si), %al
+
+ testb $NT_FG_ALST, nt_flag
+ jz 2f
+ movw %si, %bx
+ movb nt_spc, %cl
+ shrl %cl, %edx
+
+1:
+ cmpw nt_attr_end, %bx
+ jae 2f
+ cmpb %al, (%bx)
+ jnz 2f
+ cmpl %edx, 8(%bx)
+ ja 2f
+ movw %bx, %si
+ addw 4(%bx), %bx
+ jmp 1b
+2:
+
+ movw %si, nt_attr_nxt
+ call ntfs_find_attr
+
+ popw %bx
+ popl %ecx
+ popl %edx
+ jc 1f
+ call ntfs_read_data
+ clc
+1:
+ popw nt_attr_cur
+ ret
+
+// Read data
+// Input:
+// DI: pointer to buffer
+// SI: current item
+// ES:BX: buffer
+// EDX: start sector
+// ECX: sector count
+ntfs_read_data:
+ pushw %cx
+ pushw %bx
+ testb $1, 8(%si)
+ jz NTFS_Corrupt_Error
+ movb 0xC(%si), %al
+ andb $1, %al
+ orb %al, nt_flag
+
+ movl %ecx, nt_read_count
+ movb nt_spc, %cl
+
+ movl %edx, %eax
+ shrl %cl, %eax
+ movl %eax, nt_target_vcn
+ shll %cl, %eax
+ subl %eax, %edx
+ movl %edx, nt_vcn_offset
+
+ xorw %dx, %dx // edx - next VCN
+ movl %edx, nt_curr_lcn
+
+ movl 0x10(%si), %edx
+
+ addw 0x20(%si), %si
+1:
+ call ntfs_runlist_read_block
+
+ cmpl nt_target_vcn, %edx
+ jbe 1b
+1:
+ movb nt_spc, %cl
+
+ orl %eax, %eax // sparse
+ jz 2f
+
+ movl nt_target_vcn, %eax
+ subl nt_curr_vcn, %eax
+ addl nt_curr_lcn, %eax
+
+ shll %cl, %eax
+ addl nt_vcn_offset, %eax
+
+ testb $NT_FG_GPOS, nt_flag
+ jz 3f
+ pushl %eax
+ incl %eax
+ subl nt_curr_vcn, %edx
+ addl nt_curr_lcn, %edx
+ shll %cl, %edx
+ cmpl %eax, %edx
+ jnz 4f
+ pushw %cx
+ call ntfs_runlist_read_block
+ popw %cx
+ movl nt_curr_lcn, %eax
+ shll %cl, %eax
+4:
+ movl %eax, %edx
+ popl %eax
+ addl (nt_part_ofs - Entry_nt)(%bp), %edx
+3:
+
+ addl (nt_part_ofs - Entry_nt)(%bp), %eax
+
+2:
+ testb $NT_FG_GPOS, nt_flag
+ jnz 1f
+
+ pushl %ebx
+ movl %edx, %ebx
+ subl nt_target_vcn, %ebx
+ shll %cl, %ebx
+ movl %ebx, %ecx
+ popl %ebx
+
+ subl nt_vcn_offset, %ecx
+ movl $0, nt_vcn_offset
+ cmpl nt_read_count, %ecx
+ jbe 2f
+ movl nt_read_count, %ecx
+2:
+
+ pushl %ecx
+
+ orl %eax, %eax
+ jnz 3f
+ call ntfs_sparse_block
+ jmp 4f
+
+3:
+ call readDisk_nt
+ loop 3b
+
+4:
+ popl %ecx
+ subl %ecx, nt_read_count
+ jbe 1f
+
+ movl %edx, nt_target_vcn
+ call ntfs_runlist_read_block
+ jmp 1b
+
+1:
+ popw %bx
+ popw %cx
+ ret
+
+// Read run list data
+// Input:
+// CL = number of bytes
+// Output:
+// EAX = read bytes
+// SI points to the next unhandled byte
+
+ntfs_runlist_read_data:
+ pushw %cx
+ orb %cl, %cl
+ jnz 1f
+ popw %cx
+ xorl %eax, %eax
+ ret
+1:
+ lodsb (%si), %al
+ rorl $8, %eax
+ decb %cl
+ jnz 1b
+
+ popw %cx
+ negb %cl
+ add $4, %cl
+ shlb $3, %cl
+ ret
+
+NTFS_Run_Overflow_Error:
+ movb $NTFS_Run_Overflow_Error_Code, %al
+ jmp NTFS_Error
+
+// Read run list block
+// Output:
+// EDX = Next VCN
+// SI points to the next unhandled byte
+
+ntfs_runlist_read_block:
+ lodsb (%si), %al
+ movb %al, %cl
+ movb %cl, %ch
+ andb $0xF, %cl // cl - Size of length field
+ jz 1f
+ shrb $0x4, %ch // ch - Size of offset field
+
+ call ntfs_runlist_read_data
+ shrl %cl, %eax
+
+ movl %edx, nt_curr_vcn
+ addl %eax, %edx
+
+ movb %ch, %cl
+ call ntfs_runlist_read_data
+ sarl %cl, %eax
+
+ addl %eax, nt_curr_lcn
+
+ ret
+
+1:
+ testb $NT_FG_ALST, nt_flag
+ jz NTFS_Run_Overflow_Error
+
+ pushl %edx
+ pushw %bx
+ movw nt_attr_cur, %si
+ movb (%si), %al
+ call ntfs_find_attr
+ jc NTFS_Run_Overflow_Error
+ cmpb $0, 8(%si)
+ jz NTFS_Run_Overflow_Error
+ movl $0, nt_curr_lcn
+ popw %bx
+ popl %edx
+ addw 0x20(%si), %si
+ jmp ntfs_runlist_read_block
+
+// Convert seg:ofs to linear address
+// Input:
+// On stack: seg:ofs
+// Output:
+// eax:
+seg_to_lin:
+ pushw %bp
+ movw %sp, %bp
+ xorl %eax, %eax
+ xchgw 6(%bp), %ax
+ shll $4, %eax
+ addl 4(%bp), %eax
+ popw %bp
+ ret $4
+
+// Convert linear address to seg:ofs
+// Input:
+// on stack: linear address
+// Output:
+// On stack: seg:ofs
+lin_to_seg:
+ pushw %bp
+ movw %sp, %bp
+ shll $12, 4(%bp)
+ shrw $12, 4(%bp)
+ popw %bp
+ ret
+
+fix_segs:
+ pushw %ds
+ pushw %si
+ call seg_to_lin
+ pushl %eax
+ call lin_to_seg
+ popw %si
+ popw %ds
+
+fix_es_di:
+ pushw %es
+ pushw %di
+ call seg_to_lin
+ pushl %eax
+ call lin_to_seg
+ popw %di
+ popw %es
+ ret
+
+// Handle sparse block
+// DI: points to buffer
+// ES:BX: points to buffer
+// ECX: number of sectors
+// EDX: next VCN
+
+ntfs_sparse_block:
+ pushw %di
+ pushl %edx
+
+ shll $9, %ecx // ecx - totel number of bytes
+
+ testb $1, nt_flag // Not compressed
+ jz 2f
+
+ xorl %edx, %edx
+ movb nt_target_vcn, %dl
+ andb $0xF, %dl
+ jz 2f
+
+ movw %bx, %di
+
+ pushw %cx
+
+ movb nt_spc, %cl
+ addb $9, %cl
+ shll %cl, %edx // edx: offset from the start of cluster
+
+ push %es
+ push %di
+ call seg_to_lin
+ subl %edx, %eax // eax: linear address
+
+ movl $16, nt_remain_len
+ shll %cl, nt_remain_len
+
+ popw %cx
+
+ addl %edx, %ecx
+ subl nt_remain_len, %ecx
+
+ pushl %ecx
+ call ntfs_decomp_block
+ popl %ecx
+
+ addl nt_remain_len, %ecx
+
+ jecxz 1f
+
+ movw %di, %bx
+
+2:
+ movw %bx, %di
+ movl %ecx, %edx
+ xorl %eax, %eax
+ movl %eax, %ecx
+ call fix_es_di
+
+3:
+ movw $0x8000, %cx
+ cmpl %edx, %ecx
+ jbe 4f
+ movw %dx, %cx
+4:
+ pushw %cx
+ shrw $2, %cx
+
+ rep stosl %eax, %es:(%di)
+ call fix_es_di
+ popw %cx
+ subl %ecx, %edx
+ jnz 3b
+
+1:
+ movw %di, %bx
+
+ popl %edx
+ popw %di
+
+ ret
+
+// Decompress block
+// Input:
+// eax: linear address at the beginning of the compressed block
+// Output:
+// ES:DI: points to the end of the block
+ntfs_decomp_block:
+ pushw %ds
+ pushw %si
+
+ pushl %eax
+ call lin_to_seg
+ popw %si
+ popw %ds
+ movl nt_remain_len, %edx
+ addl %edx, %eax
+ pushl %eax
+ call lin_to_seg
+ popw %di
+ popw %es
+
+ pushw %es
+ pushw %di
+ pushw %ds
+ pushw %si
+
+ xorl %ecx, %ecx
+
+1:
+ movw $0x8000, %cx
+ cmpl %edx, %ecx
+ jbe 2f
+ movw %dx, %cx
+2:
+ pushw %cx
+ shrw $2, %cx
+ rep movsl (%si), %es:(%di)
+ call fix_segs
+ popw %cx
+ subl %ecx, %edx
+ jnz 1b
+
+ popw %di
+ popw %es
+ popw %si
+ popw %ds
+
+1:
+ xorl %edx, %edx // edx - copied bytes
+
+ lodsw (%si), %ax
+ testb $0x80, %ah
+ jnz 2f
+ movw $0x800, %cx
+ rep movsw (%si), %es:(%di)
+ movw $0x1000, %dx
+ jmp 7f // The block is not compressed
+
+2:
+ movw %ax, %cx
+ andw $0xFFF, %cx
+ incw %cx // ecx = block length
+ addw %si, %cx // cx: end marker
+ xorb %bh, %bh
+
+3:
+ cmpw $0x1000, %dx
+ ja NTFS_Decompress_Error
+
+ orb %bh, %bh
+ jnz 4f
+ lodsb (%si), %al
+ movb %al, %bl // bl: tag, bh: count
+ movb $8, %bh
+4:
+
+ testb $1, %bl
+ jz 5f
+
+ movw %dx, %ax
+ decw %ax
+
+ pushw %cx
+ pushw %bx
+
+ movb $12, %cl
+6:
+ cmpw $0x10, %ax
+ jb 6f
+ shrw $1, %ax
+ decb %cl
+ jmp 6b
+6:
+
+ lodsw (%si), %ax
+ movw %ax, %bx
+ shrw %cl, %bx // bx: delta
+
+ pushw %dx
+ movw $1, %dx
+ shlw %cl, %dx
+ decw %dx
+ andw %dx, %ax
+ popw %dx
+
+ addw $3, %ax
+ movw %ax, %cx // cx: length
+ negw %bx
+ decw %bx
+
+6:
+ movb %es:(%bx, %di), %al
+ stosb %al, %es:(%di)
+ incw %dx
+ loop 6b
+
+ popw %bx
+ popw %cx
+ jmp 4f
+
+5:
+ movsb (%si), %es:(%di)
+ incw %dx
+4:
+ shrb $1, %bl
+ decb %bh
+
+ cmpw %cx, %si
+ jb 3b
+
+7:
+ call fix_segs
+
+ subl %edx, nt_remain_len // End of block
+ jz 1f
+
+ cmpw $0x1000, %dx
+ je 1b
+
+1:
+
+ popw %si
+ popw %ds
+ ret
+
+NTFS_Decompress_Error:
+ pushw %ss
+ popw %ds
+ movb $NTFS_Decompress_Error_Code, %al
+ jmp NTFS_Error
+
+/*
+do_pause:
+ .byte 0
+
+pause:
+ cmpb $0, (do_pause - Entry_nt)(%bp)
+ jnz 1f
+ ret
+1:
+ xorw %bp, %bp
+1:
+ jmp 1b
+*/
+
+/*
+hex_out:
+ pushw %bp
+ movw %sp, %bp
+ pushaw
+ movb $0xE, %ah
+ movw $7, %bx
+ movw $4, %cx
+ movw 4(%bp), %dx
+1:
+ rol $4, %dx
+ movb %dl, %al
+ andb $0xF, %al
+ cmpb $10, %al
+ jb 2f
+ subb $('0'-'A'+10), %al
+2:
+ addb $'0', %al
+ int $0x10
+ loop 1b
+ movb $' ', %al
+ int $0x10
+ popaw
+ popw %bp
+ ret $2
+*/
+
+ . = Entry_nt + 0x7fc
+
+nt_sector_mark:
+ .long 0x42555247 // "GRUB"
diff --git a/debian/grub-extras/ntldr-img/utils.c b/debian/grub-extras/ntldr-img/utils.c
new file mode 100644
index 0000000..d1f3bfa
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/utils.c
@@ -0,0 +1,392 @@
+/*
+ * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
+ * Copyright (C) 2007 Bean (bean123@126.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef LINUX
+
+#define _FILE_OFFSET_BITS 64 // This is required to enable 64-bit off_t
+#include <unistd.h>
+
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "utils.h"
+
+static unsigned char ebuf[512];
+
+#if defined(WIN32)
+
+#ifdef __GNUC__ // Mingw or Cygwin
+
+#define u_off_t off64_t
+#define u_lseek lseek64
+
+#else
+
+#define u_off_t __int64
+#define u_lseek _lseeki64
+
+#endif
+
+#else
+
+#define u_off_t off_t // In FreeBSD, off_t is 64-bit !
+#define u_lseek lseek
+
+#endif
+
+int go_sect(int hd,unsigned long sec)
+{
+ // Test if 64-bit seek is supported
+ if (sizeof(u_off_t)>=8)
+ {
+ u_off_t bs,rs;
+
+ bs=sec;
+ bs<<=9;
+ rs=u_lseek(hd,bs,SEEK_SET);
+ return (bs!=rs);
+ }
+ else
+ {
+ unsigned long bs[2];
+
+ bs[0]=sec<<9;
+ bs[1]=sec>>23;
+ if (bs[1])
+ return 1;
+ return (lseek(hd,bs[0],SEEK_SET)!=(off_t)bs[0]);
+ }
+}
+
+// Partition enumerator
+// xe->cur is the current partition number, before the first call to xd_enum,
+// it should be set to 0xFF
+// xe->nxt is the target partition number, if it equals 0xFF, it means enumerate
+// all partitions, otherwise, it means jump to the specific partition.
+int xd_enum(int hd,xde_t* xe)
+{
+ int nn=512,kk=1,cc;
+
+ for (cc=xe->cur;;)
+ {
+ if (cc==0xFF)
+ {
+ unsigned long pt[4][2];
+ int i,j,np;
+
+ if (go_sect(hd,0))
+ return 1;
+ if (read(hd,ebuf,nn)!=nn)
+ return 1;
+ if (get16(ebuf,0x1FE)!=0xAA55)
+ return 1;
+ np=0;
+ for (i=0x1BE;i<0x1FE;i+=16)
+ if (ebuf[i+4])
+ {
+ if ((pt[np][1]=get32(ebuf,i+12))==0)
+ return 1;
+ pt[np++][0]=get32(ebuf,i+8);
+ }
+ if (np==0)
+ return 1;
+ // Sort partition table base on start address
+ for (i=0;i<np-1;i++)
+ {
+ int k=i;
+ for (j=i+1;j<np;j++)
+ if (pt[k][0]>pt[j][0]) k=j;
+ if (k!=i)
+ {
+ unsigned long tt;
+
+ tt=pt[i][0];
+ pt[i][0]=pt[k][0];
+ pt[k][0]=tt;
+ tt=pt[i][1];
+ pt[i][1]=pt[k][1];
+ pt[k][1]=tt;
+ }
+ }
+ // Should have space for MBR
+ if (pt[0][0]==0)
+ return 1;
+ // Check for partition overlap
+ for (i=0;i<np-1;i++)
+ if (pt[i][0]+pt[i][1]>pt[i+1][0])
+ return 1;
+ cc=0;
+ }
+ else if (kk)
+ cc++;
+ if ((unsigned char)cc>xe->nxt)
+ return 1;
+ if (cc<4)
+ {
+ if (xe->nxt<4)
+ {
+ // Empty partition
+ if (! ebuf[xe->nxt*16+4+0x1BE])
+ return 1;
+ xe->cur=xe->nxt;
+ xe->dfs=ebuf[xe->nxt*16+4+0x1BE];
+ xe->bse=get32(ebuf,xe->nxt*16+8+0x1BE);
+ xe->len=get32(ebuf,xe->nxt*16+12+0x1BE);
+ return 0;
+ }
+ else if (xe->nxt!=0xFF)
+ cc=4;
+ else while (cc<4)
+ {
+ if (ebuf[cc*16+4+0x1BE])
+ {
+ xe->cur=cc;
+ xe->dfs=ebuf[cc*16+4+0x1BE];
+ xe->bse=get32(ebuf,cc*16+8+0x1BE);
+ xe->len=get32(ebuf,cc*16+12+0x1BE);
+ return 0;
+ }
+ cc++;
+ }
+ }
+ if ((cc==4) && (kk))
+ {
+ int i;
+
+ // Scan for extended partition
+ for (i=0;i<4;i++)
+ if ((ebuf[i*16+4+0x1BE]==5) || (ebuf[i*16+4+0x1BE]==0xF)) break;
+ if (i==4)
+ return 1;
+ xe->ebs=xe->bse=get32(ebuf,i*16+8+0x1BE);
+ }
+ else
+ {
+ // Is end of extended partition chain ?
+ if (((ebuf[4+0x1CE]!=0x5) && (ebuf[4+0x1CE]!=0xF)) ||
+ (get32(ebuf,8+0x1CE)==0))
+ return 1;
+ xe->bse=xe->ebs+get32(ebuf,8+0x1CE);
+ }
+ {
+ while (1)
+ {
+ if (go_sect(hd,xe->bse))
+ return 1;
+
+ if (read(hd,ebuf,nn)!=nn)
+ return 1;
+
+ if (get16(ebuf,0x1FE)!=0xAA55)
+ return 1;
+
+ if ((ebuf[4+0x1BE]==5) || (ebuf[4+0x1BE]==0xF))
+ {
+ if (get32(ebuf,8+0x1BE)==0)
+ return 1;
+ else
+ {
+ xe->bse=xe->ebs+get32(ebuf,8+0x1BE);
+ continue;
+ }
+ }
+ break;
+ }
+ kk=(ebuf[4+0x1BE]!=0);
+ if ((kk) && ((xe->nxt==0xFF) || (cc==xe->nxt)))
+ {
+ xe->cur=cc;
+ xe->dfs=ebuf[4+0x1BE];
+ xe->bse+=get32(ebuf,8+0x1BE);
+ xe->len=get32(ebuf,12+0x1BE);
+ return 0;
+ }
+ }
+ }
+}
+
+#define EXT2_SUPER_MAGIC 0xEF53
+
+int mbr_nhd, mbr_spt;
+
+static void split_chs(unsigned char* chs,unsigned long* c,unsigned long* h,unsigned long* s)
+{
+ *h=chs[0];
+ *s=(chs[1] & 0x3F)-1;
+ *c=((unsigned long)(chs[1]>>6))*256+chs[2];
+}
+
+static int chk_chs(unsigned long nhd,unsigned long spt,unsigned long lba,unsigned char* chs)
+{
+ unsigned long c,h,s;
+
+ split_chs(chs,&c,&h,&s);
+ if (c==0x3FF)
+ return ((nhd==h+1) && (spt==s+1));
+ else
+ return (c*nhd*spt+h*spt+s==lba);
+}
+
+static int chk_mbr(unsigned char* buf)
+{
+ unsigned long nhd,spt,a1,a2,c2,h2,s2;
+ int i;
+
+ i=0x1BE;
+ while ((i<0x1FE) && (buf[i+4]==0))
+ i+=16;
+ if (i>=0x1FE)
+ return 0;
+ a1=get32(&buf[i],8);
+ a2=a1+get32(&buf[i],12)-1;
+ if (a1>=a2)
+ return 0;
+ split_chs(buf+i+5,&c2,&h2,&s2);
+ if (c2==0x3FF)
+ {
+ nhd=h2+1;
+ spt=s2+1;
+ if (! chk_chs(nhd,spt,a1,buf+i+1))
+ return 0;
+ }
+ else
+ {
+ unsigned long c1,h1,s1;
+ long n1,n2;
+
+ split_chs(buf+i+1,&c1,&h1,&s1);
+ if ((c1==0x3FF) || (c1>c2))
+ return 0;
+ n1=(long)(c1*a2)-(long)(c2*a1)-(long)(c1*s2)+(long)(c2*s1);
+ n2=(long)(c1*h2)-(long)(c2*h1);
+ if (n2<0)
+ {
+ n2=-n2;
+ n1=-n1;
+ }
+ if ((n2==0) || (n1<=0) || (n1 % n2))
+ return 0;
+ spt=(unsigned long)(n1/n2);
+ if (c2)
+ {
+ n1=(long)a2-(long)s2-(long)(h2*spt);
+ n2=(long)(c2*spt);
+ if ((n2==0) || (n1<=0) || (n1 % n2))
+ return 0;
+ nhd=(unsigned long)(n1/n2);
+ }
+ else
+ nhd=h2+1;
+ }
+ if ((nhd==0) || (nhd>255) || (spt==0) || (spt>63))
+ return 0;
+ i+=16;
+ while (i<0x1FE)
+ {
+ if (buf[i+4])
+ {
+ if ((! chk_chs(nhd,spt,get32(&buf[i],8),buf+i+1)) ||
+ (! chk_chs(nhd,spt,get32(&buf[i],8)+get32(&buf[i],12)-1,buf+i+5)))
+ return 0;
+ }
+ i+=16;
+ }
+ mbr_nhd=(int)nhd;
+ mbr_spt=(int)spt;
+ return 1;
+}
+
+int get_fstype(unsigned char* buf)
+{
+ if (chk_mbr(buf))
+ return FST_MBR;
+
+ // The first sector of EXT2 might not contain the 0xAA55 signature
+ if (get16(&buf[1024],56)==EXT2_SUPER_MAGIC)
+ return FST_EXT2;
+ if (get16(&buf[0],0x1FE)!=0xAA55)
+ return FST_OTHER;
+ if (! memcmp(&buf[0x36],"FAT",3))
+ return ((buf[0x26]==0x28) || (buf[0x26]==0x29))?FST_FAT16:FST_OTHER;
+ if (! memcmp(&buf[0x52],"FAT32",5))
+ return ((buf[0x42]==0x28) || (buf[0x42]==0x29))?FST_FAT32:FST_OTHER;
+ if (! memcmp(&buf[0x3],"NTFS",4))
+ return ((buf[0]==0xEB) && (buf[1]==0x52))?FST_NTFS:FST_OTHER;
+ return FST_OTHER;
+}
+
+const char* fst2str(int fs)
+{
+ switch (fs) {
+ case FST_OTHER:
+ return "Other";
+ case FST_MBR:
+ return "MBR";
+ case FST_FAT16:
+ return "FAT12/FAT16";
+ case FST_FAT32:
+ return "FAT32";
+ case FST_NTFS:
+ return "NTFS";
+ case FST_EXT2:
+ return "EXT2/EXT3";
+ default:
+ return "Unknown";
+ }
+}
+
+typedef struct {
+ int id;
+ const char* str;
+} fstab_t;
+
+static fstab_t fstab[]= {
+ {0x1,"FAT12"},
+ {0x4,"FAT16"},
+ {0x5,"Extended"},
+ {0x6,"FAT16B"},
+ {0x7,"NTFS"},
+ {0xB,"FAT32"},
+ {0xC,"FAT32X"},
+ {0xE,"FAT16X"},
+ {0xF,"ExtendedX"},
+ {0x11,"(H)FAT12"},
+ {0x14,"(H)FAT16"},
+ {0x16,"(H)FAT16B"},
+ {0x17,"(H)NTFS"},
+ {0x1B,"(H)FAT32"},
+ {0x1C,"(H)FAT32X"},
+ {0x1E,"(H)FAT16X"},
+ {0x82,"Swap"},
+ {0x83,"Ext2"},
+ {0xA5,"FBSD"},
+ {0,"Other"}};
+
+const char* dfs2str(int fs)
+{
+ int i;
+
+ for (i=0;fstab[i].id;i++)
+ if (fs==fstab[i].id)
+ return fstab[i].str;
+ return fstab[i].str;
+}
diff --git a/debian/grub-extras/ntldr-img/utils.h b/debian/grub-extras/ntldr-img/utils.h
new file mode 100644
index 0000000..e48aac8
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/utils.h
@@ -0,0 +1,88 @@
+/*
+ * GRUB Utilities -- Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
+ * Copyright (C) 2007 Bean (bean123@126.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __UTILS_H
+#define __UTILS_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define MAX_DISKS 10
+#define MAX_PARTS 30
+
+#define FST_OTHER 0
+#define FST_MBR 1
+#define FST_FAT16 2
+#define FST_FAT32 3
+#define FST_NTFS 4
+#define FST_EXT2 5
+
+typedef struct {
+ unsigned char cur; // Current partition number
+ unsigned char nxt; // Next partition number
+ unsigned char dfs; // File system flag
+ unsigned char pad; // Padding
+ unsigned long bse; // Partition start address
+ unsigned long len; // Partition length
+ unsigned long ebs; // Base address for the extended partition
+} __attribute__ ((packed)) xde_t;
+
+static inline unsigned short
+get16 (const void *buf_, unsigned offset)
+{
+ unsigned char *buf = (unsigned char *) buf_ + offset;
+ return buf[0] | (buf[1] << 8);
+}
+static inline unsigned int
+get32 (const void *buf_, unsigned offset)
+{
+ unsigned char *buf = (unsigned char *) buf_ + offset;
+ return buf[0] | (buf[1] << 8) | (buf[1] << 16) | (buf[1] << 24);
+}
+
+static inline void
+set16 (void *buf_, unsigned offset, unsigned short val)
+{
+ unsigned char *buf = (unsigned char *) buf_ + offset;
+ buf[0] = val;
+ buf[1] = val >> 8;
+}
+
+static inline void
+set32 (void *buf_, unsigned offset, unsigned int val)
+{
+ unsigned char *buf = (unsigned char *) buf_ + offset;
+ buf[0] = val;
+ buf[1] = val >> 8;
+ buf[2] = val >> 16;
+ buf[3] = val >> 24;
+}
+
+extern int mbr_nhd, mbr_spt;
+int go_sect(int,unsigned long);
+int xd_enum(int,xde_t*);
+int get_fstype(unsigned char*);
+const char* fst2str(int);
+const char* dfs2str(int);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+#endif /* __UTILS_H */
diff --git a/debian/grub-extras/ntldr-img/version.h b/debian/grub-extras/ntldr-img/version.h
new file mode 100644
index 0000000..ce84ad6
--- /dev/null
+++ b/debian/grub-extras/ntldr-img/version.h
@@ -0,0 +1,3 @@
+#define VERSION "1.1"
+#define VER_MAJOR 1
+#define VER_MINOR 1
diff --git a/debian/grub-firmware-qemu.dirs b/debian/grub-firmware-qemu.dirs
new file mode 100644
index 0000000..78d9a98
--- /dev/null
+++ b/debian/grub-firmware-qemu.dirs
@@ -0,0 +1 @@
+usr/share/qemu
diff --git a/debian/grub-firmware-qemu.install b/debian/grub-firmware-qemu.install
new file mode 100644
index 0000000..9587837
--- /dev/null
+++ b/debian/grub-firmware-qemu.install
@@ -0,0 +1 @@
+obj/grub-firmware-qemu/grub.bin usr/share/qemu
diff --git a/debian/grub-firmware-qemu_grub.cfg b/debian/grub-firmware-qemu_grub.cfg
new file mode 100644
index 0000000..d23f22a
--- /dev/null
+++ b/debian/grub-firmware-qemu_grub.cfg
@@ -0,0 +1,37 @@
+set default=0
+set fallback=1
+set timeout=10
+
+menuentry "Search & load /boot/multiboot.img" {
+ search -s -f /boot/multiboot.img
+ if multiboot /boot/multiboot.img ; then
+ boot
+ fi
+ unset timeout
+}
+
+# For separate /boot partition.
+menuentry "Search & load /multiboot.img" {
+ search -s -f /multiboot.img
+ if multiboot /multiboot.img ; then
+ boot
+ fi
+ unset timeout
+}
+
+menuentry "Search & source /boot/grub/grub.cfg" {
+ search -s -f /boot/grub/grub.cfg
+ source /boot/grub/grub.cfg
+ unset timeout
+}
+
+# For separate /boot partition.
+menuentry "Search & source /grub/grub.cfg" {
+ search -s -f /grub/grub.cfg
+ source /grub/grub.cfg
+ unset timeout
+}
+
+menuentry "Reboot" {
+ reboot
+}
diff --git a/debian/grub-ieee1275-bin.install.amd64.in b/debian/grub-ieee1275-bin.install.amd64.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-ieee1275-bin.install.amd64.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-ieee1275-bin.install.kopensolaris-i386.in b/debian/grub-ieee1275-bin.install.kopensolaris-i386.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-ieee1275-bin.install.kopensolaris-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-ieee1275-bin.install.linux-i386.in b/debian/grub-ieee1275-bin.install.linux-i386.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-ieee1275-bin.install.linux-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-ieee1275-bin.install.powerpc.in b/debian/grub-ieee1275-bin.install.powerpc.in
new file mode 100644
index 0000000..76af24b
--- /dev/null
+++ b/debian/grub-ieee1275-bin.install.powerpc.in
@@ -0,0 +1,3 @@
+usr/lib/grub/@CPU_PLATFORM@/bootinfo.txt
+usr/lib/grub/@CPU_PLATFORM@/grub.chrp
+../../debian/prep-bootdev usr/lib/grub/@CPU_PLATFORM@
diff --git a/debian/grub-ieee1275-bin.install.ppc64.in b/debian/grub-ieee1275-bin.install.ppc64.in
new file mode 100644
index 0000000..76af24b
--- /dev/null
+++ b/debian/grub-ieee1275-bin.install.ppc64.in
@@ -0,0 +1,3 @@
+usr/lib/grub/@CPU_PLATFORM@/bootinfo.txt
+usr/lib/grub/@CPU_PLATFORM@/grub.chrp
+../../debian/prep-bootdev usr/lib/grub/@CPU_PLATFORM@
diff --git a/debian/grub-ieee1275-bin.install.ppc64el.in b/debian/grub-ieee1275-bin.install.ppc64el.in
new file mode 100644
index 0000000..76af24b
--- /dev/null
+++ b/debian/grub-ieee1275-bin.install.ppc64el.in
@@ -0,0 +1,3 @@
+usr/lib/grub/@CPU_PLATFORM@/bootinfo.txt
+usr/lib/grub/@CPU_PLATFORM@/grub.chrp
+../../debian/prep-bootdev usr/lib/grub/@CPU_PLATFORM@
diff --git a/debian/grub-ieee1275.install.sparc.in b/debian/grub-ieee1275.install.sparc.in
new file mode 100644
index 0000000..dbd0bf9
--- /dev/null
+++ b/debian/grub-ieee1275.install.sparc.in
@@ -0,0 +1,2 @@
+usr/sbin/grub-sparc64-setup
+usr/share/man/man8/grub-sparc64-setup.8
diff --git a/debian/grub-ieee1275.install.sparc64.in b/debian/grub-ieee1275.install.sparc64.in
new file mode 100644
index 0000000..dbd0bf9
--- /dev/null
+++ b/debian/grub-ieee1275.install.sparc64.in
@@ -0,0 +1,2 @@
+usr/sbin/grub-sparc64-setup
+usr/share/man/man8/grub-sparc64-setup.8
diff --git a/debian/grub-ieee1275.links.sparc.in b/debian/grub-ieee1275.links.sparc.in
new file mode 100644
index 0000000..eaaa690
--- /dev/null
+++ b/debian/grub-ieee1275.links.sparc.in
@@ -0,0 +1 @@
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-sparc64-setup
diff --git a/debian/grub-ieee1275.links.sparc64.in b/debian/grub-ieee1275.links.sparc64.in
new file mode 100644
index 0000000..eaaa690
--- /dev/null
+++ b/debian/grub-ieee1275.links.sparc64.in
@@ -0,0 +1 @@
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-sparc64-setup
diff --git a/debian/grub-mount-udeb.install b/debian/grub-mount-udeb.install
new file mode 100644
index 0000000..dff3d11
--- /dev/null
+++ b/debian/grub-mount-udeb.install
@@ -0,0 +1,2 @@
+usr/bin/grub-mount
+usr/sbin/grub-probe
diff --git a/debian/grub-pc-bin.install.amd64.in b/debian/grub-pc-bin.install.amd64.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-pc-bin.install.amd64.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-pc-bin.install.in b/debian/grub-pc-bin.install.in
new file mode 100644
index 0000000..68cfba6
--- /dev/null
+++ b/debian/grub-pc-bin.install.in
@@ -0,0 +1,4 @@
+usr/bin/grub-ntldr-img usr/lib/grub/@CPU_PLATFORM@
+usr/lib/grub/@CPU_PLATFORM@/g2hdr.bin
+usr/lib/grub/@CPU_PLATFORM@/g2ldr.mbr
+usr/sbin/grub-bios-setup usr/lib/grub/@CPU_PLATFORM@
diff --git a/debian/grub-pc-bin.install.kopensolaris-i386.in b/debian/grub-pc-bin.install.kopensolaris-i386.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-pc-bin.install.kopensolaris-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-pc-bin.install.linux-i386.in b/debian/grub-pc-bin.install.linux-i386.in
new file mode 100644
index 0000000..b1648eb
--- /dev/null
+++ b/debian/grub-pc-bin.install.linux-i386.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/efiemu*.o
diff --git a/debian/grub-pc-dbg.install.in b/debian/grub-pc-dbg.install.in
new file mode 100644
index 0000000..2770f6d
--- /dev/null
+++ b/debian/grub-pc-dbg.install.in
@@ -0,0 +1 @@
+usr/lib/grub/@CPU_PLATFORM@/*.image
diff --git a/debian/grub-pc.dirs.in b/debian/grub-pc.dirs.in
new file mode 100644
index 0000000..4080738
--- /dev/null
+++ b/debian/grub-pc.dirs.in
@@ -0,0 +1 @@
+usr/lib/grub-legacy
diff --git a/debian/grub-pc.install.in b/debian/grub-pc.install.in
new file mode 100644
index 0000000..33ca9f3
--- /dev/null
+++ b/debian/grub-pc.install.in
@@ -0,0 +1,4 @@
+../../debian/legacy/update-grub usr/lib/grub-legacy
+../../debian/legacy/upgrade-from-grub-legacy usr/sbin
+
+usr/share/man/man8/grub-bios-setup.8
diff --git a/debian/grub-pc.links.in b/debian/grub-pc.links.in
new file mode 100644
index 0000000..4db3f61
--- /dev/null
+++ b/debian/grub-pc.links.in
@@ -0,0 +1,4 @@
+usr/lib/grub/@CPU_PLATFORM@/grub-ntldr-img usr/bin/grub-ntldr-img
+usr/lib/grub/@CPU_PLATFORM@/grub-bios-setup usr/sbin/grub-bios-setup
+
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-bios-setup
diff --git a/debian/grub-pc.prerm b/debian/grub-pc.prerm
new file mode 100644
index 0000000..13bbc60
--- /dev/null
+++ b/debian/grub-pc.prerm
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -e
+
+case "$1" in
+ remove|deconfigure)
+ . /usr/share/debconf/confmodule
+ db_get grub-pc/chainload_from_menu.lst
+ if $RET && test -e /boot/grub/menu.lst ; then
+ echo "Saving menu.lst backup in /boot/grub/menu.lst_backup_by_grub2_prerm" >&2
+ cp /boot/grub/menu.lst{,_backup_by_grub2_prerm}
+ echo "Running update-grub Legacy to remove our core.img in it" >&2
+ /usr/lib/grub-legacy/update-grub 2>&1 | sed -e "s/^/ /g" >&2
+ fi
+ ;;
+ failed-upgrade|upgrade)
+ ;;
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/grub-pc.templates.in b/debian/grub-pc.templates.in
new file mode 100644
index 0000000..79870ef
--- /dev/null
+++ b/debian/grub-pc.templates.in
@@ -0,0 +1,157 @@
+
+# This file is concatenated. Do not delete the newline above.
+
+Template: grub-pc/chainload_from_menu.lst
+Type: boolean
+Default: true
+#flag:translate!:6
+_Description: Chainload from menu.lst?
+ GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub.
+ .
+ In order to replace the Legacy version of GRUB in your system, it is
+ recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot
+ image from your existing GRUB Legacy setup. This step can be automatically
+ performed now.
+ .
+ It's recommended that you accept chainloading GRUB 2 from menu.lst, and
+ verify that the new GRUB 2 setup works before it is written to the MBR
+ (Master Boot Record).
+ .
+ Whatever your decision, you can replace the old MBR image with GRUB 2
+ later by issuing the following command as root:
+ .
+ upgrade-from-grub-legacy
+
+Template: grub-pc/install_devices
+Type: multiselect
+Choices-C: ${RAW_CHOICES}
+Choices: ${CHOICES}
+_Description: GRUB install devices:
+ The grub-pc package is being upgraded. This menu allows you to select which
+ devices you'd like grub-install to be automatically run for, if any.
+ .
+ Running grub-install automatically is recommended in most situations, to
+ prevent the installed GRUB core image from getting out of sync with GRUB
+ modules or grub.cfg.
+ .
+ If you're unsure which drive is designated as boot drive by your BIOS, it is
+ often a good idea to install GRUB to all of them.
+ .
+ Note: it is possible to install GRUB to partition boot records as well, and
+ some appropriate partitions are offered here. However, this forces GRUB to
+ use the blocklist mechanism, which makes it less reliable, and therefore is
+ not recommended.
+
+Template: grub-pc/install_devices_disks_changed
+Type: multiselect
+Choices-C: ${RAW_CHOICES}
+Choices: ${CHOICES}
+_Description: GRUB install devices:
+ The GRUB boot loader was previously installed to a disk that is no longer
+ present, or whose unique identifier has changed for some reason. It is
+ important to make sure that the installed GRUB core image stays in sync
+ with GRUB modules and grub.cfg. Please check again to make sure that GRUB
+ is written to the appropriate boot devices.
+ .
+ If you're unsure which drive is designated as boot drive by your BIOS, it is
+ often a good idea to install GRUB to all of them.
+ .
+ Note: it is possible to install GRUB to partition boot records as well, and
+ some appropriate partitions are offered here. However, this forces GRUB to
+ use the blocklist mechanism, which makes it less reliable, and therefore is
+ not recommended.
+
+Template: grub-pc/disk_description
+Type: text
+# Disk sizes are in decimal megabytes, to match how disk manufacturers
+# usually describe them.
+_Description: ${DEVICE} (${SIZE} MB; ${MODEL})
+
+Template: grub-pc/partition_description
+Type: text
+# The "-" is used to indicate indentation. Leading spaces may not work.
+_Description: - ${DEVICE} (${SIZE} MB; ${PATH})
+
+Template: grub-pc/install_devices_failed
+Type: boolean
+Default: false
+#flag:translate!:3
+_Description: Writing GRUB to boot device failed - continue?
+ GRUB failed to install to the following devices:
+ .
+ ${FAILED_DEVICES}
+ .
+ Do you want to continue anyway? If you do, your computer may not start up
+ properly.
+
+Template: grub-pc/install_devices_failed_upgrade
+Type: boolean
+Default: true
+#flag:translate!:3
+_Description: Writing GRUB to boot device failed - try again?
+ GRUB failed to install to the following devices:
+ .
+ ${FAILED_DEVICES}
+ .
+ You may be able to install GRUB to some other device, although you should
+ check that your system will boot from that device. Otherwise, the upgrade
+ from GRUB Legacy will be canceled.
+
+Template: grub-pc/install_devices_empty
+Type: boolean
+Default: false
+_Description: Continue without installing GRUB?
+ You chose not to install GRUB to any devices. If you continue, the boot
+ loader may not be properly configured, and when this computer next starts
+ up it will use whatever was previously in the boot sector. If there is an
+ earlier version of GRUB 2 in the boot sector, it may be unable to load
+ modules or handle the current configuration file.
+ .
+ If you are already using a different boot loader and want to carry on
+ doing so, or if this is a special environment where you do not need a boot
+ loader, then you should continue anyway. Otherwise, you should install
+ GRUB somewhere.
+
+Template: grub-pc/postrm_purge_boot_grub
+Type: boolean
+Default: false
+_Description: Remove GRUB 2 from /boot/grub?
+ Do you want to have all GRUB 2 files removed from /boot/grub?
+ .
+ This will make the system unbootable unless another boot loader is
+ installed.
+
+Template: grub-pc/mixed_legacy_and_grub2
+Type: boolean
+Default: true
+#flag:translate!:3
+_Description: Finish conversion to GRUB 2 now?
+ This system still has files from the GRUB Legacy boot loader installed, but
+ it now also has GRUB 2 boot records installed on these disks:
+ .
+ ${DISKS}
+ .
+ It seems likely that GRUB Legacy is no longer in use, and that you should
+ instead upgrade the GRUB 2 images on these disks and finish the conversion
+ to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these
+ GRUB 2 images, then they may be incompatible with the new packages and
+ cause your system to stop booting properly.
+ .
+ You should generally finish the conversion to GRUB 2 unless these boot
+ records were created by a GRUB 2 installation on some other operating
+ system.
+
+Template: grub-pc/kopt_extracted
+Type: boolean
+Default: false
+Description: for internal use
+
+Template: grub-pc/timeout
+Type: string
+Default: @DEFAULT_TIMEOUT@
+Description: GRUB timeout; for internal use
+
+Template: grub-pc/hidden_timeout
+Type: boolean
+Default: @DEFAULT_HIDDEN_TIMEOUT_BOOL@
+Description: Hide the GRUB timeout; for internal use
diff --git a/debian/grub-rescue-pc.README.Debian b/debian/grub-rescue-pc.README.Debian
new file mode 100644
index 0000000..aa31cfd
--- /dev/null
+++ b/debian/grub-rescue-pc.README.Debian
@@ -0,0 +1,22 @@
+grub-rescue-pc
+~~~~~~~~~~~~~~
+
+How to test the images with qemu:
+
+ qemu -fda /usr/lib/grub-rescue/grub-rescue-floppy.img
+
+ qemu -cdrom /usr/lib/grub-rescue/grub-rescue-cdrom.iso
+
+ qemu -hda /usr/lib/grub-rescue/grub-rescue-usb.img
+
+How to write the images to bootable media:
+
+ sudo dd if=/usr/lib/grub-rescue/grub-rescue-floppy.img of=/dev/fd0 bs=32k
+
+ sudo wodim /usr/lib/grub-rescue/grub-rescue-cdrom.iso
+ # or just use your favourite CD burning program
+
+ sudo dd if=/usr/lib/grub-rescue/grub-rescue-usb.img of=DEVICE bs=32k
+ # where DEVICE is something like /dev/sdb, corresponding to your USB
+ # stick's device name; be VERY CAREFUL that this is the correct device as
+ # otherwise you could destroy data on your hard disk!
diff --git a/debian/grub-rescue-pc.install b/debian/grub-rescue-pc.install
new file mode 100644
index 0000000..1d9cf22
--- /dev/null
+++ b/debian/grub-rescue-pc.install
@@ -0,0 +1,2 @@
+obj/grub-rescue-pc/grub-rescue-cdrom.iso usr/lib/grub-rescue
+obj/grub-rescue-pc/grub-rescue-floppy.img usr/lib/grub-rescue
diff --git a/debian/grub-rescue-pc.links b/debian/grub-rescue-pc.links
new file mode 100644
index 0000000..de8d123
--- /dev/null
+++ b/debian/grub-rescue-pc.links
@@ -0,0 +1,3 @@
+# Truth would be uselessly confusing for users. Let's give 'em what they
+# wanted instead.
+usr/lib/grub-rescue/grub-rescue-cdrom.iso usr/lib/grub-rescue/grub-rescue-usb.img
diff --git a/debian/grub-theme-starfield.install b/debian/grub-theme-starfield.install
new file mode 100644
index 0000000..05013a9
--- /dev/null
+++ b/debian/grub-theme-starfield.install
@@ -0,0 +1 @@
+usr/share/grub/themes/starfield
diff --git a/debian/grub-xen-host.install b/debian/grub-xen-host.install
new file mode 100644
index 0000000..2f242c3
--- /dev/null
+++ b/debian/grub-xen-host.install
@@ -0,0 +1,3 @@
+obj/grub-xen-host-i386/grub-i386-xen.bin usr/lib/grub-xen
+obj/grub-xen-host-pvh-i386/grub-i386-xen_pvh.bin usr/lib/grub-xen
+obj/grub-xen-host-amd64/grub-x86_64-xen.bin usr/lib/grub-xen
diff --git a/debian/grub-xen-host.lintian-overrides b/debian/grub-xen-host.lintian-overrides
new file mode 100644
index 0000000..846b4ce
--- /dev/null
+++ b/debian/grub-xen-host.lintian-overrides
@@ -0,0 +1,3 @@
+grub-xen-host: statically-linked-binary usr/lib/grub-xen/grub-i386-xen.bin
+grub-xen-host: statically-linked-binary usr/lib/grub-xen/grub-i386-xen_pvh.bin
+grub-xen-host: statically-linked-binary usr/lib/grub-xen/grub-x86_64-xen.bin
diff --git a/debian/grub-xen-host_grub-bootstrap.cfg b/debian/grub-xen-host_grub-bootstrap.cfg
new file mode 100644
index 0000000..e988314
--- /dev/null
+++ b/debian/grub-xen-host_grub-bootstrap.cfg
@@ -0,0 +1 @@
+normal (memdisk)/grub.cfg
diff --git a/debian/grub-xen-host_grub-pvh.cfg b/debian/grub-xen-host_grub-pvh.cfg
new file mode 100644
index 0000000..01820b7
--- /dev/null
+++ b/debian/grub-xen-host_grub-pvh.cfg
@@ -0,0 +1,9 @@
+if search -s -f /boot/grub/grub.cfg ; then
+ echo "Reading (${root})/boot/grub/grub.cfg"
+ configfile /boot/grub/grub.cfg
+fi
+
+if search -s -f /grub/grub.cfg ; then
+ echo "Reading (${root})/grub/grub.cfg"
+ configfile /grub/grub.cfg
+fi
diff --git a/debian/grub-xen-host_grub.cfg b/debian/grub-xen-host_grub.cfg
new file mode 100644
index 0000000..f0eecbb
--- /dev/null
+++ b/debian/grub-xen-host_grub.cfg
@@ -0,0 +1,24 @@
+# First search for a suitable grub to chainload
+if search -s -f /boot/xen/pvboot-@@PVBOOT_ARCH@@.elf ; then
+ echo "Chainloading (${root})/boot/xen/pvboot-@@PVBOOT_ARCH@@.elf"
+ multiboot "/boot/xen/pvboot-@@PVBOOT_ARCH@@.elf"
+ boot
+fi
+
+if search -s -f /xen/pvboot-@@PVBOOT_ARCH@@.elf ; then
+ echo "Chainloading (${root})/xen/pvboot-@@PVBOOT_ARCH@@.elf"
+ multiboot "/xen/pvboot-@@PVBOOT_ARCH@@.elf"
+ boot
+fi
+
+# Second try looking for grub.cfg
+
+if search -s -f /boot/grub/grub.cfg ; then
+ echo "Reading (${root})/boot/grub/grub.cfg"
+ configfile /boot/grub/grub.cfg
+fi
+
+if search -s -f /grub/grub.cfg ; then
+ echo "Reading (${root})/grub/grub.cfg"
+ configfile /grub/grub.cfg
+fi
diff --git a/debian/grub.d/05_debian_theme b/debian/grub.d/05_debian_theme
new file mode 100755
index 0000000..786888d
--- /dev/null
+++ b/debian/grub.d/05_debian_theme
@@ -0,0 +1,197 @@
+#!/bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2010 Alexander Kurtz <kurtz.alex@googlemail.com>
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+# Include the GRUB helper library for grub-mkconfig.
+. /usr/share/grub/grub-mkconfig_lib
+
+# We want to work in /boot/grub/ only.
+test -d /boot/grub; cd /boot/grub
+
+# Set the location of a possibly necessary cache file for the background image.
+# NOTE: This MUST BE A DOTFILE to avoid confusing it with user-defined images.
+BACKGROUND_CACHE=".background_cache"
+
+set_default_theme(){
+ case $GRUB_DISTRIBUTOR in
+ Tanglu|Ubuntu|Kubuntu)
+ # Set a monochromatic theme for Tanglu/Ubuntu.
+ echo "${1}set menu_color_normal=white/black"
+ echo "${1}set menu_color_highlight=black/light-gray"
+
+ if [ -e /usr/share/plymouth/themes/default.grub ]; then
+ sed "s/^/${1}/" /usr/share/plymouth/themes/default.grub
+ fi
+ # For plymouth backward compatibility. Can be removed
+ # after xenial.
+ if [ -e /lib/plymouth/themes/default.grub ]; then
+ sed "s/^/${1}/" /lib/plymouth/themes/default.grub
+ fi
+ ;;
+ *)
+ # Set the traditional Debian blue theme.
+ echo "${1}set menu_color_normal=cyan/blue"
+ echo "${1}set menu_color_highlight=white/blue"
+ ;;
+ esac
+}
+
+module_available(){
+ local module
+ for module in "${1}.mod" */"${1}.mod"; do
+ if [ -f "${module}" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+set_background_image(){
+ # Step #1: Search all available output modes ...
+ local output
+ for output in ${GRUB_TERMINAL_OUTPUT}; do
+ if [ "x$output" = "xgfxterm" ]; then
+ break
+ fi
+ done
+
+ # ... and check if we are able to display a background image at all.
+ if ! [ "x${output}" = "xgfxterm" ]; then
+ return 1
+ fi
+
+ # Step #2: Check if the specified background image exists.
+ if ! [ -f "${1}" ]; then
+ return 2
+ fi
+
+ # Step #3: Search the correct GRUB module for our background image.
+ local reader
+ case "${1}" in
+ *.jpg|*.JPG|*.jpeg|*.JPEG) reader="jpeg";;
+ *.png|*.PNG) reader="png";;
+ *.tga|*.TGA) reader="tga";;
+ *) return 3;; # Unknown image type.
+ esac
+
+ # Step #4: Check if the necessary GRUB module is available.
+ if ! module_available "${reader}"; then
+ return 4
+ fi
+
+ # Step #5: Check if GRUB can read the background image directly.
+ # If so, we can remove the cache file (if any). Otherwise the background
+ # image needs to be cached under /boot/grub/.
+ if is_path_readable_by_grub "${1}"; then
+ rm --force "${BACKGROUND_CACHE}.jpeg" \
+ "${BACKGROUND_CACHE}.png" "${BACKGROUND_CACHE}.tga"
+ elif cp "${1}" "${BACKGROUND_CACHE}.${reader}"; then
+ set -- "${BACKGROUND_CACHE}.${reader}" "${2}" "${3}"
+ else
+ return 5
+ fi
+
+ # Step #6: Prepare GRUB to read the background image.
+ if ! prepare_grub_to_access_device "`${grub_probe} --target=device "${1}"`"; then
+ return 6
+ fi
+
+ # Step #7: Everything went fine, print out a message to stderr ...
+ echo "Found background image: ${1}" >&2
+
+ # ... and write our configuration snippet to stdout. Use the colors
+ # desktop-base specified. If we're using a user-defined background, use
+ # the default colors since we've got no idea how the image looks like.
+ # If loading the background image fails, use the default theme.
+ echo "insmod ${reader}"
+ echo "if background_image `make_system_path_relative_to_its_root "${1}"`; then"
+ if [ -n "${2}" ]; then
+ echo " set color_normal=${2}"
+ fi
+ if [ -n "${3}" ]; then
+ echo " set color_highlight=${3}"
+ fi
+ if [ -z "${2}" ] && [ -z "${3}" ]; then
+ echo " true"
+ fi
+ echo "else"
+ set_default_theme " "
+ echo "fi"
+}
+
+# Earlier versions of grub-pc copied the default background image to /boot/grub
+# during postinst. Remove those obsolete images if they haven't been touched by
+# the user. They are still available under /usr/share/images/desktop-base/ if
+# desktop-base is installed.
+while read checksum background; do
+ if [ -f "${background}" ] && [ "x`sha1sum "${background}"`" = "x${checksum} ${background}" ]; then
+ echo "Removing old background image: ${background}" >&2
+ rm "${background}"
+ fi
+done <<EOF
+648ee65dd0c157a69b019a5372cbcfea4fc754a5 debian-blueish-wallpaper-640x480.png
+0431e97a6c661084c59676c4baeeb8c2f602edb8 debian-blueish-wallpaper-640x480.png
+968ecf6696c5638cfe80e8e70aba239526270864 debian-blueish-wallpaper-640x480.tga
+11143e8c92a073401de0b0fd42d0c052af4ccd9b moreblue-orbit-grub.png
+d00d5e505ab63f2d53fa880bfac447e2d3bb197c moreblue-orbit-grub.png
+f5b12c1009ec0a3b029185f6b66cd0d7e5611019 moreblue-orbit-grub.png
+EOF
+
+# Include the configuration of desktop-base if available.
+if [ -f "/usr/share/desktop-base/grub_background.sh" ]; then
+ . "/usr/share/desktop-base/grub_background.sh"
+fi
+
+# First check whether the user has specified a background image explicitly.
+# If so, try to use it. Don't try the other possibilities in that case
+# (#608263).
+if [ -n "${GRUB_BACKGROUND+x}" ]; then
+ set_background_image "${GRUB_BACKGROUND}" || set_default_theme
+ exit 0
+fi
+
+# Next search for pictures the user put into /boot/grub/ and use the first one.
+for background in *.jpg *.JPG *.jpeg *.JPEG *.png *.PNG *.tga *.TGA; do
+ if set_background_image "${background}"; then
+ exit 0
+ fi
+done
+
+# Next try to use the background image and colors specified by desktop-base.
+if set_background_image "${WALLPAPER}" "${COLOR_NORMAL}" "${COLOR_HIGHLIGHT}"; then
+ exit 0
+fi
+
+# If we haven't found a background image yet, use the default from desktop-base.
+case $GRUB_DISTRIBUTOR in
+ Ubuntu|Kubuntu)
+ ;;
+ Tanglu)
+ if set_background_image "/usr/share/images/grub/grub.png"; then
+ exit 0
+ fi
+ ;;
+ *)
+ if set_background_image "/usr/share/images/desktop-base/desktop-grub.png"; then
+ exit 0
+ fi
+ ;;
+esac
+
+# Finally, if all of the above fails, use the default theme.
+set_default_theme
diff --git a/debian/grub2-common.install b/debian/grub2-common.install
new file mode 100644
index 0000000..74020d9
--- /dev/null
+++ b/debian/grub2-common.install
@@ -0,0 +1,12 @@
+../../debian/default usr/share/grub
+../../debian/update-grub usr/sbin
+../../debian/kernel/zz-update-grub etc/kernel/postinst.d
+../../debian/kernel/zz-update-grub etc/kernel/postrm.d
+
+usr/sbin/grub-install
+usr/sbin/grub-reboot
+usr/sbin/grub-set-default
+usr/share/info
+usr/share/man/man8/grub-install.8
+usr/share/man/man8/grub-reboot.8
+usr/share/man/man8/grub-set-default.8
diff --git a/debian/grub2-common.links b/debian/grub2-common.links
new file mode 100644
index 0000000..a082aa2
--- /dev/null
+++ b/debian/grub2-common.links
@@ -0,0 +1,6 @@
+usr/sbin/update-grub usr/sbin/update-grub2
+usr/share/man/man8/update-grub.8 usr/share/man/man8/update-grub2.8
+
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-install
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-reboot
+usr/share/bash-completion/completions/grub usr/share/bash-completion/completions/grub-set-default
diff --git a/debian/grub2-common.manpages b/debian/grub2-common.manpages
new file mode 100644
index 0000000..58fef3f
--- /dev/null
+++ b/debian/grub2-common.manpages
@@ -0,0 +1 @@
+debian/update-grub.8
diff --git a/debian/init-select.cfg b/debian/init-select.cfg
new file mode 100644
index 0000000..7fbfff8
--- /dev/null
+++ b/debian/init-select.cfg
@@ -0,0 +1,7 @@
+# Work around a bug in the obsolete init-select package which broke
+# grub-mkconfig when init-select was removed but not purged. This file does
+# nothing and will be removed in a later release.
+#
+# See:
+# https://bugs.debian.org/858528
+# https://bugs.debian.org/863801
diff --git a/debian/install-bin.in b/debian/install-bin.in
new file mode 100644
index 0000000..ef09308
--- /dev/null
+++ b/debian/install-bin.in
@@ -0,0 +1,5 @@
+usr/lib/grub/@CPU_PLATFORM@/*.img
+usr/lib/grub/@CPU_PLATFORM@/*.lst
+usr/lib/grub/@CPU_PLATFORM@/*.mod
+usr/lib/grub/@CPU_PLATFORM@/config.h
+usr/lib/grub/@CPU_PLATFORM@/modinfo.sh
diff --git a/debian/install-dbg.in b/debian/install-dbg.in
new file mode 100644
index 0000000..dfea164
--- /dev/null
+++ b/debian/install-dbg.in
@@ -0,0 +1,4 @@
+usr/lib/grub/@CPU_PLATFORM@/*.exec
+usr/lib/grub/@CPU_PLATFORM@/*.module
+usr/lib/grub/@CPU_PLATFORM@/gdb_grub
+usr/lib/grub/@CPU_PLATFORM@/gmodule.pl
diff --git a/debian/install.in b/debian/install.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/debian/install.in
diff --git a/debian/kernel/zz-update-grub b/debian/kernel/zz-update-grub
new file mode 100755
index 0000000..9521057
--- /dev/null
+++ b/debian/kernel/zz-update-grub
@@ -0,0 +1,26 @@
+#! /bin/sh
+set -e
+
+command -v update-grub >/dev/null || exit 0
+
+if type systemd-detect-virt >/dev/null 2>&1 &&
+ systemd-detect-virt --quiet --container; then
+ exit 0
+fi
+
+set -- $DEB_MAINT_PARAMS
+mode="${1#\'}"
+mode="${mode%\'}"
+case $0:$mode in
+ # Only run on postinst configure and postrm remove, to avoid wasting
+ # time by calling update-grub multiple times on upgrade and removal.
+ # Also run if we have no DEB_MAINT_PARAMS, in order to work with old
+ # kernel packages.
+ */postinst.d/*:|*/postinst.d/*:configure|*/postrm.d/*:|*/postrm.d/*:remove)
+ if [ -e /boot/grub/grub.cfg ]; then
+ exec update-grub
+ fi
+ ;;
+esac
+
+exit 0
diff --git a/debian/legacy/update-grub b/debian/legacy/update-grub
new file mode 100755
index 0000000..aaa3f83
--- /dev/null
+++ b/debian/legacy/update-grub
@@ -0,0 +1,1068 @@
+#!/bin/bash
+#
+# Insert a list of installed kernels in a grub config file
+# Copyright 2001 Wichert Akkerman <wichert@linux.com>
+# Copyright (C) 2007,2008 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+#
+# Contributors:
+# Jason Thomas <jason@debian.org>
+# David B.Harris <dbarclay10@yahoo.ca>
+# Marc Haber <mh+debian-packages@zugschlus.de>
+# Crispin Flowerday <crispin@zeus.com>
+
+# Abort on errors
+set -e
+
+host_os=`uname -s | tr '[A-Z]' '[a-z]'`
+
+abort() {
+ message=$@
+
+ echo >&2
+ echo -e "$message" >&2
+ echo >&2
+ exit 1
+}
+
+find_grub_dir ()
+{
+ echo -n "Searching for GRUB installation directory ... " >&2
+
+ for d in /boot/grub /boot/boot/grub ; do
+ if [ -d "$d" ] ; then
+ grub_dir="$d"
+ break
+ fi
+ done
+
+ if [ -z "$grub_dir" ] ; then
+ abort "No GRUB directory found.\n To create a template run 'mkdir /boot/grub' first.\n To install grub, install it manually or try the 'grub-install' command.\n ### Warning, grub-install is used to change your MBR. ###"
+ else
+ echo "found: $grub_dir" >&2
+ fi
+
+ echo $grub_dir
+}
+
+# This function was borrowed from grub2/util/update-grub_lib.in
+make_system_path_relative_to_its_root ()
+{
+ path=$1
+ # abort if file doesn't exist
+ if test -e $path ; then : ;else
+ return 1
+ fi
+
+ # canonicalize
+ if path=`readlink -f $path` ; then : ; else
+ return 1
+ fi
+
+ # if not a directory, climb up to the directory containing it
+ if test -d $path ; then
+ dir=$path
+ else
+ dir=`echo $path | sed -e "s,/[^/]*$,,g"`
+ fi
+
+ num=`stat -c %d $dir`
+
+ # this loop sets $dir to the root directory of the filesystem we're inspecting
+ while : ; do
+ parent=`readlink -f $dir/..`
+ if [ "x`stat -c %d $parent`" = "x$num" ] ; then : ; else
+ # $parent is another filesystem; we found it.
+ break
+ fi
+ if [ "x$dir" = "x/" ] ; then
+ # / is our root.
+ break
+ fi
+ dir=$parent
+ done
+
+ # This function never prints trailing slashes (so that its output can be
+ # appended a slash unconditionally). Each slash in $dir is considered a
+ # preceding slash, and therefore the root directory is an empty string.
+ if [ "$dir" = "/" ] ; then
+ dir=""
+ fi
+
+ echo $path | sed -e "s,^$dir,,g"
+}
+
+# The grub installation directory
+grub_dir=$(find_grub_dir)
+
+# Full path to the device.map
+device_map=$grub_dir/device.map
+
+find_device ()
+{
+ if ! test -e ${device_map} ; then
+ echo quit | grub --batch --no-floppy --device-map=${device_map} > /dev/null
+ fi
+ grub-probe --device-map=${device_map} -t device $1 2> /dev/null
+}
+
+# Usage: convert_raid1 os_device
+# Checks if os_device is a software raid1.
+# If so, converts to first physical device in array.
+convert_raid1 ()
+{
+ case $1 in
+ /dev/md[0-9] | /dev/md/[0-9])
+ : ;; # Continue
+ *)
+ return 1 ;;
+ esac
+
+ [ -x /sbin/mdadm ] || return 1
+
+ # Check that the raid device is raid1
+ raidlevel=$(mdadm -D -b $1 | grep "^ARRAY" | \
+ sed "s/^.*level=//" | cut -d" " -f1)
+ [ "$raidlevel" = "raid1" ] || return 1
+
+ # Take only the first device that makes up the raid
+ raiddev=$(mdadm -D $1 | grep -A1 "Number" | grep "dev" \
+ | sed "s/^.*\(\/dev\/.*\)$/\1/")
+ [ -n "$raiddev" ] || return 1
+
+ echo $raiddev
+ return 0
+}
+
+# Usage: convert os_device
+# Convert an OS device to the corresponding GRUB drive.
+convert () {
+ if ! test -e ${device_map} ; then
+ echo quit | grub --batch --no-floppy --device-map=${device_map} > /dev/null
+ fi
+ GRUB_LEGACY_0_BASED_PARTITIONS=1 grub-probe --device-map=${device_map} -t drive -d "$1" 2> /dev/null || {
+ echo "warning: grub-probe can't find drive for $1." >&2
+ tmp_map=$(mktemp -t device.map.XXXXXXXX)
+ grub-mkdevicemap --device-map=${tmp_map} --no-floppy >/dev/null 2>&1 || true
+ GRUB_LEGACY_0_BASED_PARTITIONS=1 grub-probe --device-map=${tmp_map} -t drive -d "$1" || {
+ rm -f ${tmp_map}
+ return 1
+ }
+ echo "Please check ${device_map}, you might have to regenerate it with grub-mkdevicemap." >&2
+ rm -f ${tmp_map}
+ }
+}
+
+# Usage: convert_default os_device
+# Convert an OS device to the corresponding GRUB drive.
+convert_default () {
+ # Check if device is software raid1 array
+ if tmp_dev=$(convert_raid1 $1 2>/dev/null) ; then
+ : # Use device returned by convert_raid1
+ else
+ tmp_dev=$1
+ fi
+
+ convert $tmp_dev
+}
+
+## Configuration Options
+
+# Full path to the menu.lst
+menu_file_basename=menu.lst
+menu_file=$grub_dir/$menu_file_basename
+
+# Full path to the default file
+default_file_basename=default
+default_file=$grub_dir/$default_file_basename
+
+# the device for the / filesystem
+root_device=$(find_device "/")
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${root_device} in
+ /dev/loop/*|/dev/loop[0-9])
+ root_device=`losetup ${root_device} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
+ ;;
+esac
+
+# the device for the /boot filesystem
+boot_device=$(find_device "/boot")
+
+# where grub looks for the kernels at boot time
+kernel_dir=`make_system_path_relative_to_its_root /boot`
+
+# the "-t abstraction" check is a workaround untill #484297 is fixed
+if abstraction=`grub-probe -t abstraction --device ${root_device} 2> /dev/null` && [ "$abstraction" = "" ] && \
+ root_uuid=`grub-probe --device-map=${device_map} --device ${root_device} --target=fs_uuid 2> /dev/null` && \
+ test -e "/dev/disk/by-uuid/${root_uuid}" ; then
+ linux_root_device=UUID=${root_uuid}
+else
+ linux_root_device=${root_device}
+fi
+
+# Default kernel options, overidden by the kopt statement in the menufile.
+kopt="root=$linux_root_device ro"
+
+# Title
+title="Debian GNU/`uname -s | sed -e s,GNU/,,g`"
+
+# should update-grub remember the default entry
+updatedefaultentry="false"
+
+# Drive(in GRUB terms) where the kernel is located. Overridden by the
+# groot statement in menufile.
+grub_root_device=$(convert_default "$boot_device")
+
+# should grub create the alternative boot options in the menu
+ alternative="true"
+
+# should grub lock the alternative boot options in the menu
+ lockalternative="false"
+
+# additional options to use with the default boot option, but not with the
+# alternatives
+ defoptions=""
+
+# should grub lock the old kernels
+ lockold="false"
+
+# Xen hypervisor options to use with the default Xen boot option
+ xenhopt=""
+
+# Xen Linux kernel options to use with the default Xen boot option
+ xenkopt="console=tty0"
+
+# options to use with the alternative boot options
+ altoptions="(single-user mode) single"
+
+# controls howmany kernels are listed in the config file,
+# this does not include the alternative kernels
+ howmany="all"
+
+# should grub create a memtest86 entry
+ memtest86="true"
+
+# should grub add "savedefault" to default boot options
+ savedefault="false"
+
+# stores the command line arguments
+ command_line_arguments=$1
+
+# read user configuration
+if test -f "/etc/default/grub" ; then
+ . /etc/default/grub
+fi
+
+# Default options to use in a new config file. This will only be used if $menu_file
+# doesn't already exist. Only edit the lines between the two "EOF"s. The others are
+# part of the script.
+newtemplate=$(tempfile)
+cat > "$newtemplate" <<EOF
+# $menu_file_basename - See: grub(8), info grub, update-grub(8)
+# grub-install(8), grub-floppy(8),
+# grub-md5-crypt, /usr/share/doc/grub
+# and /usr/share/doc/grub-legacy-doc/.
+
+## default num
+# Set the default entry to the entry number NUM. Numbering starts from 0, and
+# the entry number 0 is the default if the command is not used.
+#
+# You can specify 'saved' instead of a number. In this case, the default entry
+# is the entry saved with the command 'savedefault'.
+# WARNING: If you are using dmraid do not change this entry to 'saved' or your
+# array will desync and will not let you boot your system.
+default 0
+
+## timeout sec
+# Set a timeout, in SEC seconds, before automatically booting the default entry
+# (normally the first entry defined).
+timeout 5
+
+# Pretty colours
+color cyan/blue white/blue
+
+## password ['--md5'] passwd
+# If used in the first section of a menu file, disable all interactive editing
+# control (menu entry editor and command-line) and entries protected by the
+# command 'lock'
+# e.g. password topsecret
+# password --md5 \$1\$gLhU0/\$aW78kHK1QfV3P2b2znUoe/
+# password topsecret
+
+#
+# examples
+#
+# title Windows 95/98/NT/2000
+# root (hd0,0)
+# makeactive
+# chainloader +1
+#
+# title Linux
+# root (hd0,1)
+# kernel /vmlinuz root=/dev/hda2 ro
+#
+
+#
+# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
+
+EOF
+## End Configuration Options
+
+echo -n "Searching for default file ... " >&2
+if [ -f "$default_file" ] ; then
+ echo "found: $default_file" >&2
+else
+ echo "Generating $default_file file and setting the default boot entry to 0" >&2
+ if [ -f /usr/lib/grub-legacy/grub-set-default ] ; then
+ /usr/lib/grub-legacy/grub-set-default 0
+ else
+ grub-set-default 0
+ fi
+fi
+
+# Make sure we use the standard sorting order
+LC_COLLATE=C
+# Magic markers we use
+start="### BEGIN AUTOMAGIC KERNELS LIST"
+end="### END DEBIAN AUTOMAGIC KERNELS LIST"
+
+startopt="## ## Start Default Options ##"
+endopt="## ## End Default Options ##"
+
+# Extract options from config file
+ExtractMenuOpt()
+{
+ opt=$1
+
+ sed -ne "/^$start\$/,/^$end\$/ {
+ /^$startopt\$/,/^$endopt\$/ {
+ /^# $opt=/ {
+ s/^# $opt=\(.*\)\$/\1/
+ p
+ }
+ }
+ }" $menu
+}
+
+GetMenuOpts()
+{
+ opt=$1
+
+ sed -ne "/^$start\$/,/^$end\$/ {
+ /^$startopt\$/,/^$endopt\$/ {
+ /^# $opt=/ {
+ p
+ }
+ }
+ }" $menu
+}
+
+ExtractMenuOpts()
+{
+ opt=$1
+
+ GetMenuOpts $opt | sed "s/^# $opt=\(.*\)\$/\1=\"\2\"/"
+}
+
+GetMenuOpt()
+{
+ opt=$1
+ value=$2
+
+ [ -z "$(GetMenuOpts "$opt")" ] || value=$(ExtractMenuOpt "$opt")
+
+ echo $value
+}
+
+# Compares two version strings A and B
+# Returns -1 if A<B
+# 0 if A==B
+# 1 if A>B
+# This compares version numbers of the form
+# 2.4.14.2 > 2.4.14
+# 2.4.14random = 2.4.14-random > 2.4.14-ac10 > 2.4.14 > 2.4.14-pre2 >
+# 2.4.14-pre1 > 2.4.13-ac99
+CompareVersions()
+{
+ local sedexp="s,.*/vmlinu[zx]-,,g;s/[._-]\(pre\|rc\|test\|git\|trunk\)/~\1/g"
+ local a=`echo $1 | sed -e "$sedexp"`
+ local b=`echo $2 | sed -e "$sedexp"`
+ if [ "$a" = "$b" ] ; then
+ echo 0
+ elif dpkg --compare-versions "$a" gt "$b" ; then
+ echo 1
+ else
+ echo -1
+ fi
+}
+
+# looks in the directory specified for an initrd image with the version specified
+FindInitrdName()
+{
+ # strip trailing slashes
+ directory=$(echo $1 | sed -e 's#/*$##')
+ version=$2
+
+ # initrd
+ # initrd.img
+ # initrd-lvm
+ # .*.gz
+
+ initrdName=""
+ names="initrd initrd.img initrd-lvm"
+ compressed="gz"
+
+ for n in $names ; do
+ # make sure we haven't already found it
+ if [ -z "$initrdName" ] ; then
+ if [ -f "$directory/$n$version" ] ; then
+ initrdName="$n$version"
+ break
+ else
+ for c in $compressed ; do
+ if [ -f "$directory/$n$version.$c" ] ; then
+ initrdName="$n$version.$c"
+ break
+ fi
+ done
+ fi
+ else
+ break
+ fi
+ done
+
+ # return the result
+ echo $initrdName
+}
+
+FindXenHypervisorVersions ()
+{
+ version=$1
+
+ if [ -f "/var/lib/linux-image-$version/xen-versions" ]; then
+ ret="$(cat /var/lib/linux-image-$version/xen-versions)"
+ fi
+
+ echo $ret
+}
+
+get_kernel_opt()
+{
+ kernel_version=$1
+
+ version=$(echo $kernel_version | sed 's/^[^0-9]*//')
+ version=$(echo $version | sed 's/[-\+\.]/_/g')
+ if [ -n "$version" ] ; then
+ while [ -n "$version" ] ; do
+ currentOpt="$(eval "echo \${kopt_$version}")"
+ if [ -n "$currentOpt" ] ; then
+ break
+ fi
+ version=$(echo $version | sed 's/_\?[^_]*$//')
+ done
+ fi
+
+ if [ -z "$currentOpt" ] ; then
+ currentOpt=$kopt
+ fi
+
+ echo $currentOpt
+}
+
+write_kernel_entry()
+{
+ local kernel_version; kernel_version=$1; shift
+ local recovery_desc; recovery_desc=$1; shift
+ local lock_alternative; lock_alternative=$1; shift
+ local grub_root_device; grub_root_device=$1; shift
+ local kernel; kernel=$1; shift
+ local kernel_options; kernel_options=$1; shift
+ local recovery_suffix; recovery_suffix=$1; shift
+ local initrd; initrd=$1; shift
+ local savedefault; savedefault=$1; shift
+ local lockold; lockold=$1; shift
+ local hypervisor
+ if [ -n "$1" ]; then
+ # Hypervisor.
+ hypervisor=$1; shift
+ local hypervisor_image; hypervisor_image=$1; shift
+ local hypervisor_version; hypervisor_version=$1; shift
+ local hypervisor_options; hypervisor_options=$1; shift
+ fi
+
+ echo -n "title " >> $buffer
+
+ if [ -n "$hypervisor" ]; then
+ echo -n "$hypervisor $hypervisor_version / " >> $buffer
+ fi
+
+ echo -n "$title" >> $buffer
+ if [ -n "$kernel_version" ]; then
+ echo -n ", kernel $kernel_version" >> $buffer
+ fi
+ if [ -n "$recovery_desc" ]; then
+ echo -n " $recovery_desc" >> $buffer
+ fi
+ echo >> $buffer
+
+ # lock the alternative options
+ if test x"$lock_alternative" = x"true" ; then
+ echo "lock" >> $buffer
+ fi
+ # lock the old entries
+ if test x"$lockold" = x"true" ; then
+ echo "lock" >> $buffer
+ fi
+
+ echo "root $grub_root_device" >> $buffer
+
+ echo -n "kernel " >> $buffer
+ if [ -n "$hypervisor" ]; then
+ echo -n "$hypervisor_image" >> $buffer
+ if [ -n "$hypervisor_options" ]; then
+ echo -n " $hypervisor_options" >> $buffer
+ fi
+ echo >> $buffer
+ echo -n "module " >> $buffer
+ fi
+ echo -n "$kernel" >> $buffer
+ if [ -n "$kernel_options" ]; then
+ echo -n " $kernel_options" >> $buffer
+ fi
+ if [ -n "$recovery_desc" ]; then
+ echo -n " $recovery_suffix" >> $buffer
+ fi
+ echo >> $buffer
+
+ if [ -n "$initrd" ]; then
+ if [ -n "$hypervisor" ]; then
+ echo -n "module " >> $buffer
+ else
+ echo -n "initrd " >> $buffer
+ fi
+ echo "$initrd" >> $buffer
+ fi
+
+ if test x"$savedefault" = x"true" ; then
+ echo "savedefault" >> $buffer
+ fi
+ echo >> $buffer
+}
+
+
+echo -n "Testing for an existing GRUB $menu_file_basename file ... " >&2
+
+# Test if our menu file exists
+if [ -f "$menu_file" ] ; then
+ menu="$menu_file"
+ rm -f $newtemplate
+ unset newtemplate
+ echo "found: $menu_file" >&2
+ cp -f "$menu_file" "$menu_file~"
+else
+ # if not ask user if they want us to create one
+ menu="$menu_file"
+ echo >&2
+ echo >&2
+ if [ "-y" = "$command_line_arguments" ] ; then
+ echo "Warning: ignoring deprecated -y option." >&2
+ fi
+ echo >&2
+ echo "Generating $menu_file" >&2
+ cat "$newtemplate" > $menu_file
+ rm -f $newtemplate
+ unset newtemplate
+fi
+
+# Extract the kernel options to use
+kopt=$(GetMenuOpt "kopt" "$kopt")
+
+# Set the kernel 2.6 option only for fresh install
+test -z "$(GetMenuOpt "kopt" "")" && kopt_2_6="root=$linux_root_device ro"
+
+# Extract options for specific kernels
+opts="$(ExtractMenuOpts "\(kopt_[[:alnum:]_]\+\)")"
+test -z "$opts" || eval "$opts"
+CustomKopts=$(GetMenuOpts "\(kopt_[[:alnum:]_]\+\)")
+
+# Extract the grub root
+grub_root_device=$(GetMenuOpt "groot" "$grub_root_device")
+
+# Extract the old recovery value
+alternative=$(GetMenuOpt "recovery" "$alternative")
+
+# Extract the alternative value
+alternative=$(GetMenuOpt "alternative" "$alternative")
+
+# Extract the lockalternative value
+lockalternative=$(GetMenuOpt "lockalternative" "$lockalternative")
+
+# Extract the additional default options
+defoptions=$(GetMenuOpt "defoptions" "$defoptions")
+
+# Extract the lockold value
+lockold=$(GetMenuOpt "lockold" "$lockold")
+
+# Extract Xen hypervisor options
+xenhopt=$(GetMenuOpt "xenhopt" "$xenhopt")
+
+# Extract Xen Linux kernel options
+xenkopt=$(GetMenuOpt "xenkopt" "$xenkopt")
+
+# Extract the howmany value
+howmany=$(GetMenuOpt "howmany" "$howmany")
+
+# Extract the memtest86 value
+memtest86=$(GetMenuOpt "memtest86" "$memtest86")
+
+
+# Extract the updatedefaultentry option
+updatedefaultentry=$(GetMenuOpt "updatedefaultentry" "$updatedefaultentry")
+
+# Extract the savedefault option
+savedefault=$(GetMenuOpt "savedefault" "$savedefault")
+
+# Generate the menu options we want to insert
+buffer=$(tempfile)
+echo $start >> $buffer
+echo "## lines between the AUTOMAGIC KERNELS LIST markers will be modified" >> $buffer
+echo "## by the debian update-grub script except for the default options below" >> $buffer
+echo >> $buffer
+echo "## DO NOT UNCOMMENT THEM, Just edit them to your needs" >> $buffer
+echo >> $buffer
+echo "## ## Start Default Options ##" >> $buffer
+
+echo "## default kernel options" >> $buffer
+echo "## default kernel options for automagic boot options" >> $buffer
+echo "## If you want special options for specific kernels use kopt_x_y_z" >> $buffer
+echo "## where x.y.z is kernel version. Minor versions can be omitted." >> $buffer
+echo "## e.g. kopt=root=/dev/hda1 ro" >> $buffer
+echo "## kopt_2_6_8=root=/dev/hdc1 ro" >> $buffer
+echo "## kopt_2_6_8_2_686=root=/dev/hdc2 ro" >> $buffer
+echo "# kopt=$kopt" >> $buffer
+if [ -n "$CustomKopts" ] ; then
+ echo "$CustomKopts" >> $buffer
+elif [ -n "$kopt_2_6" ] && [ "$kopt" != "$kopt_2_6" ]; then
+ echo "# kopt_2_6=$kopt_2_6" >> $buffer
+fi
+echo >> $buffer
+
+echo "## default grub root device" >> $buffer
+echo "## e.g. groot=(hd0,0)" >> $buffer
+echo "# groot=$grub_root_device" >> $buffer
+echo >> $buffer
+
+echo "## should update-grub create alternative automagic boot options" >> $buffer
+echo "## e.g. alternative=true" >> $buffer
+echo "## alternative=false" >> $buffer
+echo "# alternative=$alternative" >> $buffer
+echo >> $buffer
+
+echo "## should update-grub lock alternative automagic boot options" >> $buffer
+echo "## e.g. lockalternative=true" >> $buffer
+echo "## lockalternative=false" >> $buffer
+echo "# lockalternative=$lockalternative" >> $buffer
+echo >> $buffer
+
+echo "## additional options to use with the default boot option, but not with the" >> $buffer
+echo "## alternatives" >> $buffer
+echo "## e.g. defoptions=vga=791 resume=/dev/hda5" >> $buffer
+echo "# defoptions=$defoptions" >> $buffer
+echo >> $buffer
+
+echo "## should update-grub lock old automagic boot options" >> $buffer
+echo "## e.g. lockold=false" >> $buffer
+echo "## lockold=true" >> $buffer
+echo "# lockold=$lockold" >> $buffer
+echo >> $buffer
+
+echo "## Xen hypervisor options to use with the default Xen boot option" >> $buffer
+echo "# xenhopt=$xenhopt" >> $buffer
+echo >> $buffer
+
+echo "## Xen Linux kernel options to use with the default Xen boot option" >> $buffer
+echo "# xenkopt=$xenkopt" >> $buffer
+echo >> $buffer
+
+echo "## altoption boot targets option" >> $buffer
+echo "## multiple altoptions lines are allowed" >> $buffer
+echo "## e.g. altoptions=(extra menu suffix) extra boot options" >> $buffer
+echo "## altoptions=(single-user) single" >> $buffer
+
+if ! grep -q "^# altoptions" $menu ; then
+ echo "# altoptions=$altoptions" >> $buffer
+else
+ grep "^# altoptions" $menu >> $buffer
+fi
+echo >> $buffer
+
+echo "## controls how many kernels should be put into the $menu_file_basename" >> $buffer
+echo "## only counts the first occurence of a kernel, not the" >> $buffer
+echo "## alternative kernel options" >> $buffer
+echo "## e.g. howmany=all" >> $buffer
+echo "## howmany=7" >> $buffer
+echo "# howmany=$howmany" >> $buffer
+echo >> $buffer
+
+
+echo "## should update-grub create memtest86 boot option" >> $buffer
+echo "## e.g. memtest86=true" >> $buffer
+echo "## memtest86=false" >> $buffer
+echo "# memtest86=$memtest86" >> $buffer
+echo >> $buffer
+
+echo "## should update-grub adjust the value of the default booted system" >> $buffer
+echo "## can be true or false" >> $buffer
+echo "# updatedefaultentry=$updatedefaultentry" >> $buffer
+echo >> $buffer
+
+echo "## should update-grub add savedefault to the default options" >> $buffer
+echo "## can be true or false" >> $buffer
+echo "# savedefault=$savedefault" >> $buffer
+echo >> $buffer
+
+echo "## ## End Default Options ##" >> $buffer
+echo >> $buffer
+
+echo -n "Searching for splash image ... " >&2
+current_splash=`grep '^splashimage=' ${menu_file} || true`
+grub_dir_rel=`make_system_path_relative_to_its_root $grub_dir`
+splashimage_path="splashimage=${grub_root_device}/${grub_dir_rel##${kernel_dir}}/splash.xpm.gz"
+if [ `sed -e "/^$start/,/^$end/d" $menu_file | grep -c '^splashimage='` != "0" ] ; then
+ #checks for splashscreen defined outside the autoupdated part
+ splashimage=$(grep '^splashimage=' ${menu_file})
+ echo "found: ${splashimage##*=}" >&2
+ echo >&2
+elif [ -f "${grub_dir}/splash.xpm.gz" ] && [ "$current_splash" = "" ]; then
+ echo "found: /boot/grub/splash.xpm.gz" >&2
+ echo "$splashimage_path" >> $buffer
+ echo >> $buffer
+elif [ -f "${grub_dir}/splash.xpm.gz" ] && [ "$current_splash" = "$splashimage_path" ]; then
+ echo "found: /boot/grub/splash.xpm.gz" >&2
+ echo "$splashimage_path" >> $buffer
+ echo >> $buffer
+elif [ "$current_splash" != "" ] && [ "$current_splash" != "$splashimage_path" ]; then
+ echo "found but preserving previous setting: $(grep '^splashimage=' ${menu_file})" >&2
+ echo "$current_splash" >> $buffer
+ echo >> $buffer
+else
+ echo "none found, skipping ..." >&2
+fi
+
+xen0Kernels=""
+# First kernels with xen0 support.
+for ver in `grep -l CONFIG_XEN=y /boot/config* | sed -e s%/boot/config-%%`; do
+ if ! grep -q CONFIG_XEN_PRIVILEGED_GUEST=y /boot/config-$ver ; then
+ continue
+ fi
+ # ver is a kernel version
+ kern="/boot/vmlinuz-$ver"
+ if [ -r $kern ] ; then
+ newerKernels=""
+ for i in $xen0Kernels ; do
+ res=$(CompareVersions "$kern" "$i")
+ if [ "$kern" != "" ] && [ "$res" -gt 0 ] ; then
+ newerKernels="$newerKernels $kern $i"
+ kern=""
+ else
+ newerKernels="$newerKernels $i"
+ fi
+ done
+ if [ "$kern" != "" ] ; then
+ newerKernels="$newerKernels $kern"
+ fi
+ xen0Kernels="$newerKernels"
+ fi
+done
+
+sortedKernels=""
+for kern in $(/bin/ls -1vr /boot | grep -v "dpkg-*" | grep "^vmlinuz-") ; do
+ kern="/boot/$kern"
+ newerKernels=""
+ for i in $sortedKernels ; do
+ res=$(CompareVersions "$kern" "$i")
+ if [ "$kern" != "" ] && [ "$res" -gt 0 ] ; then
+ newerKernels="$newerKernels $kern $i"
+ kern=""
+ else
+ newerKernels="$newerKernels $i"
+ fi
+ done
+ if [ "$kern" != "" ] ; then
+ newerKernels="$newerKernels $kern"
+ fi
+ sortedKernels="$newerKernels"
+done
+
+if test -f "/boot/vmlinuz.old" ; then
+ sortedKernels="/boot/vmlinuz.old $sortedKernels"
+fi
+if test -f "/boot/vmlinuz" ; then
+ sortedKernels="/boot/vmlinuz $sortedKernels"
+fi
+
+hypervisors=""
+for hyp in /boot/xen-*.gz; do
+ if [ ! -h "$hyp" ] && [ -f "$hyp" ]; then
+ hypervisors="$hypervisors `basename "$hyp"`"
+ fi
+done
+
+#Finding the value the default line
+use_grub_set_default="false"
+if test "$updatedefaultentry" = "true" ; then
+ defaultEntryNumber=$(sed -ne 's/^[[:blank:]]*default[[:blank:]]*\(.*\).*/\1/p' $menu)
+
+ if [ "$defaultEntryNumber" = "saved" ] ; then
+ defaultEntryNumber=$(sed 'q' "$grub_dir/default")
+ use_grub_set_default="true"
+ fi
+
+ if test -n "$defaultEntryNumber"; then
+ defaultEntryNumberPlusOne=$(expr $defaultEntryNumber \+ 1);
+ defaultEntry=$(grep "^[[:blank:]]*title" $menu | sed -ne "${defaultEntryNumberPlusOne}p" | sed -ne ";s/^[[:blank:]]*title[[:blank:]]*//p")
+ defaultEntry=$(echo $defaultEntry | sed -e "s/[[:blank:]]*$//") # don't trust trailing blanks
+ else
+ notChangeDefault="yes"
+ fi
+else
+ notChangeDefault="yes"
+fi
+
+## heres where we start writing out the kernel entries
+counter=0
+
+grub2name="${kernel_dir}/grub/core.img"
+if [ "$LET_US_TRY_GRUB_2" = "true" ] \
+ && test -f /boot/grub/core.img ; then
+ echo "Found GRUB 2: $grub2name" >&2
+ cat >> $buffer << EOF
+title Chainload into GRUB 2
+root $grub_root_device
+kernel $grub2name
+
+title `echo ───────────────────────────────────────────────────────────────────── | iconv -f utf-8 -t cp437`
+root
+
+title When you have verified GRUB 2 works, you can use this command to
+root
+
+title complete the upgrade: upgrade-from-grub-legacy
+root
+
+title `echo ───────────────────────────────────────────────────────────────────── | iconv -f utf-8 -t cp437`
+root
+
+EOF
+fi
+
+
+# Xen entries first.
+for kern in $xen0Kernels ; do
+ if test ! x"$howmany" = x"all" ; then
+ if [ $counter -gt $howmany ] ; then
+ break
+ fi
+ fi
+
+ kernelName=$(basename $kern)
+ kernelVersion=$(echo $kernelName | sed -e 's/vmlinuz//')
+
+ initrdName=$(FindInitrdName "/boot" "$kernelVersion")
+ initrd=""
+
+ kernel=$kernel_dir/$kernelName
+ if [ -n "$initrdName" ] ; then
+ initrd=$kernel_dir/$initrdName
+ fi
+
+ kernelVersion=$(echo $kernelVersion | sed -e 's/^-//')
+ currentOpt=$(get_kernel_opt $kernelVersion)
+
+ hypervisorVersions=$(FindXenHypervisorVersions "$kernelVersion")
+
+ found=
+ for hypervisorVersion in $hypervisorVersions; do
+ hypervisor="$kernel_dir/xen-$hypervisorVersion.gz"
+ if [ -e "$hypervisor" ]; then
+ found=1
+
+ echo "Found Xen hypervisor $hypervisorVersion, kernel: $kernel" >&2
+
+ write_kernel_entry "$kernelVersion" '' '' "$grub_root_device" \
+ "$kernel" "$currentOpt $xenkopt" '' "$initrd" "$savedefault" '' \
+ Xen "$hypervisor" "$hypervisorVersion" "$xenhopt"
+ counter=$(($counter + 1))
+ fi
+ done
+
+ if [ -z $found ]; then
+ for hypervisor in $hypervisors; do
+ hypVersion=`basename "$hypervisor" .gz | sed s%xen-%%`
+
+ echo "Found Xen hypervisor $hypVersion, kernel: $kernel" >&2
+
+ write_kernel_entry "$kernelVersion" '' '' "$grub_root_device" \
+ "$kernel" "$currentOpt $xenkopt" '' "$initrd" "$savedefault" '' \
+ Xen "$kernel_dir/$hypervisor" "$hypVersion" "$xenhopt"
+ counter=$(($counter + 1))
+ done
+ fi
+done
+
+for kern in $sortedKernels ; do
+ counter=$(($counter + 1))
+ if test ! x"$howmany" = x"all" ; then
+ if [ $counter -gt $howmany ] ; then
+ break
+ fi
+ fi
+ kernelName=$(basename $kern)
+ kernelVersion=$(echo $kernelName | sed -e 's/vmlinuz//')
+ initrdName=$(FindInitrdName "/boot" "$kernelVersion")
+ initrd=""
+
+ kernel=$kernel_dir/$kernelName
+ if [ -n "$initrdName" ] ; then
+ initrd=$kernel_dir/$initrdName
+ fi
+
+ echo "Found kernel: $kernel" >&2
+
+ if [ "$kernelName" = "vmlinuz" ]; then
+ if [ -L "/boot/$kernelName" ]; then
+ kernelVersion=`readlink -f "/boot/$kernelName"`
+ kernelVersion=$(echo $kernelVersion | sed -e 's/.*vmlinuz-//')
+ kernelVersion="$kernelVersion Default"
+ else
+ kernelVersion="Default"
+ fi
+ fi
+ if [ "$kernelName" = "vmlinuz.old" ]; then
+ if [ -L "/boot/$kernelName" ]; then
+ kernelVersion=`readlink -f "/boot/$kernelName"`
+ kernelVersion=$(echo $kernelVersion | sed -e 's/.*vmlinuz-//')
+ kernelVersion="$kernelVersion Previous"
+ else
+ kernelVersion="Previous"
+ fi
+ fi
+ kernelVersion=$(echo $kernelVersion | sed -e 's/^-//')
+
+ currentOpt=$(get_kernel_opt $kernelVersion)
+
+ do_lockold=$lockold
+ # do not lockold for the first entry
+ [ $counter -eq 1 ] && do_lockold=false
+
+ write_kernel_entry "$kernelVersion" "" "" "$grub_root_device" "$kernel" \
+ "$currentOpt $defoptions" "" "$initrd" "$savedefault" "$do_lockold"
+
+ # insert the alternative boot options
+ if test ! x"$alternative" = x"false" ; then
+ # for each altoptions line do this stuff
+ sed -ne 's/# altoptions=\(.*\)/\1/p' $buffer | while read line; do
+ descr=$(echo $line | sed -ne 's/\(([^)]*)\)[[:space:]]\(.*\)/\1/p')
+ suffix=$(echo $line | sed -ne 's/\(([^)]*)\)[[:space:]]\(.*\)/\2/p')
+
+ test x"$lockalternative" = x"true" && do_lockold=false
+ write_kernel_entry "$kernelVersion" "$descr" "$lockalternative" \
+ "$grub_root_device" "$kernel" "$currentOpt" "$suffix" "$initrd" \
+ "$savedefault" "$do_lockold"
+
+ done
+ fi
+done
+
+memtest86names="memtest86 memtest86+"
+
+if test ! x"$memtest86" = x"false" ; then
+ for name in $memtest86names ; do
+ if test -f "/boot/$name.bin" ; then
+ kernelVersion="$name"
+ kernel="$kernel_dir/$name.bin"
+ currentOpt=
+ initrd=
+
+ echo "Found kernel: $kernel" >&2
+
+ write_kernel_entry "$kernelVersion" "" "" "$grub_root_device" \
+ "$kernel" "$currentOpt" "" "$initrd" "false" ""
+ fi
+ done
+fi
+
+echo $end >> $buffer
+
+echo -n "Updating $menu ... " >&2
+# Insert the new options into the menu
+if ! grep -q "^$start" $menu ; then
+ cat $buffer >> $menu
+ rm -f $buffer
+else
+ umask 077
+ sed -e "/^$start/,/^$end/{
+ /^$start/r $buffer
+ d
+ }
+ " $menu > $menu.new
+ cat $menu.new > $menu
+ rm -f $buffer $menu.new
+fi
+
+# Function to update the default value
+set_default_value() {
+ if [ "$use_grub_set_default" = "true" ] ; then
+ if [ -f /usr/lib/grub-legacy/grub-set-default ] ; then
+ /usr/lib/grub-legacy/grub-set-default $1
+ else
+ grub-set-default $1
+ fi
+ else
+ value="$1"
+ newmenu=$(tempfile)
+ sed -e "s/^[[:blank:]]*default[[:blank:]]*[[:digit:]]*\(.*\)/default ${value}\1/;b" $menu > $newmenu
+ cat $newmenu > $menu
+ rm -f $newmenu
+ unset newmenu
+ fi
+}
+
+#Updating the default number
+if [ "$LET_US_TRY_GRUB_2" = "true" ] && test -f /boot/grub/core.img ; then
+ set_default_value "0"
+elif test -z "$notChangeDefault"; then
+ newDefaultNumberPlusOne=$(grep "^[[:blank:]]*title[[:blank:]]*" $menu | grep -n "${defaultEntry}" | cut -f1 -d ":" | sed -ne "1p")
+ if test -z "$newDefaultNumberPlusOne"; then
+ echo "Previous default entry removed, resetting to 0">&2
+ set_default_value "0"
+ elif test -z "$defaultEntry"; then
+ echo "Value of default value matches no entry, resetting to 0" >&2
+ set_default_value "0"
+ else
+ if test "$newDefaultNumberPlusOne" = "1"; then
+ newDefaultNumber="0"
+ else
+ newDefaultNumber=$(expr $newDefaultNumberPlusOne - 1)
+ fi
+ echo "Updating the default booting kernel">&2
+ set_default_value "$newDefaultNumber"
+ fi
+fi
+
+echo "done" >&2
+echo >&2
diff --git a/debian/legacy/update-grub.ubuntu.patch b/debian/legacy/update-grub.ubuntu.patch
new file mode 100755
index 0000000..6566002
--- /dev/null
+++ b/debian/legacy/update-grub.ubuntu.patch
@@ -0,0 +1,119 @@
+--- update-grub.orig 2011-03-17 14:32:24.000000000 +0000
++++ update-grub 2012-09-06 22:38:51.498737000 +0100
+@@ -218,7 +218,7 @@
+ kopt="root=$linux_root_device ro"
+
+ # Title
+-title="Debian GNU/`uname -s | sed -e s,GNU/,,g`"
++title=$(lsb_release --short --description 2>/dev/null) || title="Ubuntu"
+
+ # should update-grub remember the default entry
+ updatedefaultentry="false"
+@@ -235,7 +235,7 @@
+
+ # additional options to use with the default boot option, but not with the
+ # alternatives
+- defoptions=""
++ defoptions="quiet splash"
+
+ # should grub lock the old kernels
+ lockold="false"
+@@ -247,7 +247,7 @@
+ xenkopt="console=tty0"
+
+ # options to use with the alternative boot options
+- altoptions="(single-user mode) single"
++ altoptions="(recovery mode) single"
+
+ # controls howmany kernels are listed in the config file,
+ # this does not include the alternative kernels
+@@ -262,6 +262,13 @@
+ # stores the command line arguments
+ command_line_arguments=$1
+
++# does this version of grub support the quiet option?
++if [ -f ${grub_dir}/installed-version ] && dpkg --compare-versions `cat ${grub_dir}/installed-version` ge 0.97-11ubuntu4; then
++ supports_quiet=true
++else
++ supports_quiet=false
++fi
++
+ # read user configuration
+ if test -f "/etc/default/grub" ; then
+ . /etc/default/grub
+@@ -504,6 +511,12 @@
+ local hypervisor_options; hypervisor_options=$1; shift
+ fi
+
++ local grub_root_type
++ case "$grub_root_device" in
++ [^A-Za-z0-9]*) grub_root_type='root' ;;
++ *) grub_root_type='uuid' ;;
++ esac
++
+ echo -n "title " >> $buffer
+
+ if [ -n "$hypervisor" ]; then
+@@ -512,7 +525,12 @@
+
+ echo -n "$title" >> $buffer
+ if [ -n "$kernel_version" ]; then
+- echo -n ", kernel $kernel_version" >> $buffer
++ echo -n ", " >> $buffer
++ # memtest86 is not strictly a kernel
++ if ! echo "$kernel_version" | grep -q ^memtest86; then
++ echo -n "kernel " >> $buffer
++ fi
++ echo -n "$kernel_version" >> $buffer
+ fi
+ if [ -n "$recovery_desc" ]; then
+ echo -n " $recovery_desc" >> $buffer
+@@ -528,7 +546,7 @@
+ echo "lock" >> $buffer
+ fi
+
+- echo "root $grub_root_device" >> $buffer
++ echo "$grub_root_type $grub_root_device" >> $buffer
+
+ echo -n "kernel " >> $buffer
+ if [ -n "$hypervisor" ]; then
+@@ -557,6 +575,10 @@
+ echo "$initrd" >> $buffer
+ fi
+
++ if [ ! -n "$recovery_desc" -a x"$supports_quiet" = x"true" ]; then
++ echo "quiet" >> $buffer
++ fi
++
+ if test x"$savedefault" = x"true" ; then
+ echo "savedefault" >> $buffer
+ fi
+@@ -701,7 +723,7 @@
+ echo "## altoption boot targets option" >> $buffer
+ echo "## multiple altoptions lines are allowed" >> $buffer
+ echo "## e.g. altoptions=(extra menu suffix) extra boot options" >> $buffer
+-echo "## altoptions=(single-user) single" >> $buffer
++echo "## altoptions=(recovery) single" >> $buffer
+
+ if ! grep -q "^# altoptions" $menu ; then
+ echo "# altoptions=$altoptions" >> $buffer
+@@ -846,13 +868,18 @@
+ ## heres where we start writing out the kernel entries
+ counter=0
+
++case "$grub_root_device" in
++[^A-Za-z0-9]*) grub_root_type='root' ;;
++*) grub_root_type='uuid' ;;
++esac
++
+ grub2name="${kernel_dir}/grub/core.img"
+ if [ "$LET_US_TRY_GRUB_2" = "true" ] \
+ && test -f /boot/grub/core.img ; then
+ echo "Found GRUB 2: $grub2name" >&2
+ cat >> $buffer << EOF
+ title Chainload into GRUB 2
+-root $grub_root_device
++$grub_root_type $grub_root_device
+ kernel $grub2name
+
+ title `echo ───────────────────────────────────────────────────────────────────── | iconv -f utf-8 -t cp437`
diff --git a/debian/legacy/upgrade-from-grub-legacy b/debian/legacy/upgrade-from-grub-legacy
new file mode 100755
index 0000000..9ed829d
--- /dev/null
+++ b/debian/legacy/upgrade-from-grub-legacy
@@ -0,0 +1,44 @@
+#!/bin/bash -e
+
+if test ! -f /boot/grub/core.img ; then
+ echo -e "\ncore.img doesn't exist, trying to create it.\n" >&2
+ grub-install --no-floppy --grub-setup=/bin/true "(hd0)" > /dev/null
+fi
+
+echo RESET grub-pc/install_devices | debconf-communicate >/dev/null
+
+# Pretend we're upgrading grub-pc. This will make our postinst DTRT.
+DPKG_MAINTSCRIPT_NAME=postinst \
+ DPKG_MAINTSCRIPT_PACKAGE=grub-pc \
+ UPGRADE_FROM_GRUB_LEGACY=1 \
+ /var/lib/dpkg/info/grub-pc.postinst configure dummy-version
+
+if test ! -f /boot/grub/grub.cfg ; then
+ echo -e "\nCalling update-grub to generate grub.cfg\n" >&2
+ update-grub || cat << EOF
+Failed to generate /boot/grub/grub.cfg but GRUB2 has been already installed to
+your MBR.
+THIS MEANS YOU HAVE CURRENTLY AN UNBOOTABLE SYSTEM.
+Either fix the error from update-grub and run $0 again
+or install old grub again and run grub-install from it to have again
+grub-legacy in your MBR.
+EOF
+fi
+
+# These never contain any valuable information, and they aren't useful for
+# boot anymore, since we just overwrote MBR/PBR.
+rm -f /boot/grub/{{xfs,reiserfs,e2fs,fat,jfs,minix}_stage1_5,stage{1,2}}
+# Remove marker file used to indicate that grub-install was run rather than
+# this script. Since stage2 has been removed, we don't need this any more.
+rm -f /boot/grub/grub2-installed
+
+cat << EOF
+
+GRUB Legacy has been removed, but its configuration files have been preserved,
+since this script cannot determine if they contain valuable information. If
+you would like to remove the configuration files as well, use the following
+command:
+
+ rm -f /boot/grub/menu.lst*
+
+EOF
diff --git a/debian/maintscript.in b/debian/maintscript.in
new file mode 100644
index 0000000..199f5b0
--- /dev/null
+++ b/debian/maintscript.in
@@ -0,0 +1 @@
+dir_to_symlink /usr/share/doc/@PACKAGE@ grub-common 1.99-1~
diff --git a/debian/patches/0063-loader-efi-chainloader-Simplify-the-loader-state.patch b/debian/patches/0063-loader-efi-chainloader-Simplify-the-loader-state.patch
new file mode 100644
index 0000000..51a7b68
--- /dev/null
+++ b/debian/patches/0063-loader-efi-chainloader-Simplify-the-loader-state.patch
@@ -0,0 +1,119 @@
+From 9c8e1c85ec9971f2c6bb9a8a7530e94f7dbec14a Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Tue, 5 Apr 2022 10:02:04 +0100
+Subject: loader/efi/chainloader: Simplify the loader state
+
+The chainloader command retains the source buffer and device path passed
+to LoadImage(), requiring the unload hook passed to grub_loader_set() to
+free them. It isn't required to retain this state though - they aren't
+required by StartImage() or anything else in the boot hook, so clean them
+up before grub_cmd_chainloader() finishes.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/loader/efi/chainloader.c | 38 +++++++++++++++++-------------
+ 1 file changed, 21 insertions(+), 17 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 2bd80f4db..d1602c89b 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -44,25 +44,20 @@ GRUB_MOD_LICENSE ("GPLv3+");
+
+ static grub_dl_t my_mod;
+
+-static grub_efi_physical_address_t address;
+-static grub_efi_uintn_t pages;
+-static grub_efi_device_path_t *file_path;
+ static grub_efi_handle_t image_handle;
+-static grub_efi_char16_t *cmdline;
+
+ static grub_err_t
+ grub_chainloader_unload (void)
+ {
++ grub_efi_loaded_image_t *loaded_image;
+ grub_efi_boot_services_t *b;
+
++ loaded_image = grub_efi_get_loaded_image (image_handle);
++ if (loaded_image != NULL)
++ grub_free (loaded_image->load_options);
++
+ b = grub_efi_system_table->boot_services;
+ efi_call_1 (b->unload_image, image_handle);
+- efi_call_2 (b->free_pages, address, pages);
+-
+- grub_free (file_path);
+- grub_free (cmdline);
+- cmdline = 0;
+- file_path = 0;
+
+ grub_dl_unref (my_mod);
+ return GRUB_ERR_NONE;
+@@ -140,7 +135,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+ char *dir_start;
+ char *dir_end;
+ grub_size_t size;
+- grub_efi_device_path_t *d;
++ grub_efi_device_path_t *d, *file_path;
+
+ dir_start = grub_strchr (filename, ')');
+ if (! dir_start)
+@@ -222,11 +217,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
+ grub_device_t dev = 0;
+- grub_efi_device_path_t *dp = 0;
++ grub_efi_device_path_t *dp = NULL, *file_path = NULL;
+ grub_efi_loaded_image_t *loaded_image;
+ char *filename;
+ void *boot_image = 0;
+ grub_efi_handle_t dev_handle = 0;
++ grub_efi_physical_address_t address = 0;
++ grub_efi_uintn_t pages = 0;
++ grub_efi_char16_t *cmdline = NULL;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -234,11 +232,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+
+ grub_dl_ref (my_mod);
+
+- /* Initialize some global variables. */
+- address = 0;
+- image_handle = 0;
+- file_path = 0;
+-
+ b = grub_efi_system_table->boot_services;
+
+ file = grub_file_open (filename, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE);
+@@ -408,6 +401,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ grub_file_close (file);
+ grub_device_close (dev);
+
++ /* We're finished with the source image buffer and file path now. */
++ efi_call_2 (b->free_pages, address, pages);
++ grub_free (file_path);
++
+ grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+ return 0;
+
+@@ -419,11 +416,18 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ if (file)
+ grub_file_close (file);
+
++ grub_free (cmdline);
+ grub_free (file_path);
+
+ if (address)
+ efi_call_2 (b->free_pages, address, pages);
+
++ if (image_handle != NULL)
++ {
++ efi_call_1 (b->unload_image, image_handle);
++ image_handle = NULL;
++ }
++
+ grub_dl_unref (my_mod);
+
+ return grub_errno;
diff --git a/debian/patches/0064-commands-boot-Add-API-to-pass-context-to-loader.patch b/debian/patches/0064-commands-boot-Add-API-to-pass-context-to-loader.patch
new file mode 100644
index 0000000..47caba2
--- /dev/null
+++ b/debian/patches/0064-commands-boot-Add-API-to-pass-context-to-loader.patch
@@ -0,0 +1,158 @@
+From bb35dbb9bf213bc9dde9a5a653e93b4c4d2bbf22 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Fri, 29 Apr 2022 21:16:02 +0100
+Subject: commands/boot: Add API to pass context to loader
+
+Loaders rely on global variables for saving context which is consumed
+in the boot hook and freed in the unload hook. In the case where a loader
+command is executed twice, calling grub_loader_set a second time executes
+the unload hook, but in some cases this runs when the loader's global
+context has already been updated, resulting in the updated context being
+freed and potential use-after-free bugs when the boot hook is subsequently
+called.
+
+This adds a new API (grub_loader_set_ex) which allows a loader to specify
+context that is passed to its boot and unload hooks. This is an alternative
+to requiring that loaders call grub_loader_unset before mutating their
+global context.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3)
+---
+ grub-core/commands/boot.c | 66 ++++++++++++++++++++++++++++++++++-----
+ include/grub/loader.h | 5 +++
+ 2 files changed, 63 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c
+index bbca81e94..53691a62d 100644
+--- a/grub-core/commands/boot.c
++++ b/grub-core/commands/boot.c
+@@ -27,10 +27,20 @@
+
+ GRUB_MOD_LICENSE ("GPLv3+");
+
+-static grub_err_t (*grub_loader_boot_func) (void);
+-static grub_err_t (*grub_loader_unload_func) (void);
++static grub_err_t (*grub_loader_boot_func) (void *);
++static grub_err_t (*grub_loader_unload_func) (void *);
++static void *grub_loader_context;
+ static int grub_loader_flags;
+
++struct grub_simple_loader_hooks
++{
++ grub_err_t (*boot) (void);
++ grub_err_t (*unload) (void);
++};
++
++/* Don't heap allocate this to avoid making grub_loader_set fallible. */
++static struct grub_simple_loader_hooks simple_loader_hooks;
++
+ struct grub_preboot
+ {
+ grub_err_t (*preboot_func) (int);
+@@ -44,6 +54,29 @@ static int grub_loader_loaded;
+ static struct grub_preboot *preboots_head = 0,
+ *preboots_tail = 0;
+
++static grub_err_t
++grub_simple_boot_hook (void *context)
++{
++ struct grub_simple_loader_hooks *hooks;
++
++ hooks = (struct grub_simple_loader_hooks *) context;
++ return hooks->boot ();
++}
++
++static grub_err_t
++grub_simple_unload_hook (void *context)
++{
++ struct grub_simple_loader_hooks *hooks;
++ grub_err_t ret;
++
++ hooks = (struct grub_simple_loader_hooks *) context;
++
++ ret = hooks->unload ();
++ grub_memset (hooks, 0, sizeof (*hooks));
++
++ return ret;
++}
++
+ int
+ grub_loader_is_loaded (void)
+ {
+@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
+ }
+
+ void
+-grub_loader_set (grub_err_t (*boot) (void),
+- grub_err_t (*unload) (void),
+- int flags)
++grub_loader_set_ex (grub_err_t (*boot) (void *),
++ grub_err_t (*unload) (void *),
++ void *context,
++ int flags)
+ {
+ if (grub_loader_loaded && grub_loader_unload_func)
+- grub_loader_unload_func ();
++ grub_loader_unload_func (grub_loader_context);
+
+ grub_loader_boot_func = boot;
+ grub_loader_unload_func = unload;
++ grub_loader_context = context;
+ grub_loader_flags = flags;
+
+ grub_loader_loaded = 1;
+ }
+
++void
++grub_loader_set (grub_err_t (*boot) (void),
++ grub_err_t (*unload) (void),
++ int flags)
++{
++ grub_loader_set_ex (grub_simple_boot_hook,
++ grub_simple_unload_hook,
++ &simple_loader_hooks,
++ flags);
++
++ simple_loader_hooks.boot = boot;
++ simple_loader_hooks.unload = unload;
++}
++
+ void
+ grub_loader_unset(void)
+ {
+ if (grub_loader_loaded && grub_loader_unload_func)
+- grub_loader_unload_func ();
++ grub_loader_unload_func (grub_loader_context);
+
+ grub_loader_boot_func = 0;
+ grub_loader_unload_func = 0;
++ grub_loader_context = 0;
+
+ grub_loader_loaded = 0;
+ }
+@@ -158,7 +208,7 @@ grub_loader_boot (void)
+ return err;
+ }
+ }
+- err = (grub_loader_boot_func) ();
++ err = (grub_loader_boot_func) (grub_loader_context);
+
+ for (cur = preboots_tail; cur; cur = cur->prev)
+ if (! err)
+diff --git a/include/grub/loader.h b/include/grub/loader.h
+index b20864282..1846fa6c5 100644
+--- a/include/grub/loader.h
++++ b/include/grub/loader.h
+@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
+ grub_err_t (*unload) (void),
+ int flags);
+
++void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *),
++ grub_err_t (*unload) (void *),
++ void *context,
++ int flags);
++
+ /* Unset current loader, if any. */
+ void EXPORT_FUNC (grub_loader_unset) (void);
+
diff --git a/debian/patches/0065-loader-efi-chainloader-Use-grub_loader_set_ex.patch b/debian/patches/0065-loader-efi-chainloader-Use-grub_loader_set_ex.patch
new file mode 100644
index 0000000..4a4a0e7
--- /dev/null
+++ b/debian/patches/0065-loader-efi-chainloader-Use-grub_loader_set_ex.patch
@@ -0,0 +1,75 @@
+From 19b4f19cfea30655032c978e228d78e056f55f1a Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Tue, 5 Apr 2022 11:48:58 +0100
+Subject: loader/efi/chainloader: Use grub_loader_set_ex()
+
+This ports the EFI chainloader to use grub_loader_set_ex() in order to fix
+a use-after-free bug that occurs when grub_cmd_chainloader() is executed
+more than once before a boot attempt is performed.
+
+Fixes: CVE-2022-28736
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/loader/efi/chainloader.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index d1602c89b..7557eb269 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -44,11 +44,10 @@ GRUB_MOD_LICENSE ("GPLv3+");
+
+ static grub_dl_t my_mod;
+
+-static grub_efi_handle_t image_handle;
+-
+ static grub_err_t
+-grub_chainloader_unload (void)
++grub_chainloader_unload (void *context)
+ {
++ grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
+ grub_efi_loaded_image_t *loaded_image;
+ grub_efi_boot_services_t *b;
+
+@@ -64,8 +63,9 @@ grub_chainloader_unload (void)
+ }
+
+ static grub_err_t
+-grub_chainloader_boot (void)
++grub_chainloader_boot (void *context)
+ {
++ grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
+ grub_efi_boot_services_t *b;
+ grub_efi_status_t status;
+ grub_efi_uintn_t exit_data_size;
+@@ -225,6 +225,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ grub_efi_physical_address_t address = 0;
+ grub_efi_uintn_t pages = 0;
+ grub_efi_char16_t *cmdline = NULL;
++ grub_efi_handle_t image_handle = NULL;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -405,7 +406,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ efi_call_2 (b->free_pages, address, pages);
+ grub_free (file_path);
+
+- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
++ grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0);
+ return 0;
+
+ fail:
+@@ -423,10 +424,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ efi_call_2 (b->free_pages, address, pages);
+
+ if (image_handle != NULL)
+- {
+- efi_call_1 (b->unload_image, image_handle);
+- image_handle = NULL;
+- }
++ efi_call_1 (b->unload_image, image_handle);
+
+ grub_dl_unref (my_mod);
+
diff --git a/debian/patches/0066-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch b/debian/patches/0066-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
new file mode 100644
index 0000000..18ecc25
--- /dev/null
+++ b/debian/patches/0066-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
@@ -0,0 +1,99 @@
+From 24e6d59ac676791507ff5267bf3bef6cbaff6aef Mon Sep 17 00:00:00 2001
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Thu, 2 Dec 2021 15:03:53 +0100
+Subject: kern/efi/sb: Reject non-kernel files in the shim_lock verifier
+
+We must not allow other verifiers to pass things like the GRUB modules.
+Instead of maintaining a blocklist, maintain an allowlist of things
+that we do not care about.
+
+This allowlist really should be made reusable, and shared by the
+lockdown verifier, but this is the minimal patch addressing
+security concerns where the TPM verifier was able to mark modules
+as verified (or the OpenPGP verifier for that matter), when it
+should not do so on shim-powered secure boot systems.
+
+Fixes: CVE-2022-28735
+
+Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++---
+ include/grub/verify.h | 1 +
+ 2 files changed, 37 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
+index c52ec6226..89c4bb3fd 100644
+--- a/grub-core/kern/efi/sb.c
++++ b/grub-core/kern/efi/sb.c
+@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+ void **context __attribute__ ((unused)),
+ enum grub_verify_flags *flags)
+ {
+- *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
++ *flags = GRUB_VERIFY_FLAGS_NONE;
+
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
++ /* Files we check. */
+ case GRUB_FILE_TYPE_LINUX_KERNEL:
+ case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+ case GRUB_FILE_TYPE_BSD_KERNEL:
+@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+ case GRUB_FILE_TYPE_PLAN9_KERNEL:
+ case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
+ *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
++ return GRUB_ERR_NONE;
+
+- /* Fall through. */
++ /* Files that do not affect secureboot state. */
++ case GRUB_FILE_TYPE_NONE:
++ case GRUB_FILE_TYPE_LOOPBACK:
++ case GRUB_FILE_TYPE_LINUX_INITRD:
++ case GRUB_FILE_TYPE_OPENBSD_RAMDISK:
++ case GRUB_FILE_TYPE_XNU_RAMDISK:
++ case GRUB_FILE_TYPE_SIGNATURE:
++ case GRUB_FILE_TYPE_PUBLIC_KEY:
++ case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST:
++ case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
++ case GRUB_FILE_TYPE_TESTLOAD:
++ case GRUB_FILE_TYPE_GET_SIZE:
++ case GRUB_FILE_TYPE_FONT:
++ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
++ case GRUB_FILE_TYPE_CAT:
++ case GRUB_FILE_TYPE_HEXCAT:
++ case GRUB_FILE_TYPE_CMP:
++ case GRUB_FILE_TYPE_HASHLIST:
++ case GRUB_FILE_TYPE_TO_HASH:
++ case GRUB_FILE_TYPE_KEYBOARD_LAYOUT:
++ case GRUB_FILE_TYPE_PIXMAP:
++ case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
++ case GRUB_FILE_TYPE_CONFIG:
++ case GRUB_FILE_TYPE_THEME:
++ case GRUB_FILE_TYPE_GETTEXT_CATALOG:
++ case GRUB_FILE_TYPE_FS_SEARCH:
++ case GRUB_FILE_TYPE_LOADENV:
++ case GRUB_FILE_TYPE_SAVEENV:
++ case GRUB_FILE_TYPE_VERIFY_SIGNATURE:
++ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
++ return GRUB_ERR_NONE;
+
++ /* Other files. */
+ default:
+- return GRUB_ERR_NONE;
++ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy"));
+ }
+ }
+
+diff --git a/include/grub/verify.h b/include/grub/verify.h
+index 6fde244fc..67448165f 100644
+--- a/include/grub/verify.h
++++ b/include/grub/verify.h
+@@ -24,6 +24,7 @@
+
+ enum grub_verify_flags
+ {
++ GRUB_VERIFY_FLAGS_NONE = 0,
+ GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1,
+ GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2,
+ /* Defer verification to another authority. */
diff --git a/debian/patches/0067-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch b/debian/patches/0067-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
new file mode 100644
index 0000000..d319507
--- /dev/null
+++ b/debian/patches/0067-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
@@ -0,0 +1,37 @@
+From c15fa5fb039cd5062dfa02a03efd924422c4a8ed Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Fri, 25 Jun 2021 02:19:05 +1000
+Subject: kern/file: Do not leak device_name on error in grub_file_open()
+
+If we have an error in grub_file_open() before we free device_name, we
+will leak it.
+
+Free device_name in the error path and null out the pointer in the good
+path once we free it there.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/file.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
+index 58454458c..ffdcaba05 100644
+--- a/grub-core/kern/file.c
++++ b/grub-core/kern/file.c
+@@ -79,6 +79,7 @@ grub_file_open (const char *name, enum grub_file_type type)
+
+ device = grub_device_open (device_name);
+ grub_free (device_name);
++ device_name = NULL;
+ if (! device)
+ goto fail;
+
+@@ -131,6 +132,7 @@ grub_file_open (const char *name, enum grub_file_type type)
+ return file;
+
+ fail:
++ grub_free (device_name);
+ if (device)
+ grub_device_close (device);
+
diff --git a/debian/patches/0068-video-readers-png-Abort-sooner-if-a-read-operation-f.patch b/debian/patches/0068-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
new file mode 100644
index 0000000..58e6e50
--- /dev/null
+++ b/debian/patches/0068-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
@@ -0,0 +1,197 @@
+From 907f100c841f39e37e4801f726f6b47c2aa9191f Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 14:02:55 +1000
+Subject: video/readers/png: Abort sooner if a read operation fails
+
+Fuzzing revealed some inputs that were taking a long time, potentially
+forever, because they did not bail quickly upon encountering an I/O error.
+
+Try to catch I/O errors sooner and bail out.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++-----
+ 1 file changed, 47 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 0157ff742..e2a6b1cf3 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -142,6 +142,7 @@ static grub_uint8_t
+ grub_png_get_byte (struct grub_png_data *data)
+ {
+ grub_uint8_t r;
++ grub_ssize_t bytes_read = 0;
+
+ if ((data->inside_idat) && (data->idat_remain == 0))
+ {
+@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data)
+ }
+
+ r = 0;
+- grub_file_read (data->file, &r, 1);
++ bytes_read = grub_file_read (data->file, &r, 1);
++
++ if (bytes_read != 1)
++ {
++ grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "png: unexpected end of data");
++ return 0;
++ }
+
+ if (data->inside_idat)
+ data->idat_remain--;
+@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data,
+ if (len == 0)
+ return GRUB_ERR_NONE;
+
+- for (i = 0; 3 * i < len && i < 256; i++)
++ grub_errno = GRUB_ERR_NONE;
++ for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++)
+ for (j = 0; j < 3; j++)
+ data->palette[i][j] = grub_png_get_byte (data);
+- for (i *= 3; i < len; i++)
++ for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++)
+ grub_png_get_byte (data);
+
+ grub_png_get_dword (data);
+
+- return GRUB_ERR_NONE;
++ return grub_errno;
+ }
+
+ static grub_err_t
+@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
+
+ color_bits = grub_png_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ data->is_16bit = (color_bits == 16);
+
+ color_type = grub_png_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ /* According to PNG spec, no other types are valid. */
+ if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
+@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data)
+ if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "png: compression method not supported");
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "png: filter method not supported");
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "png: interlace method not supported");
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ /* Skip crc checksum. */
+ grub_png_get_dword (data);
+@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
+ int code, i;
+
+ code = 0;
+- for (i = 0; i < ht->max_length; i++)
++ for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++)
+ {
+ code = (code << 1) + grub_png_get_bits (data, 1);
+ if (code < ht->maxval[i])
+@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
+ grub_uint8_t lens[DEFLATE_HCLEN_MAX];
+
+ nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
+ (nb > DEFLATE_HCLEN_MAX))
+@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
+ data->dist_offset);
+
+ prev = 0;
+- for (i = 0; i < nl + nd; i++)
++ for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++)
+ {
+ int n, code;
+ struct huff_table *ht;
+@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
+ len = cplens[n];
+ if (cplext[n])
+ len += grub_png_get_bits (data, cplext[n]);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ n = grub_png_get_huff_code (data, &data->dist_table);
+ dist = cpdist[n];
+ if (cpdext[n])
+ dist += grub_png_get_bits (data, cpdext[n]);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ pos = data->wp - dist;
+ if (pos < 0)
+ pos += WSIZE;
+
+- while (len > 0)
++ while (len > 0 && grub_errno == GRUB_ERR_NONE)
+ {
+ data->slide[data->wp] = data->slide[pos];
+ grub_png_output_byte (data, data->slide[data->wp]);
+@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
+ int final;
+
+ cmf = grub_png_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ flg = grub_png_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ if ((cmf & 0xF) != Z_DEFLATED)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
+ int block_type;
+
+ final = grub_png_get_bits (data, 1);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ block_type = grub_png_get_bits (data, 2);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ switch (block_type)
+ {
+@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data)
+ grub_png_get_byte (data);
+ grub_png_get_byte (data);
+
+- for (i = 0; i < len; i++)
++ for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++)
+ grub_png_output_byte (data, grub_png_get_byte (data));
+
+ break;
+@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data)
+
+ len = grub_png_get_dword (data);
+ type = grub_png_get_dword (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ break;
+ data->next_offset = data->file->offset + len + 4;
+
+ switch (type)
diff --git a/debian/patches/0069-video-readers-png-Refuse-to-handle-multiple-image-he.patch b/debian/patches/0069-video-readers-png-Refuse-to-handle-multiple-image-he.patch
new file mode 100644
index 0000000..1c0aba1
--- /dev/null
+++ b/debian/patches/0069-video-readers-png-Refuse-to-handle-multiple-image-he.patch
@@ -0,0 +1,27 @@
+From 5e496e28b3c76666c98b737153f9b0c2bedf489d Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 14:13:40 +1000
+Subject: video/readers/png: Refuse to handle multiple image headers
+
+This causes the bitmap to be leaked. Do not permit multiple image headers.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index e2a6b1cf3..8955b8ecf 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data)
+ int color_bits;
+ enum grub_video_blit_format blt;
+
++ if (data->image_width || data->image_height)
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found");
++
+ data->image_width = grub_png_get_dword (data);
+ data->image_height = grub_png_get_dword (data);
+
diff --git a/debian/patches/0070-video-readers-png-Drop-greyscale-support-to-fix-heap.patch b/debian/patches/0070-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
new file mode 100644
index 0000000..08c33f8
--- /dev/null
+++ b/debian/patches/0070-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
@@ -0,0 +1,168 @@
+From 558c69b5d36d14d55bff21e6570205fe73a02ca2 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 18:51:35 +1000
+Subject: video/readers/png: Drop greyscale support to fix heap out-of-bounds
+ write
+
+A 16-bit greyscale PNG without alpha is processed in the following loop:
+
+ for (i = 0; i < (data->image_width * data->image_height);
+ i++, d1 += 4, d2 += 2)
+ {
+ d1[R3] = d2[1];
+ d1[G3] = d2[1];
+ d1[B3] = d2[1];
+ }
+
+The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration,
+but there are only 3 bytes allocated for storage. This means that image
+data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes
+out of every 4 following the end of the image.
+
+This has existed since greyscale support was added in 2013 in commit
+3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale).
+
+Saving starfield.png as a 16-bit greyscale image without alpha in the gimp
+and attempting to load it causes grub-emu to crash - I don't think this code
+has ever worked.
+
+Delete all PNG greyscale support.
+
+Fixes: CVE-2021-3695
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 87 +++--------------------------------
+ 1 file changed, 7 insertions(+), 80 deletions(-)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 8955b8ecf..a3161e25b 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -100,7 +100,7 @@ struct grub_png_data
+
+ unsigned image_width, image_height;
+ int bpp, is_16bit;
+- int raw_bytes, is_gray, is_alpha, is_palette;
++ int raw_bytes, is_alpha, is_palette;
+ int row_bytes, color_bits;
+ grub_uint8_t *image_data;
+
+@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
+ data->bpp = 3;
+ else
+ {
+- data->is_gray = 1;
+- data->bpp = 1;
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "png: color type not supported");
+ }
+
+ if ((color_bits != 8) && (color_bits != 16)
+ && (color_bits != 4
+- || !(data->is_gray || data->is_palette)))
++ || !data->is_palette))
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "png: bit depth must be 8 or 16");
+
+@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
+ }
+
+ #ifndef GRUB_CPU_WORDS_BIGENDIAN
+- if (data->is_16bit || data->is_gray || data->is_palette)
++ if (data->is_16bit || data->is_palette)
+ #endif
+ {
+ data->image_data = grub_calloc (data->image_height, data->row_bytes);
+@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data)
+ int shift;
+ int mask = (1 << data->color_bits) - 1;
+ unsigned j;
+- if (data->is_gray)
+- {
+- /* Generic formula is
+- (0xff * i) / ((1U << data->color_bits) - 1)
+- but for allowed bit depth of 1, 2 and for it's
+- equivalent to
+- (0xff / ((1U << data->color_bits) - 1)) * i
+- Precompute the multipliers to avoid division.
+- */
+-
+- const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 };
+- for (i = 0; i < (1U << data->color_bits); i++)
+- {
+- grub_uint8_t col = multipliers[data->color_bits] * i;
+- palette[i][0] = col;
+- palette[i][1] = col;
+- palette[i][2] = col;
+- }
+- }
+- else
+- grub_memcpy (palette, data->palette, 3 << data->color_bits);
++
++ grub_memcpy (palette, data->palette, 3 << data->color_bits);
+ d1c = d1;
+ d2c = d2;
+ for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3,
+@@ -956,60 +937,6 @@ grub_png_convert_image (struct grub_png_data *data)
+ }
+ return;
+ }
+-
+- if (data->is_gray)
+- {
+- switch (data->bpp)
+- {
+- case 4:
+- /* 16-bit gray with alpha. */
+- for (i = 0; i < (data->image_width * data->image_height);
+- i++, d1 += 4, d2 += 4)
+- {
+- d1[R4] = d2[3];
+- d1[G4] = d2[3];
+- d1[B4] = d2[3];
+- d1[A4] = d2[1];
+- }
+- break;
+- case 2:
+- if (data->is_16bit)
+- /* 16-bit gray without alpha. */
+- {
+- for (i = 0; i < (data->image_width * data->image_height);
+- i++, d1 += 4, d2 += 2)
+- {
+- d1[R3] = d2[1];
+- d1[G3] = d2[1];
+- d1[B3] = d2[1];
+- }
+- }
+- else
+- /* 8-bit gray with alpha. */
+- {
+- for (i = 0; i < (data->image_width * data->image_height);
+- i++, d1 += 4, d2 += 2)
+- {
+- d1[R4] = d2[1];
+- d1[G4] = d2[1];
+- d1[B4] = d2[1];
+- d1[A4] = d2[0];
+- }
+- }
+- break;
+- /* 8-bit gray without alpha. */
+- case 1:
+- for (i = 0; i < (data->image_width * data->image_height);
+- i++, d1 += 3, d2++)
+- {
+- d1[R3] = d2[0];
+- d1[G3] = d2[0];
+- d1[B3] = d2[0];
+- }
+- break;
+- }
+- return;
+- }
+
+ {
+ /* Only copy the upper 8 bit. */
diff --git a/debian/patches/0071-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch b/debian/patches/0071-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
new file mode 100644
index 0000000..7f73935
--- /dev/null
+++ b/debian/patches/0071-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
@@ -0,0 +1,38 @@
+From 21e3b255f91d9b7711f8346f1e4acf8cc19bf4fb Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 23:25:07 +1000
+Subject: video/readers/png: Avoid heap OOB R/W inserting huff table items
+
+In fuzzing we observed crashes where a code would attempt to be inserted
+into a huffman table before the start, leading to a set of heap OOB reads
+and writes as table entries with negative indices were shifted around and
+the new code written in.
+
+Catch the case where we would underflow the array and bail.
+
+Fixes: CVE-2021-3696
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index a3161e25b..d7ed5aa6c 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
+ for (i = len; i < ht->max_length; i++)
+ n += ht->maxval[i];
+
++ if (n > ht->num_values)
++ {
++ grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "png: out of range inserting huffman table item");
++ return;
++ }
++
+ for (i = 0; i < n; i++)
+ ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
+
diff --git a/debian/patches/0072-video-readers-png-Sanity-check-some-huffman-codes.patch b/debian/patches/0072-video-readers-png-Sanity-check-some-huffman-codes.patch
new file mode 100644
index 0000000..b355584
--- /dev/null
+++ b/debian/patches/0072-video-readers-png-Sanity-check-some-huffman-codes.patch
@@ -0,0 +1,39 @@
+From e1c0a986e39ab93954436bcf6e6a9a7ea465e4e7 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 19:19:11 +1000
+Subject: video/readers/png: Sanity check some huffman codes
+
+ASAN picked up two OOB global reads: we weren't checking if some code
+values fit within the cplens or cpdext arrays. Check and throw an error
+if not.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index d7ed5aa6c..7f2ba7849 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
+ int len, dist, pos;
+
+ n -= 257;
++ if (((unsigned int) n) >= ARRAY_SIZE (cplens))
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "png: invalid huff code");
+ len = cplens[n];
+ if (cplext[n])
+ len += grub_png_get_bits (data, cplext[n]);
+@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
+ return grub_errno;
+
+ n = grub_png_get_huff_code (data, &data->dist_table);
++ if (((unsigned int) n) >= ARRAY_SIZE (cpdist))
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "png: invalid huff code");
+ dist = cpdist[n];
+ if (cpdext[n])
+ dist += grub_png_get_bits (data, cpdext[n]);
diff --git a/debian/patches/0073-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch b/debian/patches/0073-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
new file mode 100644
index 0000000..1f5b558
--- /dev/null
+++ b/debian/patches/0073-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
@@ -0,0 +1,254 @@
+From 40be99c5f8162887d1922fb9428b39de4cdad3af Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 28 Jun 2021 14:16:14 +1000
+Subject: video/readers/jpeg: Abort sooner if a read operation fails
+
+Fuzzing revealed some inputs that were taking a long time, potentially
+forever, because they did not bail quickly upon encountering an I/O error.
+
+Try to catch I/O errors sooner and bail out.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 86 +++++++++++++++++++++++++++-------
+ 1 file changed, 70 insertions(+), 16 deletions(-)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index e31602f76..10225abd5 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -109,9 +109,17 @@ static grub_uint8_t
+ grub_jpeg_get_byte (struct grub_jpeg_data *data)
+ {
+ grub_uint8_t r;
++ grub_ssize_t bytes_read;
+
+ r = 0;
+- grub_file_read (data->file, &r, 1);
++ bytes_read = grub_file_read (data->file, &r, 1);
++
++ if (bytes_read != 1)
++ {
++ grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: unexpected end of data");
++ return 0;
++ }
+
+ return r;
+ }
+@@ -120,9 +128,17 @@ static grub_uint16_t
+ grub_jpeg_get_word (struct grub_jpeg_data *data)
+ {
+ grub_uint16_t r;
++ grub_ssize_t bytes_read;
+
+ r = 0;
+- grub_file_read (data->file, &r, sizeof (grub_uint16_t));
++ bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t));
++
++ if (bytes_read != sizeof (grub_uint16_t))
++ {
++ grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: unexpected end of data");
++ return 0;
++ }
+
+ return grub_be_to_cpu16 (r);
+ }
+@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
+ if (data->bit_mask == 0)
+ {
+ data->bit_save = grub_jpeg_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE) {
++ grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: file read error");
++ return 0;
++ }
+ if (data->bit_save == JPEG_ESC_CHAR)
+ {
+ if (grub_jpeg_get_byte (data) != 0)
+@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
+ "jpeg: invalid 0xFF in data stream");
+ return 0;
+ }
++ if (grub_errno != GRUB_ERR_NONE)
++ {
++ grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error");
++ return 0;
++ }
+ }
+ data->bit_mask = 0x80;
+ }
+@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
+ return 0;
+
+ msb = value = grub_jpeg_get_bit (data);
+- for (i = 1; i < num; i++)
++ for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++)
+ value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
+ if (!msb)
+ value += 1 - (1 << num);
+@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
+ while (data->file->offset + sizeof (count) + 1 <= next_marker)
+ {
+ id = grub_jpeg_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ ac = (id >> 4) & 1;
+ id &= 0xF;
+ if (id > 1)
+@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
+
+ next_marker = data->file->offset;
+ next_marker += grub_jpeg_get_word (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+
+ if (next_marker > data->file->size)
+ {
+@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
+ <= next_marker)
+ {
+ id = grub_jpeg_get_byte (data);
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ if (id >= 0x10) /* Upper 4-bit is precision. */
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "jpeg: only 8-bit precision is supported");
+@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
+ next_marker = data->file->offset;
+ next_marker += grub_jpeg_get_word (data);
+
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
++
+ if (grub_jpeg_get_byte (data) != 8)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "jpeg: only 8-bit precision is supported");
+@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
+
+ ss = grub_jpeg_get_byte (data); /* Sampling factor. */
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ if (!id)
+ {
+ grub_uint8_t vs, hs;
+@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du)
+ }
+ }
+
+-static void
++static grub_err_t
+ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+ {
+ int h1, h2, qt;
+@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+ data->dc_value[id] +=
+ grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
+
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
++
+ du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
+ pos = 1;
+ while (pos < ARRAY_SIZE (data->quan_table[qt]))
+@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+ num >>= 4;
+ pos += num;
+
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
++
+ if (pos >= ARRAY_SIZE (jpeg_zigzag_order))
+ {
+- grub_error (GRUB_ERR_BAD_FILE_TYPE,
+- "jpeg: invalid position in zigzag order!?");
+- return;
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: invalid position in zigzag order!?");
+ }
+
+ du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
+@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+ }
+
+ grub_jpeg_idct_transform (du);
++ return GRUB_ERR_NONE;
+ }
+
+ static void
+@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+ data_offset += grub_jpeg_get_word (data);
+
+ cc = grub_jpeg_get_byte (data);
+-
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ if (cc != 3 && cc != 1)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "jpeg: component count must be 1 or 3");
+@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+ id = grub_jpeg_get_byte (data) - 1;
+ if ((id < 0) || (id >= 3))
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
+-
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ ht = grub_jpeg_get_byte (data);
+ data->comp_index[id][1] = (ht >> 4);
+ data->comp_index[id][2] = (ht & 0xF) + 2;
+@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+ if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) ||
+ (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3))
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index");
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ }
+
+ grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */
+ grub_jpeg_get_word (data);
+-
++ if (grub_errno != GRUB_ERR_NONE)
++ return grub_errno;
+ if (data->file->offset != data_offset)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
+
+@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ {
+ unsigned c1, vb, hb, nr1, nc1;
+ int rst = data->dri;
++ grub_err_t err = GRUB_ERR_NONE;
+
+ vb = 8 << data->log_vs;
+ hb = 8 << data->log_hs;
+@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+
+ for (r2 = 0; r2 < (1U << data->log_vs); r2++)
+ for (c2 = 0; c2 < (1U << data->log_hs); c2++)
+- grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
++ {
++ err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
++ if (err != GRUB_ERR_NONE)
++ return err;
++ }
+
+ if (data->color_components >= 3)
+ {
+- grub_jpeg_decode_du (data, 1, data->cbdu);
+- grub_jpeg_decode_du (data, 2, data->crdu);
++ err = grub_jpeg_decode_du (data, 1, data->cbdu);
++ if (err != GRUB_ERR_NONE)
++ return err;
++ err = grub_jpeg_decode_du (data, 2, data->crdu);
++ if (err != GRUB_ERR_NONE)
++ return err;
+ }
+
+- if (grub_errno)
+- return grub_errno;
+-
+ nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
+ nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
+
diff --git a/debian/patches/0074-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch b/debian/patches/0074-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
new file mode 100644
index 0000000..c4228f9
--- /dev/null
+++ b/debian/patches/0074-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
@@ -0,0 +1,28 @@
+From 610c5986058312cfc0375fc04f88fcc116bdd043 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 28 Jun 2021 14:16:58 +1000
+Subject: video/readers/jpeg: Do not reallocate a given huff table
+
+Fix a memory leak where an invalid file could cause us to reallocate
+memory for a huffman table we had already allocated memory for.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index 10225abd5..caa211f06 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
+ n += count[i];
+
+ id += ac * 2;
++ if (data->huff_value[id] != NULL)
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: attempt to reallocate huffman table");
+ data->huff_value[id] = grub_malloc (n);
+ if (grub_errno)
+ return grub_errno;
diff --git a/debian/patches/0075-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch b/debian/patches/0075-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
new file mode 100644
index 0000000..07fd802
--- /dev/null
+++ b/debian/patches/0075-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
@@ -0,0 +1,42 @@
+From 9286f0009b922571c247012e699c3ed5f6e918bc Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 28 Jun 2021 14:25:17 +1000
+Subject: video/readers/jpeg: Refuse to handle multiple start of streams
+
+An invalid file could contain multiple start of stream blocks, which
+would cause us to reallocate and leak our bitmap. Refuse to handle
+multiple start of streams.
+
+Additionally, fix a grub_error() call formatting.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index caa211f06..1df1171d7 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+ if (data->file->offset != data_offset)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
+
++ if (*data->bitmap)
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks");
++
+ if (grub_video_bitmap_create (data->bitmap, data->image_width,
+ data->image_height,
+ GRUB_VIDEO_BLIT_FORMAT_RGB_888))
+@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs);
+
+ if (data->bitmap_ptr == NULL)
+- return grub_error(GRUB_ERR_BAD_FILE_TYPE,
+- "jpeg: attempted to decode data before start of stream");
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: attempted to decode data before start of stream");
+
+ for (; data->r1 < nr1 && (!data->dri || rst);
+ data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
diff --git a/debian/patches/0076-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch b/debian/patches/0076-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
new file mode 100644
index 0000000..b292cbc
--- /dev/null
+++ b/debian/patches/0076-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
@@ -0,0 +1,73 @@
+From a10c2350a766f9b315735931a49499a7e2c77bf3 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Wed, 7 Jul 2021 15:38:19 +1000
+Subject: video/readers/jpeg: Block int underflow -> wild pointer write
+
+Certain 1 px wide images caused a wild pointer write in
+grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(),
+we have the following loop:
+
+for (; data->r1 < nr1 && (!data->dri || rst);
+ data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
+
+We did not check if vb * width >= hb * nc1.
+
+On a 64-bit platform, if that turns out to be negative, it will underflow,
+be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so
+we see data->bitmap_ptr jump, e.g.:
+
+0x6180_0000_0480 to
+0x6181_0000_0498
+ ^
+ ~--- carry has occurred and this pointer is now far away from
+ any object.
+
+On a 32-bit platform, it will decrement the pointer, creating a pointer
+that won't crash but will overwrite random data.
+
+Catch the underflow and error out.
+
+Fixes: CVE-2021-3697
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index 1df1171d7..97a533b24 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -23,6 +23,7 @@
+ #include <grub/mm.h>
+ #include <grub/misc.h>
+ #include <grub/bufio.h>
++#include <grub/safemath.h>
+
+ GRUB_MOD_LICENSE ("GPLv3+");
+
+@@ -693,6 +694,7 @@ static grub_err_t
+ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ {
+ unsigned c1, vb, hb, nr1, nc1;
++ unsigned stride_a, stride_b, stride;
+ int rst = data->dri;
+ grub_err_t err = GRUB_ERR_NONE;
+
+@@ -705,8 +707,14 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "jpeg: attempted to decode data before start of stream");
+
++ if (grub_mul(vb, data->image_width, &stride_a) ||
++ grub_mul(hb, nc1, &stride_b) ||
++ grub_sub(stride_a, stride_b, &stride))
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++ "jpeg: cannot decode image with these dimensions");
++
+ for (; data->r1 < nr1 && (!data->dri || rst);
+- data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
++ data->r1++, data->bitmap_ptr += stride * 3)
+ for (c1 = 0; c1 < nc1 && (!data->dri || rst);
+ c1++, rst--, data->bitmap_ptr += hb * 3)
+ {
diff --git a/debian/patches/0077-normal-charset-Fix-array-out-of-bounds-formatting-un.patch b/debian/patches/0077-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
new file mode 100644
index 0000000..066775a
--- /dev/null
+++ b/debian/patches/0077-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
@@ -0,0 +1,33 @@
+From 557370849b914110a9efbd7256dc3942a8af8b99 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 13 Jul 2021 13:24:38 +1000
+Subject: normal/charset: Fix array out-of-bounds formatting unicode for
+ display
+
+In some cases attempting to display arbitrary binary strings leads
+to ASAN splats reading the widthspec array out of bounds.
+
+Check the index. If it would be out of bounds, return a width of 1.
+I don't know if that's strictly correct, but we're not really expecting
+great display of arbitrary binary data, and it's certainly not worse than
+an OOB read.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/normal/charset.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
+index 4dfcc3107..7a5a7c153 100644
+--- a/grub-core/normal/charset.c
++++ b/grub-core/normal/charset.c
+@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c)
+ {
+ if (grub_unicode_get_comb_type (c->base))
+ return 0;
++ if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec))
++ return 1;
+ if (widthspec[c->base >> 3] & (1 << (c->base & 7)))
+ return 2;
+ else
diff --git a/debian/patches/0078-net-netbuff-Block-overly-large-netbuff-allocs.patch b/debian/patches/0078-net-netbuff-Block-overly-large-netbuff-allocs.patch
new file mode 100644
index 0000000..150f101
--- /dev/null
+++ b/debian/patches/0078-net-netbuff-Block-overly-large-netbuff-allocs.patch
@@ -0,0 +1,45 @@
+From 4ea64c827f8bc57180772fd5671ddd010cb7b2ed Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 8 Mar 2022 23:47:46 +1100
+Subject: net/netbuff: Block overly large netbuff allocs
+
+A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment
+reassembly.
+
+This helps avoid some bugs (and provides a spot to instrument to catch
+them at their source).
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/netbuff.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
+index dbeeefe47..d5e9e9a0d 100644
+--- a/grub-core/net/netbuff.c
++++ b/grub-core/net/netbuff.c
+@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len)
+
+ COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0);
+
++ /*
++ * The largest size of a TCP packet is 64 KiB, and everything else
++ * should be a lot smaller - most MTUs are 1500 or less. Cap data
++ * size at 64 KiB + a buffer.
++ */
++ if (len > 0xffffUL + 0x1000UL)
++ {
++ grub_error (GRUB_ERR_BUG,
++ "attempted to allocate a packet that is too big");
++ return NULL;
++ }
++
+ if (len < NETBUFFMINLEN)
+ len = NETBUFFMINLEN;
+
+ len = ALIGN_UP (len, NETBUFF_ALIGN);
++
+ #ifdef GRUB_MACHINE_EMU
+ data = grub_malloc (len + sizeof (*nb));
+ #else
diff --git a/debian/patches/0079-net-ip-Do-IP-fragment-maths-safely.patch b/debian/patches/0079-net-ip-Do-IP-fragment-maths-safely.patch
new file mode 100644
index 0000000..7c5d8dc
--- /dev/null
+++ b/debian/patches/0079-net-ip-Do-IP-fragment-maths-safely.patch
@@ -0,0 +1,43 @@
+From 2a4f87df650fd2ef639b48b43fc834b97b6b2bfa Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 20 Dec 2021 19:41:21 +1100
+Subject: net/ip: Do IP fragment maths safely
+
+This avoids an underflow and subsequent unpleasantness.
+
+Fixes: CVE-2022-28733
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/ip.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index 01410798b..937be8767 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -25,6 +25,7 @@
+ #include <grub/net/netbuff.h>
+ #include <grub/mm.h>
+ #include <grub/priority_queue.h>
++#include <grub/safemath.h>
+ #include <grub/time.h>
+
+ struct iphdr {
+@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
+ {
+ rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK)
+ + (nb->tail - nb->data));
+- rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t));
++
++ if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t),
++ &rsm->total_len))
++ {
++ grub_dprintf ("net", "IP reassembly size underflow\n");
++ return GRUB_ERR_NONE;
++ }
++
+ rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len);
+ if (!rsm->asm_netbuff)
+ {
diff --git a/debian/patches/0080-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch b/debian/patches/0080-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
new file mode 100644
index 0000000..0f3cdc7
--- /dev/null
+++ b/debian/patches/0080-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
@@ -0,0 +1,55 @@
+From 21158c5dfb5e0c5015277346128903397d498da4 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 16 Sep 2021 01:29:54 +1000
+Subject: net/dns: Fix double-free addresses on corrupt DNS response
+
+grub_net_dns_lookup() takes as inputs a pointer to an array of addresses
+("addresses") for the given name, and pointer to a number of addresses
+("naddresses"). grub_net_dns_lookup() is responsible for allocating
+"addresses", and the caller is responsible for freeing it if
+"naddresses" > 0.
+
+The DNS recv_hook will sometimes set and free the addresses array,
+for example if the packet is too short:
+
+ if (ptr + 10 >= nb->tail)
+ {
+ if (!*data->naddresses)
+ grub_free (*data->addresses);
+ grub_netbuff_free (nb);
+ return GRUB_ERR_NONE;
+ }
+
+Later on the nslookup command code unconditionally frees the "addresses"
+array. Normally this is fine: the array is either populated with valid
+data or is NULL. But in these sorts of error cases it is neither NULL
+nor valid and we get a double-free.
+
+Only free "addresses" if "naddresses" > 0.
+
+It looks like the other use of grub_net_dns_lookup() is not affected.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/dns.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
+index 906ec7d67..135faac03 100644
+--- a/grub-core/net/dns.c
++++ b/grub-core/net/dns.c
+@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
+ grub_net_addr_to_str (&addresses[i], buf);
+ grub_printf ("%s\n", buf);
+ }
+- grub_free (addresses);
+ if (naddresses)
+- return GRUB_ERR_NONE;
++ {
++ grub_free (addresses);
++ return GRUB_ERR_NONE;
++ }
+ return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
+ }
+
diff --git a/debian/patches/0081-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch b/debian/patches/0081-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
new file mode 100644
index 0000000..0fc28a9
--- /dev/null
+++ b/debian/patches/0081-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
@@ -0,0 +1,69 @@
+From 968febf3a4de5df0f91cc13bc6b6053fc22575e1 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 20 Dec 2021 21:55:43 +1100
+Subject: net/dns: Don't read past the end of the string we're checking against
+
+I don't really understand what's going on here but fuzzing found
+a bug where we read past the end of check_with. That's a C string,
+so use grub_strlen() to make sure we don't overread it.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/dns.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
+index 135faac03..17961a9f1 100644
+--- a/grub-core/net/dns.c
++++ b/grub-core/net/dns.c
+@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
+ int *length, char *set)
+ {
+ const char *readable_ptr = check_with;
++ int readable_len;
+ const grub_uint8_t *ptr;
+ char *optr = set;
+ int bytes_processed = 0;
+ if (length)
+ *length = 0;
++
++ if (readable_ptr != NULL)
++ readable_len = grub_strlen (readable_ptr);
++ else
++ readable_len = 0;
++
+ for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; )
+ {
+ /* End marker. */
+@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
+ ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]);
+ continue;
+ }
+- if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)
++ if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0))
+ return 0;
+ if (grub_memchr (ptr + 1, 0, *ptr)
+ || grub_memchr (ptr + 1, '.', *ptr))
+ return 0;
+ if (readable_ptr)
+- readable_ptr += *ptr;
++ {
++ readable_ptr += *ptr;
++ readable_len -= *ptr;
++ }
+ if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0)
+ return 0;
+ bytes_processed += *ptr + 1;
+@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
+ if (optr)
+ *optr++ = '.';
+ if (readable_ptr && *readable_ptr)
+- readable_ptr++;
++ {
++ readable_ptr++;
++ readable_len--;
++ }
+ ptr += *ptr + 1;
+ }
+ return 0;
diff --git a/debian/patches/0082-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch b/debian/patches/0082-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
new file mode 100644
index 0000000..bb4cd8c
--- /dev/null
+++ b/debian/patches/0082-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
@@ -0,0 +1,111 @@
+From e7573be61b3cf005cdf0a068652153437daca4b3 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 20 Sep 2021 01:12:24 +1000
+Subject: net/tftp: Prevent a UAF and double-free from a failed seek
+
+A malicious tftp server can cause UAFs and a double free.
+
+An attempt to read from a network file is handled by grub_net_fs_read(). If
+the read is at an offset other than the current offset, grub_net_seek_real()
+is invoked.
+
+In grub_net_seek_real(), if a backwards seek cannot be satisfied from the
+currently received packets, and the underlying transport does not provide
+a seek method, then grub_net_seek_real() will close and reopen the network
+protocol layer.
+
+For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t
+file->data. The file->data pointer is not nulled out after the free.
+
+If the ->open() call fails, the file->data will not be reallocated and will
+continue point to a freed memory block. This could happen from a server
+refusing to send the requisite ack to the new tftp request, for example.
+
+The seek and the read will then fail, but the grub_file continues to exist:
+the failed seek does not necessarily cause the entire file to be thrown
+away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc.,
+a read failure is interpreted as a decompressor passing on the file, not as
+an invalidation of the entire grub_file_t structure).
+
+This means subsequent attempts to read or seek the file will use the old
+file->data after free. Eventually, the file will be close()d again and
+file->data will be freed again.
+
+Mark a net_fs file that doesn't reopen as broken. Do not permit read() or
+close() on a broken file (seek is not exposed directly to the file API -
+it is only called as part of read, so this blocks seeks as well).
+
+As an additional defence, null out the ->data pointer if tftp_open() fails.
+That would have lead to a simple null pointer dereference rather than
+a mess of UAFs.
+
+This may affect other protocols, I haven't checked.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/net.c | 11 +++++++++--
+ grub-core/net/tftp.c | 1 +
+ include/grub/net.h | 1 +
+ 3 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 15a2f29a9..af7440776 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1548,7 +1548,8 @@ grub_net_fs_close (grub_file_t file)
+ grub_netbuff_free (file->device->net->packs.first->nb);
+ grub_net_remove_packet (file->device->net->packs.first);
+ }
+- file->device->net->protocol->close (file);
++ if (!file->device->net->broken)
++ file->device->net->protocol->close (file);
+ grub_free (file->device->net->name);
+ return GRUB_ERR_NONE;
+ }
+@@ -1770,7 +1771,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
+ file->device->net->stall = 0;
+ err = file->device->net->protocol->open (file, file->device->net->name);
+ if (err)
+- return err;
++ {
++ file->device->net->broken = 1;
++ return err;
++ }
+ grub_net_fs_read_real (file, NULL, offset);
+ return grub_errno;
+ }
+@@ -1779,6 +1783,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
+ static grub_ssize_t
+ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
+ {
++ if (file->device->net->broken)
++ return -1;
++
+ if (file->offset != file->device->net->offset)
+ {
+ grub_err_t err;
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index f3e787938..d1afa2535 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -404,6 +404,7 @@ tftp_open (struct grub_file *file, const char *filename)
+ {
+ grub_net_udp_close (data->sock);
+ grub_free (data);
++ file->data = NULL;
+ return grub_errno;
+ }
+
+diff --git a/include/grub/net.h b/include/grub/net.h
+index cbcae79b1..8d71ca6cc 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -277,6 +277,7 @@ typedef struct grub_net
+ grub_fs_t fs;
+ int eof;
+ int stall;
++ int broken;
+ } *grub_net_t;
+
+ extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
diff --git a/debian/patches/0083-net-tftp-Avoid-a-trivial-UAF.patch b/debian/patches/0083-net-tftp-Avoid-a-trivial-UAF.patch
new file mode 100644
index 0000000..8e42215
--- /dev/null
+++ b/debian/patches/0083-net-tftp-Avoid-a-trivial-UAF.patch
@@ -0,0 +1,34 @@
+From fb66f40ba67b88408a43cb38492053985bfe4968 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 18 Jan 2022 14:29:20 +1100
+Subject: net/tftp: Avoid a trivial UAF
+
+Under tftp errors, we print a tftp error message from the tftp header.
+However, the tftph pointer is a pointer inside nb, the netbuff. Previously,
+we were freeing the nb and then dereferencing it. Don't do that, use it
+and then free it later.
+
+This isn't really _bad_ per se, especially as we're single-threaded, but
+it trips up fuzzers.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/tftp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index d1afa2535..4222d93b6 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
+ return GRUB_ERR_NONE;
+ case TFTP_ERROR:
+ data->have_oack = 1;
+- grub_netbuff_free (nb);
+ grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
+ grub_error_save (&data->save_err);
++ grub_netbuff_free (nb);
+ return GRUB_ERR_NONE;
+ default:
+ grub_netbuff_free (nb);
diff --git a/debian/patches/0084-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch b/debian/patches/0084-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
new file mode 100644
index 0000000..763e46a
--- /dev/null
+++ b/debian/patches/0084-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
@@ -0,0 +1,40 @@
+From 6df718714dea5043243e367750b5c6abebcf79fe Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 1 Mar 2022 23:14:15 +1100
+Subject: net/http: Do not tear down socket if it's already been torn down
+
+It's possible for data->sock to get torn down in tcp error handling.
+If we unconditionally tear it down again we will end up doing writes
+to an offset of the NULL pointer when we go to tear it down again.
+
+Detect if it has been torn down and don't do it again.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/http.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index 3fe155f1b..ef6eaff0d 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -422,7 +422,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ return err;
+ }
+
+- for (i = 0; !data->headers_recv && i < 100; i++)
++ for (i = 0; data->sock && !data->headers_recv && i < 100; i++)
+ {
+ grub_net_tcp_retransmit ();
+ grub_net_poll_cards (300, &data->headers_recv);
+@@ -430,7 +430,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+
+ if (!data->headers_recv)
+ {
+- grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
++ if (data->sock)
++ grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
+ if (data->err)
+ {
+ char *str = data->errmsg;
diff --git a/debian/patches/0085-net-http-Fix-OOB-write-for-split-http-headers.patch b/debian/patches/0085-net-http-Fix-OOB-write-for-split-http-headers.patch
new file mode 100644
index 0000000..3b6ff59
--- /dev/null
+++ b/debian/patches/0085-net-http-Fix-OOB-write-for-split-http-headers.patch
@@ -0,0 +1,45 @@
+From f407a45bd3483f6bbf58c5e9386a44caa14287e3 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 8 Mar 2022 18:17:03 +1100
+Subject: net/http: Fix OOB write for split http headers
+
+GRUB has special code for handling an http header that is split
+across two packets.
+
+The code tracks the end of line by looking for a "\n" byte. The
+code for split headers has always advanced the pointer just past the
+end of the line, whereas the code that handles unsplit headers does
+not advance the pointer. This extra advance causes the length to be
+one greater, which breaks an assumption in parse_line(), leading to
+it writing a NUL byte one byte past the end of the buffer where we
+reconstruct the line from the two packets.
+
+It's conceivable that an attacker controlled set of packets could
+cause this to zero out the first byte of the "next" pointer of the
+grub_mm_region structure following the current_line buffer.
+
+Do not advance the pointer in the split header case.
+
+Fixes: CVE-2022-28734
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/http.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index ef6eaff0d..9f45ad4e8 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -190,9 +190,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
+ int have_line = 1;
+ char *t;
+ ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
+- if (ptr)
+- ptr++;
+- else
++ if (ptr == NULL)
+ {
+ have_line = 0;
+ ptr = (char *) nb->tail;
diff --git a/debian/patches/0086-net-http-Error-out-on-headers-with-LF-without-CR.patch b/debian/patches/0086-net-http-Error-out-on-headers-with-LF-without-CR.patch
new file mode 100644
index 0000000..5b7ede1
--- /dev/null
+++ b/debian/patches/0086-net-http-Error-out-on-headers-with-LF-without-CR.patch
@@ -0,0 +1,47 @@
+From 870b94755b6a341d21632293677b346ff033e5f0 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 8 Mar 2022 19:04:40 +1100
+Subject: net/http: Error out on headers with LF without CR
+
+In a similar vein to the previous patch, parse_line() would write
+a NUL byte past the end of the buffer if there was an HTTP header
+with a LF rather than a CRLF.
+
+RFC-2616 says:
+
+ Many HTTP/1.1 header field values consist of words separated by LWS
+ or special characters. These special characters MUST be in a quoted
+ string to be used within a parameter value (as defined in section 3.6).
+
+We don't support quoted sections or continuation lines, etc.
+
+If we see an LF that's not part of a CRLF, bail out.
+
+Fixes: CVE-2022-28734
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/http.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index 9f45ad4e8..6988d38fb 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -68,7 +68,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
+ char *end = ptr + len;
+ while (end > ptr && *(end - 1) == '\r')
+ end--;
++
++ /* LF without CR. */
++ if (end == ptr + len)
++ {
++ data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR"));
++ return GRUB_ERR_NONE;
++ }
+ *end = 0;
++
+ /* Trailing CRLF. */
+ if (data->in_chunk_len == 1)
+ {
diff --git a/debian/patches/0087-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch b/debian/patches/0087-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
new file mode 100644
index 0000000..cc6520e
--- /dev/null
+++ b/debian/patches/0087-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
@@ -0,0 +1,71 @@
+From 2d014248d540c7e087934a94b6e7a2aa7fc2c704 Mon Sep 17 00:00:00 2001
+From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Date: Wed, 6 Apr 2022 18:03:37 +0530
+Subject: fs/f2fs: Do not read past the end of nat journal entries
+
+A corrupt f2fs file system could specify a nat journal entry count
+that is beyond the maximum NAT_JOURNAL_ENTRIES.
+
+Check if the specified nat journal entry count before accessing the
+array, and throw an error if it is too large.
+
+Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/f2fs.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
+index 8a9992ca9..63702214b 100644
+--- a/grub-core/fs/f2fs.c
++++ b/grub-core/fs/f2fs.c
+@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data)
+ return err;
+ }
+
+-static grub_uint32_t
+-get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
++static grub_err_t
++get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid,
++ grub_uint32_t *blkaddr)
+ {
+ grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
+- grub_uint32_t blkaddr = 0;
+ grub_uint16_t i;
+
++ if (n > NAT_JOURNAL_ENTRIES)
++ return grub_error (GRUB_ERR_BAD_FS,
++ "invalid number of nat journal entries");
++
+ for (i = 0; i < n; i++)
+ {
+ if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
+ {
+- blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
++ *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
+ break;
+ }
+ }
+
+- return blkaddr;
++ return GRUB_ERR_NONE;
+ }
+
+ static grub_uint32_t
+@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+ {
+ struct grub_f2fs_nat_block *nat_block;
+ grub_uint32_t seg_off, block_off, entry_off, block_addr;
+- grub_uint32_t blkaddr;
++ grub_uint32_t blkaddr = 0;
+ grub_err_t err;
+
+- blkaddr = get_blkaddr_from_nat_journal (data, nid);
++ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
++ if (err != GRUB_ERR_NONE)
++ return 0;
++
+ if (blkaddr)
+ return blkaddr;
+
diff --git a/debian/patches/0088-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch b/debian/patches/0088-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
new file mode 100644
index 0000000..5f06bd4
--- /dev/null
+++ b/debian/patches/0088-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
@@ -0,0 +1,131 @@
+From 9561d7ef621e5e68f12bcd916252ef1c11e60366 Mon Sep 17 00:00:00 2001
+From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Date: Wed, 6 Apr 2022 18:49:09 +0530
+Subject: fs/f2fs: Do not read past the end of nat bitmap
+
+A corrupt f2fs filesystem could have a block offset or a bitmap
+offset that would cause us to read beyond the bounds of the nat
+bitmap.
+
+Introduce the nat_bitmap_size member in grub_f2fs_data which holds
+the size of nat bitmap.
+
+Set the size when loading the nat bitmap in nat_bitmap_ptr(), and
+catch when an invalid offset would create a pointer past the end of
+the allocated space.
+
+Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid
+reading past the end of the nat bitmap.
+
+Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------
+ 1 file changed, 27 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
+index 63702214b..8898b235e 100644
+--- a/grub-core/fs/f2fs.c
++++ b/grub-core/fs/f2fs.c
+@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ #define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */
+
+ #define MAX_VOLUME_NAME 512
++#define MAX_NAT_BITMAP_SIZE 3900
+
+ enum FILE_TYPE
+ {
+@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint
+ grub_uint32_t checksum_offset;
+ grub_uint64_t elapsed_time;
+ grub_uint8_t alloc_type[MAX_ACTIVE_LOGS];
+- grub_uint8_t sit_nat_version_bitmap[3900];
++ grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE];
+ grub_uint32_t checksum;
+ } GRUB_PACKED;
+
+@@ -302,6 +303,7 @@ struct grub_f2fs_data
+
+ struct grub_f2fs_nat_journal nat_j;
+ char *nat_bitmap;
++ grub_uint32_t nat_bitmap_size;
+
+ grub_disk_t disk;
+ struct grub_f2fs_node *inode;
+@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type)
+ }
+
+ static void *
+-nat_bitmap_ptr (struct grub_f2fs_data *data)
++nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size)
+ {
+ struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+ grub_uint32_t offset;
++ *nat_bitmap_size = MAX_NAT_BITMAP_SIZE;
+
+ if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
+ return ckpt->sit_nat_version_bitmap;
+
+ offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
++ if (offset >= MAX_NAT_BITMAP_SIZE)
++ return NULL;
++
++ *nat_bitmap_size = *nat_bitmap_size - offset;
+
+ return ckpt->sit_nat_version_bitmap + offset;
+ }
+@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len)
+ }
+
+ static int
+-grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
++grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len)
+ {
+ int mask;
++ grub_uint32_t shifted_nr = (nr >> 3);
++
++ if (shifted_nr >= len)
++ return -1;
+
+- p += (nr >> 3);
++ p += shifted_nr;
+ mask = 1 << (7 - (nr & 0x07));
+
+ return mask & *p;
+@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+ grub_uint32_t seg_off, block_off, entry_off, block_addr;
+ grub_uint32_t blkaddr = 0;
+ grub_err_t err;
++ int result_bit;
+
+ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
+ if (err != GRUB_ERR_NONE)
+@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+ ((seg_off * data->blocks_per_seg) << 1) +
+ (block_off & (data->blocks_per_seg - 1));
+
+- if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
++ result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap,
++ data->nat_bitmap_size);
++ if (result_bit > 0)
+ block_addr += data->blocks_per_seg;
++ else if (result_bit == -1)
++ {
++ grub_free (nat_block);
++ return 0;
++ }
+
+ err = grub_f2fs_block_read (data, block_addr, nat_block);
+ if (err)
+@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk)
+ if (err)
+ goto fail;
+
+- data->nat_bitmap = nat_bitmap_ptr (data);
++ data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size);
++ if (data->nat_bitmap == NULL)
++ goto fail;
+
+ err = get_nat_journal (data);
+ if (err)
diff --git a/debian/patches/0089-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch b/debian/patches/0089-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
new file mode 100644
index 0000000..cf71b38
--- /dev/null
+++ b/debian/patches/0089-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
@@ -0,0 +1,37 @@
+From 998bd74c11c0e00f69fe2f37a8200381faf51061 Mon Sep 17 00:00:00 2001
+From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Date: Wed, 6 Apr 2022 18:17:43 +0530
+Subject: fs/f2fs: Do not copy file names that are too long
+
+A corrupt f2fs file system might specify a name length which is greater
+than the maximum name length supported by the GRUB f2fs driver.
+
+We will allocate enough memory to store the overly long name, but there
+are only F2FS_NAME_LEN bytes in the source, so we would read past the end
+of the source.
+
+While checking directory entries, do not copy a file name with an invalid
+length.
+
+Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/f2fs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
+index 8898b235e..df6beb544 100644
+--- a/grub-core/fs/f2fs.c
++++ b/grub-core/fs/f2fs.c
+@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
+
+ ftype = ctx->dentry[i].file_type;
+ name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
++
++ if (name_len >= F2FS_NAME_LEN)
++ return 0;
++
+ filename = grub_malloc (name_len + 1);
+ if (!filename)
+ return 0;
diff --git a/debian/patches/0090-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch b/debian/patches/0090-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
new file mode 100644
index 0000000..d02cbe2
--- /dev/null
+++ b/debian/patches/0090-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
@@ -0,0 +1,75 @@
+From 23c785c3e965731ac440f9c150fdfeec6dd433e7 Mon Sep 17 00:00:00 2001
+From: Darren Kenny <darren.kenny@oracle.com>
+Date: Tue, 29 Mar 2022 10:49:56 +0000
+Subject: fs/btrfs: Fix several fuzz issues with invalid dir item sizing
+
+According to the btrfs code in Linux, the structure of a directory item
+leaf should be of the form:
+
+ |struct btrfs_dir_item|name|data|
+
+in GRUB the name len and data len are in the grub_btrfs_dir_item
+structure's n and m fields respectively.
+
+The combined size of the structure, name and data should be less than
+the allocated memory, a difference to the Linux kernel's struct
+btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for
+where the name is stored, so we adjust for that too.
+
+Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index 63203034d..eb9857d74 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -1961,6 +1961,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
+ int r = 0;
+ grub_uint64_t tree;
+ grub_uint8_t type;
++ grub_size_t est_size = 0;
+
+ if (!data)
+ return grub_errno;
+@@ -2019,6 +2020,18 @@ grub_btrfs_dir (grub_device_t device, const char *path,
+ break;
+ }
+
++ if (direl == NULL ||
++ grub_add (grub_le_to_cpu16 (direl->n),
++ grub_le_to_cpu16 (direl->m), &est_size) ||
++ grub_add (est_size, sizeof (*direl), &est_size) ||
++ grub_sub (est_size, sizeof (direl->name), &est_size) ||
++ est_size > allocated)
++ {
++ grub_errno = GRUB_ERR_OUT_OF_RANGE;
++ r = -grub_errno;
++ goto out;
++ }
++
+ for (cdirel = direl;
+ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ < (grub_ssize_t) elemsize;
+@@ -2029,6 +2042,19 @@ grub_btrfs_dir (grub_device_t device, const char *path,
+ char c;
+ struct grub_btrfs_inode inode;
+ struct grub_dirhook_info info;
++
++ if (cdirel == NULL ||
++ grub_add (grub_le_to_cpu16 (cdirel->n),
++ grub_le_to_cpu16 (cdirel->m), &est_size) ||
++ grub_add (est_size, sizeof (*cdirel), &est_size) ||
++ grub_sub (est_size, sizeof (cdirel->name), &est_size) ||
++ est_size > allocated)
++ {
++ grub_errno = GRUB_ERR_OUT_OF_RANGE;
++ r = -grub_errno;
++ goto out;
++ }
++
+ err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id,
+ tree);
+ grub_memset (&info, 0, sizeof (info));
diff --git a/debian/patches/0091-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch b/debian/patches/0091-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
new file mode 100644
index 0000000..4ae22c9
--- /dev/null
+++ b/debian/patches/0091-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
@@ -0,0 +1,133 @@
+From 22976cf1b9864455173e1bfc617bc63f13fbecf7 Mon Sep 17 00:00:00 2001
+From: Darren Kenny <darren.kenny@oracle.com>
+Date: Tue, 29 Mar 2022 15:52:46 +0000
+Subject: fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing
+
+The fuzzer is generating btrfs file systems that have chunks with
+invalid combinations of stripes and substripes for the given RAID
+configurations.
+
+After examining the Linux kernel fs/btrfs/tree-checker.c code, it
+appears that sub-stripes should only be applied to RAID10, and in that
+case there should only ever be 2 of them.
+
+Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4
+should have 2. 3 or 4 stripes respectively, which is what redundancy
+corresponds.
+
+Some of the chunks ended up with a size of 0, which grub_malloc() still
+returned memory for and in turn generated ASAN errors later when
+accessed.
+
+While it would be possible to specifically limit the number of stripes,
+a more correct test was on the combination of the chunk item, and the
+number of stripes by the size of the chunk stripe structure in
+comparison to the size of the chunk itself.
+
+Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 55 insertions(+)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index eb9857d74..b3d71cd9e 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -912,6 +912,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ return grub_error (GRUB_ERR_BAD_FS,
+ "couldn't find the chunk descriptor");
+
++ if (!chsize)
++ {
++ grub_dprintf ("btrfs", "zero-size chunk\n");
++ return grub_error (GRUB_ERR_BAD_FS,
++ "got an invalid zero-size chunk");
++ }
+ chunk = grub_malloc (chsize);
+ if (!chunk)
+ return grub_errno;
+@@ -970,6 +976,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
+ nstripes,
+ NULL);
++
++ /* For single, there should be exactly 1 stripe. */
++ if (grub_le_to_cpu16 (chunk->nstripes) != 1)
++ {
++ grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n",
++ grub_le_to_cpu16 (chunk->nstripes));
++ return grub_error (GRUB_ERR_BAD_FS,
++ "invalid RAID_SINGLE: nstripes != 1 (%u)",
++ grub_le_to_cpu16 (chunk->nstripes));
++ }
+ if (stripe_length == 0)
+ stripe_length = 512;
+ stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
+@@ -989,6 +1005,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ stripen = 0;
+ stripe_offset = off;
+ csize = grub_le_to_cpu64 (chunk->size) - off;
++
++ /*
++ * Redundancy, and substripes only apply to RAID10, and there
++ * should be exactly 2 sub-stripes.
++ */
++ if (grub_le_to_cpu16 (chunk->nstripes) != redundancy)
++ {
++ grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n",
++ redundancy, grub_le_to_cpu16 (chunk->nstripes));
++ return grub_error (GRUB_ERR_BAD_FS,
++ "invalid RAID1: nstripes != %u (%u)",
++ redundancy, grub_le_to_cpu16 (chunk->nstripes));
++ }
+ break;
+ }
+ case GRUB_BTRFS_CHUNK_TYPE_RAID0:
+@@ -1025,6 +1054,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ stripe_offset = low + chunk_stripe_length
+ * high;
+ csize = chunk_stripe_length - low;
++
++ /*
++ * Substripes only apply to RAID10, and there
++ * should be exactly 2 sub-stripes.
++ */
++ if (grub_le_to_cpu16 (chunk->nsubstripes) != 2)
++ {
++ grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)",
++ grub_le_to_cpu16 (chunk->nsubstripes));
++ return grub_error (GRUB_ERR_BAD_FS,
++ "invalid RAID10: nsubstripes != 2 (%u)",
++ grub_le_to_cpu16 (chunk->nsubstripes));
++ }
++
+ break;
+ }
+ case GRUB_BTRFS_CHUNK_TYPE_RAID5:
+@@ -1124,6 +1167,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+
+ for (j = 0; j < 2; j++)
+ {
++ grub_size_t est_chunk_alloc = 0;
++
+ grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
+ "+0x%" PRIxGRUB_UINT64_T
+ " (%d stripes (%d substripes) of %"
+@@ -1136,6 +1181,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n",
+ addr);
+
++ if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe),
++ grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) ||
++ grub_add (est_chunk_alloc,
++ sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) ||
++ est_chunk_alloc > chunk->size)
++ {
++ err = GRUB_ERR_BAD_FS;
++ break;
++ }
++
+ if (is_raid56)
+ {
+ err = btrfs_read_from_chunk (data, chunk, stripen,
diff --git a/debian/patches/0092-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch b/debian/patches/0092-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
new file mode 100644
index 0000000..30c2dad
--- /dev/null
+++ b/debian/patches/0092-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
@@ -0,0 +1,75 @@
+From 589500ad3777d1335c8e5cb139f7c0c6089112a8 Mon Sep 17 00:00:00 2001
+From: Darren Kenny <darren.kenny@oracle.com>
+Date: Thu, 7 Apr 2022 15:18:12 +0000
+Subject: fs/btrfs: Fix more fuzz issues related to chunks
+
+The corpus was generating issues in grub_btrfs_read_logical() when
+attempting to iterate over stripe entries in the superblock's
+bootmapping.
+
+In most cases the reason for the failure was that the number of stripes
+in chunk->nstripes exceeded the possible space statically allocated in
+superblock bootmapping space. Each stripe entry in the bootmapping block
+consists of a grub_btrfs_key followed by a grub_btrfs_chunk_stripe.
+
+Another issue that came up was that while calculating the chunk size,
+in an earlier piece of code in that function, depending on the data
+provided in the btrfs file system, it would end up calculating a size
+that was too small to contain even 1 grub_btrfs_chunk_item, which is
+obviously invalid too.
+
+Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index b3d71cd9e..54a46b8f8 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -918,6 +918,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ return grub_error (GRUB_ERR_BAD_FS,
+ "got an invalid zero-size chunk");
+ }
++
++ /*
++ * The space being allocated for a chunk should at least be able to
++ * contain one chunk item.
++ */
++ if (chsize < sizeof (struct grub_btrfs_chunk_item))
++ {
++ grub_dprintf ("btrfs", "chunk-size too small\n");
++ return grub_error (GRUB_ERR_BAD_FS,
++ "got an invalid chunk size");
++ }
+ chunk = grub_malloc (chsize);
+ if (!chunk)
+ return grub_errno;
+@@ -1165,6 +1176,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ if (csize > (grub_uint64_t) size)
+ csize = size;
+
++ /*
++ * The space for a chunk stripe is limited to the space provide in the super-block's
++ * bootstrap mapping with an initial btrfs key at the start of each chunk.
++ */
++ grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) /
++ (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe));
++
+ for (j = 0; j < 2; j++)
+ {
+ grub_size_t est_chunk_alloc = 0;
+@@ -1191,6 +1209,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ break;
+ }
+
++ if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes)
++ {
++ err = GRUB_ERR_BAD_FS;
++ break;
++ }
++
+ if (is_raid56)
+ {
+ err = btrfs_read_from_chunk (data, chunk, stripen,
diff --git a/debian/patches/987008-lvrename-boot-fail.patch b/debian/patches/987008-lvrename-boot-fail.patch
new file mode 100644
index 0000000..5d5df3e
--- /dev/null
+++ b/debian/patches/987008-lvrename-boot-fail.patch
@@ -0,0 +1,35 @@
+Description: fix renamed LV detection
+ It looks like the detection of the LVM logical volumes fails in
+ certain edge conditions. In particular, it was reported that
+ renaming an LV will make grub fail to boot from the system as it
+ cannot properly detect it anymore.
+ .
+ I have looked at the code surrounding the patch and cannot claim to
+ understand the entire function here, as it is huge and quite
+ cryptic. But it seems sane: the `ptr` we're inspecting here starts
+ at the `rlocn->offset`, but we were adding `mda_size` to the
+ (somewhat) unrelated metadatabuf instead. Now we're marking the
+ `mda_end` correctly, based on the rlocn->offsite and ->size.
+ .
+ I have not tested this myself as the test setup is quite involved,
+ but it seems others (e.g. "Hoyer, David" <David.Hoyer@netapp.com>)
+ have tested the patch and confirmed it worked.
+Author: Rogier <rogier777@gmail.com>
+Origin: other
+Bug: https://savannah.gnu.org/bugs/index.php?61620
+Bug-Debian: https://bugs.debian.org/987008
+Forwarded: https://savannah.gnu.org/bugs/index.php?61620
+Reviewed-By: Antoine Beaupré
+Last-Update: 2023-02-25
+
+--- grub2-2.06.orig/grub-core/disk/lvm.c
++++ grub2-2.06/grub-core/disk/lvm.c
+@@ -290,7 +290,7 @@ grub_lvm_detect (grub_disk_t disk,
+
+ p = q = (char *)ptr;
+
+- if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
++ if (grub_add (ptr, (grub_size_t)grub_le_to_cpu64 (rlocn->size), &ptr))
+ goto error_parsing_metadata;
+
+ mda_end = (char *)ptr;
diff --git a/debian/patches/arm64-handover-to-kernel-if-sb-enabled.patch b/debian/patches/arm64-handover-to-kernel-if-sb-enabled.patch
new file mode 100644
index 0000000..e20d4ad
--- /dev/null
+++ b/debian/patches/arm64-handover-to-kernel-if-sb-enabled.patch
@@ -0,0 +1,152 @@
+From: Emanuele Rocca <ema@debian.org>
+Date: Fri, 31 Mar 2023 12:38:52 +0200
+Subject: Cherry-pick parts of "Load arm with SB enabled."
+
+Fix Secure Boot on arm64 by cherry-picking the relevant parts of upstream patch
+"Load arm with SB enabled."
+
+Signed-off-by: Emanuele Rocca <ema@debian.org>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/2786ab864cf00c15123320671f653e9a36ba12b4
+---
+
+Index: grub.git/grub-core/loader/arm64/linux.c
+===================================================================
+--- grub.git.orig/grub-core/loader/arm64/linux.c
++++ grub.git/grub-core/loader/arm64/linux.c
+@@ -16,6 +16,7 @@
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
++#include <grub/cache.h>
+ #include <grub/charset.h>
+ #include <grub/command.h>
+ #include <grub/err.h>
+@@ -33,6 +34,7 @@
+ #include <grub/i18n.h>
+ #include <grub/lib/cmdline.h>
+ #include <grub/verify.h>
++#include <grub/efi/sb.h>
+
+ GRUB_MOD_LICENSE ("GPLv3+");
+
+@@ -41,6 +43,7 @@ static int loaded;
+
+ static void *kernel_addr;
+ static grub_uint64_t kernel_size;
++static grub_uint32_t handover_offset;
+
+ static char *linux_args;
+ static grub_uint32_t cmdline_size;
+@@ -48,6 +51,15 @@ static grub_uint32_t cmdline_size;
+ static grub_addr_t initrd_start;
+ static grub_addr_t initrd_end;
+
++struct grub_arm64_linux_pe_header
++{
++ grub_uint32_t magic;
++ struct grub_pe32_coff_header coff;
++ struct grub_pe64_optional_header opt;
++};
++
++typedef void (*handover_func) (void *, grub_efi_system_table_t *);
++
+ grub_err_t
+ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+ {
+@@ -64,7 +76,8 @@ grub_arch_efi_linux_check_image (struct
+ static grub_err_t
+ finalize_params_linux (void)
+ {
+- int node, retval;
++ grub_efi_loaded_image_t *loaded_image = NULL;
++ int node, retval, len;
+
+ void *fdt;
+
+@@ -99,6 +112,27 @@ finalize_params_linux (void)
+ if (grub_fdt_install() != GRUB_ERR_NONE)
+ goto failure;
+
++ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
++ fdt);
++
++ /* Convert command line to UCS-2 */
++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++ if (!loaded_image) {
++ grub_dprintf ("linux", "Error loading image with grub_efi_get_loaded_image()\n");
++ goto failure;
++ }
++
++ loaded_image->load_options_size = len =
++ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
++ loaded_image->load_options =
++ grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
++ if (!loaded_image->load_options)
++ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
++
++ loaded_image->load_options_size =
++ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
++ (grub_uint8_t *) linux_args, len, NULL);
++
+ return GRUB_ERR_NONE;
+
+ failure:
+@@ -116,6 +150,39 @@ grub_arch_efi_linux_boot_image (grub_add
+ grub_efi_loaded_image_t *loaded_image;
+ int len;
+
++#ifdef __aarch64__ /* SB only enabled for arm64 */
++ handover_func hf;
++
++ if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED) {
++ grub_dprintf ("linux", "GRUB_EFI_SECUREBOOT_MODE enabled\n");
++ /*
++ * Since the EFI loader is not calling the LoadImage() and StartImage()
++ * services for loading the kernel and booting respectively, it has to
++ * set the Loaded Image base address.
++ */
++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++ if (loaded_image) {
++ loaded_image->image_base = kernel_addr;
++ grub_dprintf ("linux", "Loaded Image base address set to %p\n", kernel_addr);
++ }
++ else
++ grub_dprintf ("linux", "Loaded Image base address could not be set\n");
++
++ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p\n",
++ kernel_addr, (void *)(grub_efi_uintn_t)handover_offset);
++
++ /* Invalidate the instruction cache */
++ grub_arch_sync_caches((void *)kernel_addr, kernel_size);
++
++ hf = (handover_func)((char *)kernel_addr + handover_offset);
++ hf (grub_efi_image_handle, grub_efi_system_table);
++
++ return GRUB_ERR_BUG;
++ }
++
++ grub_dprintf ("linux", "GRUB_EFI_SECUREBOOT_MODE is NOT enabled\n");
++#endif
++
+ mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
+ if (!mempath)
+ return grub_errno;
+@@ -285,6 +352,7 @@ grub_cmd_linux (grub_command_t cmd __att
+ {
+ grub_file_t file = 0;
+ struct linux_arch_kernel_header lh;
++ struct grub_arm64_linux_pe_header *pe;
+ grub_err_t err;
+
+ grub_dl_ref (my_mod);
+@@ -330,6 +398,9 @@ grub_cmd_linux (grub_command_t cmd __att
+
+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+
++ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
++ handover_offset = pe->opt.entry_addr;
++
+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+ linux_args = grub_malloc (cmdline_size);
+ if (!linux_args)
diff --git a/debian/patches/arm64_remove_magic_number_check.patch b/debian/patches/arm64_remove_magic_number_check.patch
new file mode 100644
index 0000000..acc0897
--- /dev/null
+++ b/debian/patches/arm64_remove_magic_number_check.patch
@@ -0,0 +1,37 @@
+commit 69edb31205602c29293a8c6e67363bba2a4a1e66
+Author: Ard Biesheuvel <ardb@kernel.org>
+Date: Thu Aug 11 16:51:57 2022 +0200
+
+ loader/arm64/linux: Remove magic number header field check
+
+ The "ARM\x64" magic number in the file header identifies an image as one
+ that implements the bare metal boot protocol, allowing the loader to
+ simply move the file to a suitably aligned address in memory, with
+ sufficient headroom for the trailing .bss segment (the required memory
+ size is described in the header as well).
+
+ Note of this matters for GRUB, as it only supports EFI boot. EFI does
+ not care about this magic number, and nor should GRUB: this prevents us
+ from booting other PE linux images, such as the generic EFI zboot
+ decompressor, which is a pure PE/COFF image, and does not implement the
+ bare metal boot protocol.
+
+ So drop the magic number check.
+
+ Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index ef3e9f944..4c92e48ac 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -51,9 +51,6 @@ static grub_addr_t initrd_end;
+ grub_err_t
+ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+ {
+- if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
+- return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+-
+ if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
diff --git a/debian/patches/at_keyboard-module-init.patch b/debian/patches/at_keyboard-module-init.patch
new file mode 100644
index 0000000..deb713d
--- /dev/null
+++ b/debian/patches/at_keyboard-module-init.patch
@@ -0,0 +1,44 @@
+From e619f11201a4d93ce36d384221c899f88f7618c9 Mon Sep 17 00:00:00 2001
+From: Jeroen Dekkers <jeroen@dekkers.ch>
+Date: Sat, 12 Jan 2019 21:02:18 +0100
+Subject: at_keyboard: initialize keyboard in module init if keyboard is ready
+
+The change in 0c62a5b2 caused at_keyboard to fail on some
+machines. Immediately initializing the keyboard in the module init if
+the keyboard is ready makes the problem go away.
+
+Bug-Debian: https://bugs.debian.org/741464
+Last-Update: 2019-02-09
+
+Patch-Name: at_keyboard-module-init.patch
+---
+ grub-core/term/at_keyboard.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
+index 597111077..beb007002 100644
+--- a/grub-core/term/at_keyboard.c
++++ b/grub-core/term/at_keyboard.c
+@@ -244,6 +244,14 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
+ return ret;
+ }
+
++static grub_err_t
++grub_keyboard_controller_mod_init (struct grub_term_input *term __attribute__ ((unused))) {
++ if (KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
++ grub_keyboard_controller_init ();
++
++ return GRUB_ERR_NONE;
++}
++
+ static void
+ grub_keyboard_controller_init (void)
+ {
+@@ -314,6 +322,7 @@ grub_at_restore_hw (void)
+ static struct grub_term_input grub_at_keyboard_term =
+ {
+ .name = "at_keyboard",
++ .init = grub_keyboard_controller_mod_init,
+ .fini = grub_keyboard_controller_fini,
+ .getkey = grub_at_keyboard_getkey
+ };
diff --git a/debian/patches/bash-completion-drop-have-checks.patch b/debian/patches/bash-completion-drop-have-checks.patch
new file mode 100644
index 0000000..c425471
--- /dev/null
+++ b/debian/patches/bash-completion-drop-have-checks.patch
@@ -0,0 +1,143 @@
+From c543561137513e37ae17879366ebf4e10348daa2 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Fri, 16 Nov 2018 16:37:02 +0000
+Subject: bash-completion: Drop "have" checks
+
+These don't work with and aren't needed by dynamically-loaded
+completions.
+
+Bug-Debian: https://bugs.debian.org/912852
+Forwarded: no
+Last-Update: 2018-11-16
+
+Patch-Name: bash-completion-drop-have-checks.patch
+---
+ .../bash-completion.d/grub-completion.bash.in | 39 +++++++------------
+ 1 file changed, 13 insertions(+), 26 deletions(-)
+
+diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
+index 44bf135b9..d4235e7ef 100644
+--- a/util/bash-completion.d/grub-completion.bash.in
++++ b/util/bash-completion.d/grub-completion.bash.in
+@@ -166,13 +166,11 @@ _grub_set_entry () {
+ }
+
+ __grub_set_default_program="@grub_set_default@"
+-have ${__grub_set_default_program} && \
+- complete -F _grub_set_entry -o filenames ${__grub_set_default_program}
++complete -F _grub_set_entry -o filenames ${__grub_set_default_program}
+ unset __grub_set_default_program
+
+ __grub_reboot_program="@grub_reboot@"
+-have ${__grub_reboot_program} && \
+- complete -F _grub_set_entry -o filenames ${__grub_reboot_program}
++complete -F _grub_set_entry -o filenames ${__grub_reboot_program}
+ unset __grub_reboot_program
+
+
+@@ -198,8 +196,7 @@ _grub_editenv () {
+ }
+
+ __grub_editenv_program="@grub_editenv@"
+-have ${__grub_editenv_program} && \
+- complete -F _grub_editenv -o filenames ${__grub_editenv_program}
++complete -F _grub_editenv -o filenames ${__grub_editenv_program}
+ unset __grub_editenv_program
+
+
+@@ -219,8 +216,7 @@ _grub_mkconfig () {
+ fi
+ }
+ __grub_mkconfig_program="@grub_mkconfig@"
+-have ${__grub_mkconfig_program} && \
+- complete -F _grub_mkconfig -o filenames ${__grub_mkconfig_program}
++complete -F _grub_mkconfig -o filenames ${__grub_mkconfig_program}
+ unset __grub_mkconfig_program
+
+
+@@ -254,13 +250,11 @@ _grub_setup () {
+ }
+
+ __grub_bios_setup_program="@grub_bios_setup@"
+-have ${__grub_bios_setup_program} && \
+- complete -F _grub_setup -o filenames ${__grub_bios_setup_program}
++complete -F _grub_setup -o filenames ${__grub_bios_setup_program}
+ unset __grub_bios_setup_program
+
+ __grub_sparc64_setup_program="@grub_sparc64_setup@"
+-have ${__grub_sparc64_setup_program} && \
+- complete -F _grub_setup -o filenames ${__grub_sparc64_setup_program}
++complete -F _grub_setup -o filenames ${__grub_sparc64_setup_program}
+ unset __grub_sparc64_setup_program
+
+
+@@ -305,8 +299,7 @@ _grub_install () {
+ fi
+ }
+ __grub_install_program="@grub_install@"
+-have ${__grub_install_program} && \
+- complete -F _grub_install -o filenames ${__grub_install_program}
++complete -F _grub_install -o filenames ${__grub_install_program}
+ unset __grub_install_program
+
+
+@@ -327,8 +320,7 @@ _grub_mkfont () {
+ fi
+ }
+ __grub_mkfont_program="@grub_mkfont@"
+-have ${__grub_mkfont_program} && \
+- complete -F _grub_mkfont -o filenames ${__grub_mkfont_program}
++complete -F _grub_mkfont -o filenames ${__grub_mkfont_program}
+ unset __grub_mkfont_program
+
+
+@@ -358,8 +350,7 @@ _grub_mkrescue () {
+ fi
+ }
+ __grub_mkrescue_program="@grub_mkrescue@"
+-have ${__grub_mkrescue_program} && \
+- complete -F _grub_mkrescue -o filenames ${__grub_mkrescue_program}
++complete -F _grub_mkrescue -o filenames ${__grub_mkrescue_program}
+ unset __grub_mkrescue_program
+
+
+@@ -400,8 +391,7 @@ _grub_mkimage () {
+ fi
+ }
+ __grub_mkimage_program="@grub_mkimage@"
+-have ${__grub_mkimage_program} && \
+- complete -F _grub_mkimage -o filenames ${__grub_mkimage_program}
++complete -F _grub_mkimage -o filenames ${__grub_mkimage_program}
+ unset __grub_mkimage_program
+
+
+@@ -422,8 +412,7 @@ _grub_mkpasswd_pbkdf2 () {
+ fi
+ }
+ __grub_mkpasswd_pbkdf2_program="@grub_mkpasswd_pbkdf2@"
+-have ${__grub_mkpasswd_pbkdf2_program} && \
+- complete -F _grub_mkpasswd_pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program}
++complete -F _grub_mkpasswd_pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program}
+ unset __grub_mkpasswd_pbkdf2_program
+
+
+@@ -460,8 +449,7 @@ _grub_probe () {
+ fi
+ }
+ __grub_probe_program="@grub_probe@"
+-have ${__grub_probe_program} && \
+- complete -F _grub_probe -o filenames ${__grub_probe_program}
++complete -F _grub_probe -o filenames ${__grub_probe_program}
+ unset __grub_probe_program
+
+
+@@ -482,8 +470,7 @@ _grub_script_check () {
+ fi
+ }
+ __grub_script_check_program="@grub_script_check@"
+-have ${__grub_script_check_program} && \
+- complete -F _grub_script_check -o filenames ${__grub_script_check_program}
++complete -F _grub_script_check -o filenames ${__grub_script_check_program}
+
+
+ # Local variables:
diff --git a/debian/patches/blacklist-1440x900x32.patch b/debian/patches/blacklist-1440x900x32.patch
new file mode 100644
index 0000000..e19fc08
--- /dev/null
+++ b/debian/patches/blacklist-1440x900x32.patch
@@ -0,0 +1,34 @@
+From ee6cee995e403b3fa81798cddb5247be6de3205b Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:11 +0000
+Subject: Blacklist 1440x900x32 from VBE preferred mode handling
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/701111
+Forwarded: no
+Last-Update: 2013-11-14
+
+Patch-Name: blacklist-1440x900x32.patch
+---
+ grub-core/video/i386/pc/vbe.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c
+index b7f911926..4b1bd7d5e 100644
+--- a/grub-core/video/i386/pc/vbe.c
++++ b/grub-core/video/i386/pc/vbe.c
+@@ -1054,6 +1054,15 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
+ || vbe_mode_info.y_resolution > height)
+ /* Resolution exceeds that of preferred mode. */
+ continue;
++
++ /* Blacklist 1440x900x32 from preferred mode handling until a
++ better solution is available. This mode causes problems on
++ many Thinkpads. See:
++ https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/701111 */
++ if (vbe_mode_info.x_resolution == 1440 &&
++ vbe_mode_info.y_resolution == 900 &&
++ vbe_mode_info.bits_per_pixel == 32)
++ continue;
+ }
+ else
+ {
diff --git a/debian/patches/bootp-new-net_bootp6-command.patch b/debian/patches/bootp-new-net_bootp6-command.patch
new file mode 100644
index 0000000..775213a
--- /dev/null
+++ b/debian/patches/bootp-new-net_bootp6-command.patch
@@ -0,0 +1,1119 @@
+From 2ce72d9b58e2166f47603851fb9b66acb314cca1 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 27 Oct 2016 17:41:04 -0400
+Subject: bootp: New net_bootp6 command
+
+Implement new net_bootp6 command for IPv6 network auto configuration via the
+DHCPv6 protocol (RFC3315).
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Last-Update: 2021-09-24
+
+Patch-Name: bootp-new-net_bootp6-command.patch
+---
+ grub-core/net/bootp.c | 908 +++++++++++++++++++++++++++++++++++++++++-
+ grub-core/net/ip.c | 39 ++
+ include/grub/net.h | 72 ++++
+ 3 files changed, 1018 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 6fb562702..00c11af39 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -24,6 +24,98 @@
+ #include <grub/net/netbuff.h>
+ #include <grub/net/udp.h>
+ #include <grub/datetime.h>
++#include <grub/time.h>
++#include <grub/list.h>
++
++static int
++dissect_url (const char *url, char **proto, char **host, char **path)
++{
++ const char *p, *ps;
++ grub_size_t l;
++
++ *proto = *host = *path = NULL;
++ ps = p = url;
++
++ while ((p = grub_strchr (p, ':')))
++ {
++ if (grub_strlen (p) < sizeof ("://") - 1)
++ break;
++ if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0)
++ {
++ l = p - ps;
++ *proto = grub_malloc (l + 1);
++ if (!*proto)
++ {
++ grub_print_error ();
++ return 0;
++ }
++
++ grub_memcpy (*proto, ps, l);
++ (*proto)[l] = '\0';
++ p += sizeof ("://") - 1;
++ break;
++ }
++ ++p;
++ }
++
++ if (!*proto)
++ {
++ grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url);
++ return 0;
++ }
++
++ ps = p;
++ p = grub_strchr (p, '/');
++
++ if (!p)
++ {
++ grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url);
++ grub_free (*proto);
++ *proto = NULL;
++ return 0;
++ }
++
++ l = p - ps;
++
++ if (l > 2 && ps[0] == '[' && ps[l - 1] == ']')
++ {
++ *host = grub_malloc (l - 1);
++ if (!*host)
++ {
++ grub_print_error ();
++ grub_free (*proto);
++ *proto = NULL;
++ return 0;
++ }
++ grub_memcpy (*host, ps + 1, l - 2);
++ (*host)[l - 2] = 0;
++ }
++ else
++ {
++ *host = grub_malloc (l + 1);
++ if (!*host)
++ {
++ grub_print_error ();
++ grub_free (*proto);
++ *proto = NULL;
++ return 0;
++ }
++ grub_memcpy (*host, ps, l);
++ (*host)[l] = 0;
++ }
++
++ *path = grub_strdup (p);
++ if (!*path)
++ {
++ grub_print_error ();
++ grub_free (*host);
++ grub_free (*proto);
++ *host = NULL;
++ *proto = NULL;
++ return 0;
++ }
++ return 1;
++}
+
+ struct grub_dhcp_discover_options
+ {
+@@ -607,6 +699,578 @@ out:
+ return err;
+ }
+
++/* The default netbuff size for sending DHCPv6 packets which should be
++ large enough to hold the information */
++#define GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE 512
++
++struct grub_dhcp6_options
++{
++ grub_uint8_t *client_duid;
++ grub_uint16_t client_duid_len;
++ grub_uint8_t *server_duid;
++ grub_uint16_t server_duid_len;
++ grub_uint32_t iaid;
++ grub_uint32_t t1;
++ grub_uint32_t t2;
++ grub_net_network_level_address_t *ia_addr;
++ grub_uint32_t preferred_lifetime;
++ grub_uint32_t valid_lifetime;
++ grub_net_network_level_address_t *dns_server_addrs;
++ grub_uint16_t num_dns_server;
++ char *boot_file_proto;
++ char *boot_file_server_ip;
++ char *boot_file_path;
++};
++
++typedef struct grub_dhcp6_options *grub_dhcp6_options_t;
++
++struct grub_dhcp6_session
++{
++ struct grub_dhcp6_session *next;
++ struct grub_dhcp6_session **prev;
++ grub_uint32_t iaid;
++ grub_uint32_t transaction_id:24;
++ grub_uint64_t start_time;
++ struct grub_net_dhcp6_option_duid_ll duid;
++ struct grub_net_network_level_interface *iface;
++
++ /* The associated dhcpv6 options */
++ grub_dhcp6_options_t adv;
++ grub_dhcp6_options_t reply;
++};
++
++typedef struct grub_dhcp6_session *grub_dhcp6_session_t;
++
++typedef void (*dhcp6_option_hook_fn) (const struct grub_net_dhcp6_option *opt, void *data);
++
++static void
++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size,
++ dhcp6_option_hook_fn hook, void *hook_data);
++
++static void
++parse_dhcp6_iaaddr (const struct grub_net_dhcp6_option *opt, void *data)
++{
++ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t )data;
++
++ grub_uint16_t code = grub_be_to_cpu16 (opt->code);
++ grub_uint16_t len = grub_be_to_cpu16 (opt->len);
++
++ if (code == GRUB_NET_DHCP6_OPTION_IAADDR)
++ {
++ const struct grub_net_dhcp6_option_iaaddr *iaaddr;
++ iaaddr = (const struct grub_net_dhcp6_option_iaaddr *)opt->data;
++
++ if (len < sizeof (*iaaddr))
++ {
++ grub_dprintf ("bootp", "DHCPv6: code %u with insufficient length %u\n", code, len);
++ return;
++ }
++ if (!dhcp6->ia_addr)
++ {
++ dhcp6->ia_addr = grub_malloc (sizeof(*dhcp6->ia_addr));
++ dhcp6->ia_addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++ dhcp6->ia_addr->ipv6[0] = grub_get_unaligned64 (iaaddr->addr);
++ dhcp6->ia_addr->ipv6[1] = grub_get_unaligned64 (iaaddr->addr + 8);
++ dhcp6->preferred_lifetime = grub_be_to_cpu32 (iaaddr->preferred_lifetime);
++ dhcp6->valid_lifetime = grub_be_to_cpu32 (iaaddr->valid_lifetime);
++ }
++ }
++}
++
++static void
++parse_dhcp6_option (const struct grub_net_dhcp6_option *opt, void *data)
++{
++ grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t)data;
++ grub_uint16_t code = grub_be_to_cpu16 (opt->code);
++ grub_uint16_t len = grub_be_to_cpu16 (opt->len);
++
++ switch (code)
++ {
++ case GRUB_NET_DHCP6_OPTION_CLIENTID:
++
++ if (dhcp6->client_duid || !len)
++ {
++ grub_dprintf ("bootp", "Skipped DHCPv6 CLIENTID with length %u\n", len);
++ break;
++ }
++ dhcp6->client_duid = grub_malloc (len);
++ grub_memcpy (dhcp6->client_duid, opt->data, len);
++ dhcp6->client_duid_len = len;
++ break;
++
++ case GRUB_NET_DHCP6_OPTION_SERVERID:
++
++ if (dhcp6->server_duid || !len)
++ {
++ grub_dprintf ("bootp", "Skipped DHCPv6 SERVERID with length %u\n", len);
++ break;
++ }
++ dhcp6->server_duid = grub_malloc (len);
++ grub_memcpy (dhcp6->server_duid, opt->data, len);
++ dhcp6->server_duid_len = len;
++ break;
++
++ case GRUB_NET_DHCP6_OPTION_IA_NA:
++ {
++ const struct grub_net_dhcp6_option_iana *ia_na;
++ grub_uint16_t data_len;
++
++ if (dhcp6->iaid || len < sizeof (*ia_na))
++ {
++ grub_dprintf ("bootp", "Skipped DHCPv6 IA_NA with length %u\n", len);
++ break;
++ }
++ ia_na = (const struct grub_net_dhcp6_option_iana *)opt->data;
++ dhcp6->iaid = grub_be_to_cpu32 (ia_na->iaid);
++ dhcp6->t1 = grub_be_to_cpu32 (ia_na->t1);
++ dhcp6->t2 = grub_be_to_cpu32 (ia_na->t2);
++
++ data_len = len - sizeof (*ia_na);
++ if (data_len)
++ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)ia_na->data, data_len, parse_dhcp6_iaaddr, dhcp6);
++ }
++ break;
++
++ case GRUB_NET_DHCP6_OPTION_DNS_SERVERS:
++ {
++ const grub_uint8_t *po;
++ grub_uint16_t ln;
++ grub_net_network_level_address_t *la;
++
++ if (!len || len & 0xf)
++ {
++ grub_dprintf ("bootp", "Skip invalid length DHCPv6 DNS_SERVERS \n");
++ break;
++ }
++ dhcp6->num_dns_server = ln = len >> 4;
++ dhcp6->dns_server_addrs = la = grub_calloc (ln, sizeof (*la));
++
++ for (po = opt->data; ln > 0; po += 0x10, la++, ln--)
++ {
++ la->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++ la->ipv6[0] = grub_get_unaligned64 (po);
++ la->ipv6[1] = grub_get_unaligned64 (po + 8);
++ la->option = DNS_OPTION_PREFER_IPV6;
++ }
++ }
++ break;
++
++ case GRUB_NET_DHCP6_OPTION_BOOTFILE_URL:
++ dissect_url ((const char *)opt->data,
++ &dhcp6->boot_file_proto,
++ &dhcp6->boot_file_server_ip,
++ &dhcp6->boot_file_path);
++ break;
++
++ default:
++ break;
++ }
++}
++
++static void
++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, dhcp6_option_hook_fn hook, void *hook_data)
++{
++ while (size)
++ {
++ grub_uint16_t code, len;
++
++ if (size < sizeof (*opt))
++ {
++ grub_dprintf ("bootp", "DHCPv6: Options stopped with remaining size %" PRIxGRUB_SIZE "\n", size);
++ break;
++ }
++ size -= sizeof (*opt);
++ len = grub_be_to_cpu16 (opt->len);
++ code = grub_be_to_cpu16 (opt->code);
++ if (size < len)
++ {
++ grub_dprintf ("bootp", "DHCPv6: Options stopped at out of bound length %u for option %u\n", len, code);
++ break;
++ }
++ if (!len)
++ {
++ grub_dprintf ("bootp", "DHCPv6: Options stopped at zero length option %u\n", code);
++ break;
++ }
++ else
++ {
++ if (hook)
++ hook (opt, hook_data);
++ size -= len;
++ opt = (const struct grub_net_dhcp6_option *)((grub_uint8_t *)opt + len + sizeof (*opt));
++ }
++ }
++}
++
++static grub_dhcp6_options_t
++grub_dhcp6_options_get (const struct grub_net_dhcp6_packet *v6h,
++ grub_size_t size)
++{
++ grub_dhcp6_options_t options;
++
++ if (size < sizeof (*v6h))
++ {
++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small"));
++ return NULL;
++ }
++
++ options = grub_zalloc (sizeof(*options));
++ if (!options)
++ return NULL;
++
++ foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)v6h->dhcp_options,
++ size - sizeof (*v6h), parse_dhcp6_option, options);
++
++ return options;
++}
++
++static void
++grub_dhcp6_options_free (grub_dhcp6_options_t options)
++{
++ if (options->client_duid)
++ grub_free (options->client_duid);
++ if (options->server_duid)
++ grub_free (options->server_duid);
++ if (options->ia_addr)
++ grub_free (options->ia_addr);
++ if (options->dns_server_addrs)
++ grub_free (options->dns_server_addrs);
++ if (options->boot_file_proto)
++ grub_free (options->boot_file_proto);
++ if (options->boot_file_server_ip)
++ grub_free (options->boot_file_server_ip);
++ if (options->boot_file_path)
++ grub_free (options->boot_file_path);
++
++ grub_free (options);
++}
++
++static grub_dhcp6_session_t grub_dhcp6_sessions;
++#define FOR_DHCP6_SESSIONS(var) FOR_LIST_ELEMENTS (var, grub_dhcp6_sessions)
++
++static void
++grub_net_configure_by_dhcp6_info (const char *name,
++ struct grub_net_card *card,
++ grub_dhcp6_options_t dhcp6,
++ int is_def,
++ int flags,
++ struct grub_net_network_level_interface **ret_inf)
++{
++ grub_net_network_level_netaddress_t netaddr;
++ struct grub_net_network_level_interface *inf;
++
++ if (dhcp6->ia_addr)
++ {
++ inf = grub_net_add_addr (name, card, dhcp6->ia_addr, &card->default_address, flags);
++
++ netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++ netaddr.ipv6.base[0] = dhcp6->ia_addr->ipv6[0];
++ netaddr.ipv6.base[1] = 0;
++ netaddr.ipv6.masksize = 64;
++ grub_net_add_route (name, netaddr, inf);
++
++ if (ret_inf)
++ *ret_inf = inf;
++ }
++
++ if (dhcp6->dns_server_addrs)
++ {
++ grub_uint16_t i;
++
++ for (i = 0; i < dhcp6->num_dns_server; ++i)
++ grub_net_add_dns_server (dhcp6->dns_server_addrs + i);
++ }
++
++ if (dhcp6->boot_file_path)
++ grub_env_set_net_property (name, "boot_file", dhcp6->boot_file_path,
++ grub_strlen (dhcp6->boot_file_path));
++
++ if (is_def && dhcp6->boot_file_server_ip)
++ {
++ grub_net_default_server = grub_strdup (dhcp6->boot_file_server_ip);
++ grub_env_set ("net_default_interface", name);
++ grub_env_export ("net_default_interface");
++ }
++}
++
++static void
++grub_dhcp6_session_add (struct grub_net_network_level_interface *iface,
++ grub_uint32_t iaid)
++{
++ grub_dhcp6_session_t se;
++ struct grub_datetime date;
++ grub_err_t err;
++ grub_int64_t t = 0;
++
++ se = grub_malloc (sizeof (*se));
++
++ err = grub_get_datetime (&date);
++ if (err || !grub_datetime2unixtime (&date, &t))
++ {
++ grub_errno = GRUB_ERR_NONE;
++ t = 0;
++ }
++
++ se->iface = iface;
++ se->iaid = iaid;
++ se->transaction_id = t;
++ se->start_time = grub_get_time_ms ();
++ se->duid.type = grub_cpu_to_be16_compile_time (3) ;
++ se->duid.hw_type = grub_cpu_to_be16_compile_time (1);
++ grub_memcpy (&se->duid.hwaddr, &iface->hwaddress.mac, sizeof (se->duid.hwaddr));
++ se->adv = NULL;
++ se->reply = NULL;
++ grub_list_push (GRUB_AS_LIST_P (&grub_dhcp6_sessions), GRUB_AS_LIST (se));
++}
++
++static void
++grub_dhcp6_session_remove (grub_dhcp6_session_t se)
++{
++ grub_list_remove (GRUB_AS_LIST (se));
++ if (se->adv)
++ grub_dhcp6_options_free (se->adv);
++ if (se->reply)
++ grub_dhcp6_options_free (se->reply);
++ grub_free (se);
++}
++
++static void
++grub_dhcp6_session_remove_all (void)
++{
++ grub_dhcp6_session_t se;
++
++ FOR_DHCP6_SESSIONS (se)
++ {
++ grub_dhcp6_session_remove (se);
++ se = grub_dhcp6_sessions;
++ }
++}
++
++static grub_err_t
++grub_dhcp6_session_configure_network (grub_dhcp6_session_t se)
++{
++ char *name;
++
++ name = grub_xasprintf ("%s:dhcp6", se->iface->card->name);
++ if (!name)
++ return grub_errno;
++
++ grub_net_configure_by_dhcp6_info (name, se->iface->card, se->reply, 1, 0, 0);
++ grub_free (name);
++
++ return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_dhcp6_session_send_request (grub_dhcp6_session_t se)
++{
++ struct grub_net_buff *nb;
++ struct grub_net_dhcp6_option *opt;
++ struct grub_net_dhcp6_packet *v6h;
++ struct grub_net_dhcp6_option_iana *ia_na;
++ struct grub_net_dhcp6_option_iaaddr *iaaddr;
++ struct udphdr *udph;
++ grub_net_network_level_address_t multicast;
++ grub_net_link_level_address_t ll_multicast;
++ grub_uint64_t elapsed;
++ struct grub_net_network_level_interface *inf = se->iface;
++ grub_dhcp6_options_t dhcp6 = se->adv;
++ grub_err_t err = GRUB_ERR_NONE;
++
++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL);
++
++ err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
++ if (err)
++ return err;
++
++ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++
++ if (!nb)
++ return grub_errno;
++
++ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ err = grub_netbuff_push (nb, dhcp6->client_duid_len + sizeof (*opt));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++ opt = (struct grub_net_dhcp6_option *)nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID);
++ opt->len = grub_cpu_to_be16 (dhcp6->client_duid_len);
++ grub_memcpy (opt->data, dhcp6->client_duid , dhcp6->client_duid_len);
++
++ err = grub_netbuff_push (nb, dhcp6->server_duid_len + sizeof (*opt));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++ opt = (struct grub_net_dhcp6_option *)nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_SERVERID);
++ opt->len = grub_cpu_to_be16 (dhcp6->server_duid_len);
++ grub_memcpy (opt->data, dhcp6->server_duid , dhcp6->server_duid_len);
++
++ err = grub_netbuff_push (nb, sizeof (*ia_na) + sizeof (*opt));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ if (dhcp6->ia_addr)
++ {
++ err = grub_netbuff_push (nb, sizeof(*iaaddr) + sizeof (*opt));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++ }
++ opt = (struct grub_net_dhcp6_option *)nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
++ opt->len = grub_cpu_to_be16 (sizeof (*ia_na));
++ if (dhcp6->ia_addr)
++ opt->len += grub_cpu_to_be16 (sizeof(*iaaddr) + sizeof (*opt));
++
++ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data;
++ ia_na->iaid = grub_cpu_to_be32 (dhcp6->iaid);
++
++ ia_na->t1 = grub_cpu_to_be32 (dhcp6->t1);
++ ia_na->t2 = grub_cpu_to_be32 (dhcp6->t2);
++
++ if (dhcp6->ia_addr)
++ {
++ opt = (struct grub_net_dhcp6_option *)ia_na->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
++ opt->len = grub_cpu_to_be16 (sizeof (*iaaddr));
++ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)opt->data;
++ grub_set_unaligned64 (iaaddr->addr, dhcp6->ia_addr->ipv6[0]);
++ grub_set_unaligned64 (iaaddr->addr + 8, dhcp6->ia_addr->ipv6[1]);
++
++ iaaddr->preferred_lifetime = grub_cpu_to_be32 (dhcp6->preferred_lifetime);
++ iaaddr->valid_lifetime = grub_cpu_to_be32 (dhcp6->valid_lifetime);
++ }
++
++ err = grub_netbuff_push (nb, sizeof (*opt) + 2 * sizeof (grub_uint16_t));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ opt = (struct grub_net_dhcp6_option*) nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ORO);
++ opt->len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_uint16_t));
++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL));
++ grub_set_unaligned16 (opt->data + 2, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS));
++
++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++ opt = (struct grub_net_dhcp6_option*) nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME);
++ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t));
++
++ /* the time is expressed in hundredths of a second */
++ elapsed = grub_divmod64 (grub_get_time_ms () - se->start_time, 10, 0);
++
++ if (elapsed > 0xffff)
++ elapsed = 0xffff;
++
++ grub_set_unaligned16 (opt->data, grub_cpu_to_be16 ((grub_uint16_t)elapsed));
++
++ err = grub_netbuff_push (nb, sizeof (*v6h));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ v6h = (struct grub_net_dhcp6_packet *) nb->data;
++ v6h->message_type = GRUB_NET_DHCP6_REQUEST;
++ v6h->transaction_id = se->transaction_id;
++
++ err = grub_netbuff_push (nb, sizeof (*udph));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ udph = (struct udphdr *) nb->data;
++ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT);
++ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT);
++ udph->chksum = 0;
++ udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
++
++ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
++ &inf->address,
++ &multicast);
++ err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
++ GRUB_NET_IP_UDP);
++
++ grub_netbuff_free (nb);
++
++ return err;
++}
++
++struct grub_net_network_level_interface *
++grub_net_configure_by_dhcpv6_reply (const char *name,
++ struct grub_net_card *card,
++ grub_net_interface_flags_t flags,
++ const struct grub_net_dhcp6_packet *v6h,
++ grub_size_t size,
++ int is_def,
++ char **device, char **path)
++{
++ struct grub_net_network_level_interface *inf;
++ grub_dhcp6_options_t dhcp6;
++
++ dhcp6 = grub_dhcp6_options_get (v6h, size);
++ if (!dhcp6)
++ {
++ grub_print_error ();
++ return NULL;
++ }
++
++ grub_net_configure_by_dhcp6_info (name, card, dhcp6, is_def, flags, &inf);
++
++ if (device && dhcp6->boot_file_proto && dhcp6->boot_file_server_ip)
++ {
++ *device = grub_xasprintf ("%s,%s", dhcp6->boot_file_proto, dhcp6->boot_file_server_ip);
++ grub_print_error ();
++ }
++ if (path && dhcp6->boot_file_path)
++ {
++ *path = grub_strdup (dhcp6->boot_file_path);
++ grub_print_error ();
++ if (*path)
++ {
++ char *slash;
++ slash = grub_strrchr (*path, '/');
++ if (slash)
++ *slash = 0;
++ else
++ **path = 0;
++ }
++ }
++
++ grub_dhcp6_options_free (dhcp6);
++ return inf;
++}
++
+ /*
+ * This is called directly from net/ip.c:handle_dgram(), because those
+ * BOOTP/DHCP packets are a bit special due to their improper
+@@ -675,6 +1339,77 @@ grub_net_process_dhcp (struct grub_net_buff *nb,
+ }
+ }
+
++grub_err_t
++grub_net_process_dhcp6 (struct grub_net_buff *nb,
++ struct grub_net_card *card __attribute__ ((unused)))
++{
++ const struct grub_net_dhcp6_packet *v6h;
++ grub_dhcp6_session_t se;
++ grub_size_t size;
++ grub_dhcp6_options_t options;
++
++ v6h = (const struct grub_net_dhcp6_packet *) nb->data;
++ size = nb->tail - nb->data;
++
++ options = grub_dhcp6_options_get (v6h, size);
++ if (!options)
++ return grub_errno;
++
++ if (!options->client_duid || !options->server_duid || !options->ia_addr)
++ {
++ grub_dhcp6_options_free (options);
++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Bad DHCPv6 Packet");
++ }
++
++ FOR_DHCP6_SESSIONS (se)
++ {
++ if (se->transaction_id == v6h->transaction_id &&
++ grub_memcmp (options->client_duid, &se->duid, sizeof (se->duid)) == 0 &&
++ se->iaid == options->iaid)
++ break;
++ }
++
++ if (!se)
++ {
++ grub_dprintf ("bootp", "DHCPv6 session not found\n");
++ grub_dhcp6_options_free (options);
++ return GRUB_ERR_NONE;
++ }
++
++ if (v6h->message_type == GRUB_NET_DHCP6_ADVERTISE)
++ {
++ if (se->adv)
++ {
++ grub_dprintf ("bootp", "Skipped DHCPv6 Advertised .. \n");
++ grub_dhcp6_options_free (options);
++ return GRUB_ERR_NONE;
++ }
++
++ se->adv = options;
++ return grub_dhcp6_session_send_request (se);
++ }
++ else if (v6h->message_type == GRUB_NET_DHCP6_REPLY)
++ {
++ if (!se->adv)
++ {
++ grub_dprintf ("bootp", "Skipped DHCPv6 Reply .. \n");
++ grub_dhcp6_options_free (options);
++ return GRUB_ERR_NONE;
++ }
++
++ se->reply = options;
++ grub_dhcp6_session_configure_network (se);
++ grub_dhcp6_session_remove (se);
++ return GRUB_ERR_NONE;
++ }
++ else
++ {
++ grub_dhcp6_options_free (options);
++ }
++
++ return GRUB_ERR_NONE;
++}
++
+ static grub_err_t
+ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char **args)
+@@ -900,7 +1635,174 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+ return err;
+ }
+
+-static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp;
++static grub_err_t
++grub_cmd_bootp6 (struct grub_command *cmd __attribute__ ((unused)),
++ int argc, char **args)
++{
++ struct grub_net_card *card;
++ grub_uint32_t iaid = 0;
++ int interval;
++ grub_err_t err;
++ grub_dhcp6_session_t se;
++
++ err = GRUB_ERR_NONE;
++
++ FOR_NET_CARDS (card)
++ {
++ struct grub_net_network_level_interface *iface;
++
++ if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
++ continue;
++
++ iface = grub_net_ipv6_get_link_local (card, &card->default_address);
++ if (!iface)
++ {
++ grub_dhcp6_session_remove_all ();
++ return grub_errno;
++ }
++
++ grub_dhcp6_session_add (iface, iaid++);
++ }
++
++ for (interval = 200; interval < 10000; interval *= 2)
++ {
++ int done = 1;
++
++ FOR_DHCP6_SESSIONS (se)
++ {
++ struct grub_net_buff *nb;
++ struct grub_net_dhcp6_option *opt;
++ struct grub_net_dhcp6_packet *v6h;
++ struct grub_net_dhcp6_option_duid_ll *duid;
++ struct grub_net_dhcp6_option_iana *ia_na;
++ grub_net_network_level_address_t multicast;
++ grub_net_link_level_address_t ll_multicast;
++ struct udphdr *udph;
++
++ multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++ multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
++ multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL);
++
++ err = grub_net_link_layer_resolve (se->iface,
++ &multicast, &ll_multicast);
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ return err;
++ }
++
++ nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++
++ if (!nb)
++ {
++ grub_dhcp6_session_remove_all ();
++ return grub_errno;
++ }
++
++ err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t));
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ opt = (struct grub_net_dhcp6_option *)nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME);
++ opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t));
++ grub_set_unaligned16 (opt->data, 0);
++
++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*duid));
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ opt = (struct grub_net_dhcp6_option *)nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID);
++ opt->len = grub_cpu_to_be16 (sizeof (*duid));
++
++ duid = (struct grub_net_dhcp6_option_duid_ll *) opt->data;
++ grub_memcpy (duid, &se->duid, sizeof (*duid));
++
++ err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*ia_na));
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ opt = (struct grub_net_dhcp6_option *)nb->data;
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
++ opt->len = grub_cpu_to_be16 (sizeof (*ia_na));
++ ia_na = (struct grub_net_dhcp6_option_iana *)opt->data;
++ ia_na->iaid = grub_cpu_to_be32 (se->iaid);
++ ia_na->t1 = 0;
++ ia_na->t2 = 0;
++
++ err = grub_netbuff_push (nb, sizeof (*v6h));
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ v6h = (struct grub_net_dhcp6_packet *)nb->data;
++ v6h->message_type = GRUB_NET_DHCP6_SOLICIT;
++ v6h->transaction_id = se->transaction_id;
++
++ grub_netbuff_push (nb, sizeof (*udph));
++
++ udph = (struct udphdr *) nb->data;
++ udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT);
++ udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT);
++ udph->chksum = 0;
++ udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
++
++ udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
++ &se->iface->address, &multicast);
++
++ err = grub_net_send_ip_packet (se->iface, &multicast,
++ &ll_multicast, nb, GRUB_NET_IP_UDP);
++ done = 0;
++ grub_netbuff_free (nb);
++
++ if (err)
++ {
++ grub_dhcp6_session_remove_all ();
++ return err;
++ }
++ }
++ if (!done)
++ grub_net_poll_cards (interval, 0);
++ }
++
++ FOR_DHCP6_SESSIONS (se)
++ {
++ grub_error_push ();
++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
++ N_("couldn't autoconfigure %s"),
++ se->iface->card->name);
++ }
++
++ grub_dhcp6_session_remove_all ();
++
++ return err;
++}
++
++static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp, cmd_bootp6;
+
+ void
+ grub_bootp_init (void)
+@@ -914,6 +1816,9 @@ grub_bootp_init (void)
+ cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt,
+ N_("VAR INTERFACE NUMBER DESCRIPTION"),
+ N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
++ cmd_bootp6 = grub_register_command ("net_bootp6", grub_cmd_bootp6,
++ N_("[CARD]"),
++ N_("perform a DHCPv6 autoconfiguration"));
+ }
+
+ void
+@@ -922,4 +1827,5 @@ grub_bootp_fini (void)
+ grub_unregister_command (cmd_getdhcp);
+ grub_unregister_command (cmd_bootp);
+ grub_unregister_command (cmd_dhcp);
++ grub_unregister_command (cmd_bootp6);
+ }
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index ea5edf8f1..01410798b 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -239,6 +239,45 @@ handle_dgram (struct grub_net_buff *nb,
+ {
+ struct udphdr *udph;
+ udph = (struct udphdr *) nb->data;
++
++ if (proto == GRUB_NET_IP_UDP && udph->dst == grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT))
++ {
++ if (udph->chksum)
++ {
++ grub_uint16_t chk, expected;
++ chk = udph->chksum;
++ udph->chksum = 0;
++ expected = grub_net_ip_transport_checksum (nb,
++ GRUB_NET_IP_UDP,
++ source,
++ dest);
++ if (expected != chk)
++ {
++ grub_dprintf ("net", "Invalid UDP checksum. "
++ "Expected %x, got %x\n",
++ grub_be_to_cpu16 (expected),
++ grub_be_to_cpu16 (chk));
++ grub_netbuff_free (nb);
++ return GRUB_ERR_NONE;
++ }
++ udph->chksum = chk;
++ }
++
++ err = grub_netbuff_pull (nb, sizeof (*udph));
++ if (err)
++ {
++ grub_netbuff_free (nb);
++ return err;
++ }
++
++ err = grub_net_process_dhcp6 (nb, card);
++ if (err)
++ grub_print_error ();
++
++ grub_netbuff_free (nb);
++ return GRUB_ERR_NONE;
++ }
++
+ if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68)
+ {
+ const struct grub_net_bootp_packet *bootp;
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 69bfe0947..1cb05627e 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -448,6 +448,66 @@ struct grub_net_bootp_packet
+ grub_uint8_t vendor[0];
+ } GRUB_PACKED;
+
++struct grub_net_dhcp6_packet
++{
++ grub_uint32_t message_type:8;
++ grub_uint32_t transaction_id:24;
++ grub_uint8_t dhcp_options[0];
++} GRUB_PACKED;
++
++struct grub_net_dhcp6_option {
++ grub_uint16_t code;
++ grub_uint16_t len;
++ grub_uint8_t data[0];
++} GRUB_PACKED;
++
++struct grub_net_dhcp6_option_iana {
++ grub_uint32_t iaid;
++ grub_uint32_t t1;
++ grub_uint32_t t2;
++ grub_uint8_t data[0];
++} GRUB_PACKED;
++
++struct grub_net_dhcp6_option_iaaddr {
++ grub_uint8_t addr[16];
++ grub_uint32_t preferred_lifetime;
++ grub_uint32_t valid_lifetime;
++ grub_uint8_t data[0];
++} GRUB_PACKED;
++
++struct grub_net_dhcp6_option_duid_ll
++{
++ grub_uint16_t type;
++ grub_uint16_t hw_type;
++ grub_uint8_t hwaddr[6];
++} GRUB_PACKED;
++
++enum
++ {
++ GRUB_NET_DHCP6_SOLICIT = 1,
++ GRUB_NET_DHCP6_ADVERTISE = 2,
++ GRUB_NET_DHCP6_REQUEST = 3,
++ GRUB_NET_DHCP6_REPLY = 7
++ };
++
++enum
++ {
++ DHCP6_CLIENT_PORT = 546,
++ DHCP6_SERVER_PORT = 547
++ };
++
++enum
++ {
++ GRUB_NET_DHCP6_OPTION_CLIENTID = 1,
++ GRUB_NET_DHCP6_OPTION_SERVERID = 2,
++ GRUB_NET_DHCP6_OPTION_IA_NA = 3,
++ GRUB_NET_DHCP6_OPTION_IAADDR = 5,
++ GRUB_NET_DHCP6_OPTION_ORO = 6,
++ GRUB_NET_DHCP6_OPTION_ELAPSED_TIME = 8,
++ GRUB_NET_DHCP6_OPTION_DNS_SERVERS = 23,
++ GRUB_NET_DHCP6_OPTION_BOOTFILE_URL = 59
++ };
++
+ #define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63
+ #define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82
+ #define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53
+@@ -483,6 +543,14 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ grub_size_t size,
+ int is_def, char **device, char **path);
+
++struct grub_net_network_level_interface *
++grub_net_configure_by_dhcpv6_reply (const char *name,
++ struct grub_net_card *card,
++ grub_net_interface_flags_t flags,
++ const struct grub_net_dhcp6_packet *v6,
++ grub_size_t size,
++ int is_def, char **device, char **path);
++
+ grub_err_t
+ grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf,
+ int mask);
+@@ -491,6 +559,10 @@ void
+ grub_net_process_dhcp (struct grub_net_buff *nb,
+ struct grub_net_network_level_interface *iface);
+
++grub_err_t
++grub_net_process_dhcp6 (struct grub_net_buff *nb,
++ struct grub_net_card *card);
++
+ int
+ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
+ const grub_net_link_level_address_t *b);
diff --git a/debian/patches/bootp-process-dhcpack-http-boot.patch b/debian/patches/bootp-process-dhcpack-http-boot.patch
new file mode 100644
index 0000000..64b19f6
--- /dev/null
+++ b/debian/patches/bootp-process-dhcpack-http-boot.patch
@@ -0,0 +1,124 @@
+From cd78a54e5fa8d4a6f9223b7ddbb7db86ca0dd993 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 27 Oct 2016 17:42:19 -0400
+Subject: bootp: Add processing DHCPACK packet from HTTP Boot
+
+The vendor class identifier with the string "HTTPClient" is used to denote the
+packet as responding to HTTP boot request. In DHCP4 config, the filename for
+HTTP boot is the URL of the boot file while for PXE boot it is the path to the
+boot file. As a consequence, the next-server becomes obseleted because the HTTP
+URL already contains the server address for the boot file. For DHCP6 config,
+there's no difference definition in existing config as dhcp6.bootfile-url can
+be used to specify URL for both HTTP and PXE boot file.
+
+This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK
+packet by treating it as HTTP format, not as the PXE format.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Last-Update: 2021-09-24
+
+Patch-Name: bootp-process-dhcpack-http-boot.patch
+---
+ grub-core/net/bootp.c | 60 ++++++++++++++++++++++++++++++++++++++++++-
+ include/grub/net.h | 1 +
+ 2 files changed, 60 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 00c11af39..f35d582b8 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -154,7 +154,7 @@ struct grub_dhcp_request_options
+ {
+ grub_uint8_t type;
+ grub_uint8_t len;
+- grub_uint8_t data[7];
++ grub_uint8_t data[8];
+ } GRUB_PACKED parameter_request;
+ grub_uint8_t end;
+ } GRUB_PACKED;
+@@ -542,6 +542,63 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ grub_free (val);
+ }
+
++ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER,
++ &opt_len);
++ if (opt && opt_len)
++ {
++ grub_env_set_net_property (name, "vendor_class_identifier",
++ (const char *) opt, opt_len);
++ if (opt_len == sizeof ("HTTPClient") - 1 &&
++ grub_memcmp (opt, "HTTPClient", sizeof ("HTTPClient") - 1) == 0)
++ {
++ char *proto, *ip, *pa;
++
++ if (!dissect_url (bp->boot_file, &proto, &ip, &pa))
++ return inter;
++
++ grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa));
++ if (is_def)
++ {
++ grub_net_default_server = grub_strdup (ip);
++ grub_env_set ("net_default_interface", name);
++ grub_env_export ("net_default_interface");
++ }
++ if (device && !*device)
++ {
++ *device = grub_xasprintf ("%s,%s", proto, ip);
++ grub_print_error ();
++ }
++ if (path)
++ {
++ *path = grub_strdup (pa);
++ grub_print_error ();
++ if (*path)
++ {
++ char *slash;
++ slash = grub_strrchr (*path, '/');
++ if (slash)
++ *slash = 0;
++ else
++ **path = 0;
++ }
++ }
++ grub_net_add_ipv4_local (inter, mask);
++ inter->dhcp_ack = grub_malloc (size);
++ if (inter->dhcp_ack)
++ {
++ grub_memcpy (inter->dhcp_ack, bp, size);
++ inter->dhcp_acklen = size;
++ }
++ else
++ grub_errno = GRUB_ERR_NONE;
++
++ grub_free (proto);
++ grub_free (ip);
++ grub_free (pa);
++ return inter;
++ }
++ }
++
+ inter->dhcp_ack = grub_malloc (size);
+ if (inter->dhcp_ack)
+ {
+@@ -616,6 +673,7 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface)
+ GRUB_NET_BOOTP_HOSTNAME,
+ GRUB_NET_BOOTP_ROOT_PATH,
+ GRUB_NET_BOOTP_EXTENSIONS_PATH,
++ GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER,
+ },
+ },
+ GRUB_NET_BOOTP_END,
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 1cb05627e..cbcae79b1 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -528,6 +528,7 @@ enum
+ GRUB_NET_DHCP_MESSAGE_TYPE = 53,
+ GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
+ GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55,
++ GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60,
+ GRUB_NET_BOOTP_CLIENT_ID = 61,
+ GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
+ GRUB_NET_DHCP_BOOTFILE_NAME = 67,
diff --git a/debian/patches/core-in-fs.patch b/debian/patches/core-in-fs.patch
new file mode 100644
index 0000000..1f18554
--- /dev/null
+++ b/debian/patches/core-in-fs.patch
@@ -0,0 +1,45 @@
+From bd289b232f3e9ddaa378d02f0f0040c2171078a4 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:12:51 +0000
+Subject: Write marker if core.img was written to filesystem
+
+The Debian bug reporting script includes a warning in this case.
+
+Patch-Name: core-in-fs.patch
+---
+ util/setup.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/util/setup.c b/util/setup.c
+index da5f2c07f..d1902656e 100644
+--- a/util/setup.c
++++ b/util/setup.c
+@@ -58,6 +58,8 @@
+
+ #include <errno.h>
+
++#define CORE_IMG_IN_FS "setup_left_core_image_in_filesystem"
++
+ /* On SPARC this program fills in various fields inside of the 'boot' and 'core'
+ * image files.
+ *
+@@ -670,6 +672,8 @@ SETUP (const char *dir,
+ #endif
+ grub_free (sectors);
+
++ unlink (DEFAULT_DIRECTORY "/" CORE_IMG_IN_FS);
++
+ goto finish;
+ }
+
+@@ -711,6 +715,10 @@ unable_to_embed:
+ /* The core image must be put on a filesystem unfortunately. */
+ grub_util_info ("will leave the core image on the filesystem");
+
++ fp = grub_util_fd_open (DEFAULT_DIRECTORY "/" CORE_IMG_IN_FS,
++ GRUB_UTIL_FD_O_WRONLY);
++ grub_util_fd_close (fp);
++
+ grub_util_biosdisk_flush (root_dev->disk);
+
+ /* Clean out the blocklists. */
diff --git a/debian/patches/cve_2022_2601/0001-video-readers-Add-artificial-limit-to-image-dimensio.patch b/debian/patches/cve_2022_2601/0001-video-readers-Add-artificial-limit-to-image-dimensio.patch
new file mode 100644
index 0000000..99c2f5a
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0001-video-readers-Add-artificial-limit-to-image-dimensio.patch
@@ -0,0 +1,109 @@
+From a85714545fe57a86d14ee231a4cd312158101d43 Mon Sep 17 00:00:00 2001
+From: Alec Brown <alec.r.brown@oracle.com>
+Date: Wed, 26 Oct 2022 20:16:44 -0400
+Subject: [PATCH 01/14] video/readers: Add artificial limit to image dimensions
+
+In grub-core/video/readers/jpeg.c, the height and width of a JPEG image don't
+have an upper limit for how big the JPEG image can be. In Coverity, this is
+getting flagged as an untrusted loop bound. This issue can also seen in PNG and
+TGA format images as well but Coverity isn't flagging it. To prevent this, the
+constant IMAGE_HW_MAX_PX is being added to include/grub/bitmap.h, which has
+a value of 16384, to act as an artificial limit and restrict the height and
+width of images. This value was picked as it is double the current max
+resolution size, which is 8K.
+
+Fixes: CID 292450
+
+Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
+Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ docs/grub.texi | 3 ++-
+ grub-core/video/readers/jpeg.c | 6 +++++-
+ grub-core/video/readers/png.c | 6 +++++-
+ grub-core/video/readers/tga.c | 7 +++++++
+ include/grub/bitmap.h | 2 ++
+ 5 files changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 0dbbdc374..2d6cd8358 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -1515,7 +1515,8 @@ resolution. @xref{gfxmode}.
+ Set a background image for use with the @samp{gfxterm} graphical terminal.
+ The value of this option must be a file readable by GRUB at boot time, and
+ it must end with @file{.png}, @file{.tga}, @file{.jpg}, or @file{.jpeg}.
+-The image will be scaled if necessary to fit the screen.
++The image will be scaled if necessary to fit the screen. Image height and
++width will be restricted by an artificial limit of 16384.
+
+ @item GRUB_THEME
+ Set a theme for use with the @samp{gfxterm} graphical terminal.
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index 09596fbf5..ae634fd41 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -346,7 +346,11 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
+ data->image_height = grub_jpeg_get_word (data);
+ data->image_width = grub_jpeg_get_word (data);
+
+- if ((!data->image_height) || (!data->image_width))
++ grub_dprintf ("jpeg", "image height: %d\n", data->image_height);
++ grub_dprintf ("jpeg", "image width: %d\n", data->image_width);
++
++ if ((!data->image_height) || (!data->image_width) ||
++ (data->image_height > IMAGE_HW_MAX_PX) || (data->image_width > IMAGE_HW_MAX_PX))
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid image size");
+
+ cc = grub_jpeg_get_byte (data);
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 7f2ba7849..3163e97bf 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -264,7 +264,11 @@ grub_png_decode_image_header (struct grub_png_data *data)
+ data->image_width = grub_png_get_dword (data);
+ data->image_height = grub_png_get_dword (data);
+
+- if ((!data->image_height) || (!data->image_width))
++ grub_dprintf ("png", "image height: %d\n", data->image_height);
++ grub_dprintf ("png", "image width: %d\n", data->image_width);
++
++ if ((!data->image_height) || (!data->image_width) ||
++ (data->image_height > IMAGE_HW_MAX_PX) || (data->image_width > IMAGE_HW_MAX_PX))
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
+
+ color_bits = grub_png_get_byte (data);
+diff --git a/grub-core/video/readers/tga.c b/grub-core/video/readers/tga.c
+index a9ec3a1b6..9c35bf29d 100644
+--- a/grub-core/video/readers/tga.c
++++ b/grub-core/video/readers/tga.c
+@@ -340,6 +340,13 @@ grub_video_reader_tga (struct grub_video_bitmap **bitmap,
+ data.image_width = grub_le_to_cpu16 (data.hdr.image_width);
+ data.image_height = grub_le_to_cpu16 (data.hdr.image_height);
+
++ grub_dprintf ("tga", "image height: %d\n", data.image_height);
++ grub_dprintf ("tga", "image width: %d\n", data.image_width);
++
++ /* Check image height and width are within restrictions. */
++ if ((data.image_height > IMAGE_HW_MAX_PX) || (data.image_width > IMAGE_HW_MAX_PX))
++ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "tga: invalid image size");
++
+ /* Check that bitmap encoding is supported. */
+ switch (data.hdr.image_type)
+ {
+diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h
+index 5728f8ca3..149d37bfe 100644
+--- a/include/grub/bitmap.h
++++ b/include/grub/bitmap.h
+@@ -24,6 +24,8 @@
+ #include <grub/types.h>
+ #include <grub/video.h>
+
++#define IMAGE_HW_MAX_PX 16384
++
+ struct grub_video_bitmap
+ {
+ /* Bitmap format description. */
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0002-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch b/debian/patches/cve_2022_2601/0002-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch
new file mode 100644
index 0000000..7330e5a
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0002-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch
@@ -0,0 +1,33 @@
+From 5760fcfd466cc757540ea0d591bad6a08caeaa16 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Wed, 3 Aug 2022 19:45:33 +0800
+Subject: [PATCH 02/14] font: Reject glyphs exceeds font->max_glyph_width or
+ font->max_glyph_height
+
+Check glyph's width and height against limits specified in font's
+metadata. Reject the glyph (and font) if such limits are exceeded.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 42189c325..756ca0abf 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+ || read_be_uint16 (font->file, &height) != 0
+ || read_be_int16 (font->file, &xoff) != 0
+ || read_be_int16 (font->file, &yoff) != 0
+- || read_be_int16 (font->file, &dwidth) != 0)
++ || read_be_int16 (font->file, &dwidth) != 0
++ || width > font->max_char_width
++ || height > font->max_char_height)
+ {
+ remove_font (font);
+ return 0;
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0003-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch b/debian/patches/cve_2022_2601/0003-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch
new file mode 100644
index 0000000..46ccb00
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0003-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch
@@ -0,0 +1,110 @@
+From 941d10ad6f1dcbd12fb613002249e29ba035f985 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 00:51:20 +0800
+Subject: [PATCH 03/14] font: Fix size overflow in
+ grub_font_get_glyph_internal()
+
+The length of memory allocation and file read may overflow. This patch
+fixes the problem by using safemath macros.
+
+There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe
+if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz().
+It is safe replacement for such code. It has safemath-like prototype.
+
+This patch also introduces grub_cast(value, pointer), it casts value to
+typeof(*pointer) then store the value to *pointer. It returns true when
+overflow occurs or false if there is no overflow. The semantics of arguments
+and return value are designed to be consistent with other safemath macros.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 17 +++++++++++++----
+ include/grub/bitmap.h | 18 ++++++++++++++++++
+ include/grub/safemath.h | 2 ++
+ 3 files changed, 33 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 2f09a4a55..6a3fbebbd 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+ grub_int16_t xoff;
+ grub_int16_t yoff;
+ grub_int16_t dwidth;
+- int len;
++ grub_ssize_t len;
++ grub_size_t sz;
+
+ if (index_entry->glyph)
+ /* Return cached glyph. */
+@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+ return 0;
+ }
+
+- len = (width * height + 7) / 8;
+- glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
+- if (!glyph)
++ /* Calculate real struct size of current glyph. */
++ if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) ||
++ grub_add (sizeof (struct grub_font_glyph), len, &sz))
++ {
++ remove_font (font);
++ return 0;
++ }
++
++ /* Allocate and initialize the glyph struct. */
++ glyph = grub_malloc (sz);
++ if (glyph == NULL)
+ {
+ remove_font (font);
+ return 0;
+diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h
+index 149d37bfe..431048936 100644
+--- a/include/grub/bitmap.h
++++ b/include/grub/bitmap.h
+@@ -23,6 +23,7 @@
+ #include <grub/symbol.h>
+ #include <grub/types.h>
+ #include <grub/video.h>
++#include <grub/safemath.h>
+
+ #define IMAGE_HW_MAX_PX 16384
+
+@@ -81,6 +82,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap)
+ return bitmap->mode_info.height;
+ }
+
++/*
++ * Calculate and store the size of data buffer of 1bit bitmap in result.
++ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs.
++ * Return true when overflow occurs or false if there is no overflow.
++ * This function is intentionally implemented as a macro instead of
++ * an inline function. Although a bit awkward, it preserves data types for
++ * safemath macros and reduces macro side effects as much as possible.
++ *
++ * XXX: Will report false overflow if width * height > UINT64_MAX.
++ */
++#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \
++({ \
++ grub_uint64_t _bitmap_pixels; \
++ grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \
++ grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \
++})
++
+ void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap,
+ struct grub_video_mode_info *mode_info);
+
+diff --git a/include/grub/safemath.h b/include/grub/safemath.h
+index c17b89bba..bb0f826de 100644
+--- a/include/grub/safemath.h
++++ b/include/grub/safemath.h
+@@ -30,6 +30,8 @@
+ #define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res)
+ #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
+
++#define grub_cast(a, res) grub_add ((a), 0, (res))
++
+ #else
+ #error gcc 5.1 or newer or clang 3.8 or newer is required
+ #endif
diff --git a/debian/patches/cve_2022_2601/0004-font-Fix-several-integer-overflows-in-grub_font_cons.patch b/debian/patches/cve_2022_2601/0004-font-Fix-several-integer-overflows-in-grub_font_cons.patch
new file mode 100644
index 0000000..9d3c9b2
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0004-font-Fix-several-integer-overflows-in-grub_font_cons.patch
@@ -0,0 +1,81 @@
+From b1805f251b31a9d3cfae5c3572ddfa630145dbbf Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 01:58:27 +0800
+Subject: [PATCH 04/14] font: Fix several integer overflows in
+ grub_font_construct_glyph()
+
+This patch fixes several integer overflows in grub_font_construct_glyph().
+Glyphs of invalid size, zero or leading to an overflow, are rejected.
+The inconsistency between "glyph" and "max_glyph_size" when grub_malloc()
+returns NULL is fixed too.
+
+Fixes: CVE-2022-2601
+
+Reported-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index e781521a7..e6548892f 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font,
+ struct grub_video_signed_rect bounds;
+ static struct grub_font_glyph *glyph = 0;
+ static grub_size_t max_glyph_size = 0;
++ grub_size_t cur_glyph_size;
+
+ ensure_comb_space (glyph_id);
+
+@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font,
+ if (!glyph_id->ncomb && !glyph_id->attributes)
+ return main_glyph;
+
+- if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT)
++ if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) ||
++ grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size))
++ return main_glyph;
++
++ if (max_glyph_size < cur_glyph_size)
+ {
+ grub_free (glyph);
+- max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2;
+- if (max_glyph_size < 8)
+- max_glyph_size = 8;
+- glyph = grub_malloc (max_glyph_size);
++ if (grub_mul (cur_glyph_size, 2, &max_glyph_size))
++ max_glyph_size = 0;
++ glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL;
+ }
+ if (!glyph)
+ {
++ max_glyph_size = 0;
+ grub_errno = GRUB_ERR_NONE;
+ return main_glyph;
+ }
+
+- grub_memset (glyph, 0, sizeof (*glyph)
+- + (bounds.width * bounds.height
+- + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT);
++ grub_memset (glyph, 0, cur_glyph_size);
+
+ glyph->font = main_glyph->font;
+- glyph->width = bounds.width;
+- glyph->height = bounds.height;
+- glyph->offset_x = bounds.x;
+- glyph->offset_y = bounds.y;
++ if (bounds.width == 0 || bounds.height == 0 ||
++ grub_cast (bounds.width, &glyph->width) ||
++ grub_cast (bounds.height, &glyph->height) ||
++ grub_cast (bounds.x, &glyph->offset_x) ||
++ grub_cast (bounds.y, &glyph->offset_y))
++ return main_glyph;
+
+ if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR)
+ grub_font_blit_glyph_mirror (glyph, main_glyph,
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0005-font-Remove-grub_font_dup_glyph.patch b/debian/patches/cve_2022_2601/0005-font-Remove-grub_font_dup_glyph.patch
new file mode 100644
index 0000000..7c957a6
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0005-font-Remove-grub_font_dup_glyph.patch
@@ -0,0 +1,42 @@
+From 25ad31c19c331aaa2dbd9bd2b2e2655de5766a9d Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 02:13:29 +0800
+Subject: [PATCH 05/14] font: Remove grub_font_dup_glyph()
+
+Remove grub_font_dup_glyph() since nobody is using it since 2013, and
+I'm too lazy to fix the integer overflow problem in it.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 14 --------------
+ 1 file changed, 14 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index e6548892f..a8576ffec 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
+ return best_glyph;
+ }
+
+-#if 0
+-static struct grub_font_glyph *
+-grub_font_dup_glyph (struct grub_font_glyph *glyph)
+-{
+- static struct grub_font_glyph *ret;
+- ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8);
+- if (!ret)
+- return NULL;
+- grub_memcpy (ret, glyph, sizeof (*ret)
+- + (glyph->width * glyph->height + 7) / 8);
+- return ret;
+-}
+-#endif
+-
+ /* FIXME: suboptimal. */
+ static void
+ grub_font_blit_glyph (struct grub_font_glyph *target,
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0006-font-Fix-integer-overflow-in-ensure_comb_space.patch b/debian/patches/cve_2022_2601/0006-font-Fix-integer-overflow-in-ensure_comb_space.patch
new file mode 100644
index 0000000..f35c646
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0006-font-Fix-integer-overflow-in-ensure_comb_space.patch
@@ -0,0 +1,48 @@
+From b2740b7e4a03bb8331d48b54b119afea76bb9d5f Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 02:27:05 +0800
+Subject: [PATCH 06/14] font: Fix integer overflow in ensure_comb_space()
+
+In fact it can't overflow at all because glyph_id->ncomb is only 8-bit
+wide. But let's keep safe if somebody changes the width of glyph_id->ncomb
+in the future. This patch also fixes the inconsistency between
+render_max_comb_glyphs and render_combining_glyphs when grub_malloc()
+returns NULL.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index a8576ffec..9e3e0a94e 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id)
+ if (glyph_id->ncomb <= render_max_comb_glyphs)
+ return;
+
+- render_max_comb_glyphs = 2 * glyph_id->ncomb;
+- if (render_max_comb_glyphs < 8)
++ if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs))
++ render_max_comb_glyphs = 0;
++ if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8)
+ render_max_comb_glyphs = 8;
+ grub_free (render_combining_glyphs);
+- render_combining_glyphs = grub_malloc (render_max_comb_glyphs
+- * sizeof (render_combining_glyphs[0]));
++ render_combining_glyphs = (render_max_comb_glyphs > 0) ?
++ grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL;
+ if (!render_combining_glyphs)
+- grub_errno = 0;
++ {
++ render_max_comb_glyphs = 0;
++ grub_errno = GRUB_ERR_NONE;
++ }
+ }
+
+ int
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0007-font-Fix-integer-overflow-in-BMP-index.patch b/debian/patches/cve_2022_2601/0007-font-Fix-integer-overflow-in-BMP-index.patch
new file mode 100644
index 0000000..7d426f0
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0007-font-Fix-integer-overflow-in-BMP-index.patch
@@ -0,0 +1,65 @@
+From afda8b60ba0712abe01ae1e64c5f7a067a0e6492 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Mon, 15 Aug 2022 02:04:58 +0800
+Subject: [PATCH 07/14] font: Fix integer overflow in BMP index
+
+The BMP index (font->bmp_idx) is designed as a reverse lookup table of
+char entries (font->char_index), in order to speed up lookups for BMP
+chars (i.e. code < 0x10000). The values in BMP index are the subscripts
+of the corresponding char entries, stored in grub_uint16_t, while 0xffff
+means not found.
+
+This patch fixes the problem of large subscript truncated to grub_uint16_t,
+leading BMP index to return wrong char entry or report false miss. The
+code now checks for bounds and uses BMP index as a hint, and fallbacks
+to binary-search if necessary.
+
+On the occasion add a comment about BMP index is initialized to 0xffff.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 9e3e0a94e..e4cb0d867 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+ font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
+ if (!font->bmp_idx)
+ return 1;
++
++ /* Init the BMP index array to 0xffff. */
+ grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t));
+
+
+@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+ return 1;
+ }
+
+- if (entry->code < 0x10000)
++ if (entry->code < 0x10000 && i < 0xffff)
+ font->bmp_idx[entry->code] = i;
+
+ last_code = entry->code;
+@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
+ /* Use BMP index if possible. */
+ if (code < 0x10000 && font->bmp_idx)
+ {
+- if (font->bmp_idx[code] == 0xffff)
+- return 0;
+- return &table[font->bmp_idx[code]];
++ if (font->bmp_idx[code] < 0xffff)
++ return &table[font->bmp_idx[code]];
++ /*
++ * When we are here then lookup in BMP index result in miss,
++ * fallthough to binary-search.
++ */
+ }
+
+ /* Do a binary search in `char_index', which is ordered by code point. */
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0008-font-Fix-integer-underflow-in-binary-search-of-char-.patch b/debian/patches/cve_2022_2601/0008-font-Fix-integer-underflow-in-binary-search-of-char-.patch
new file mode 100644
index 0000000..0db8d15
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0008-font-Fix-integer-underflow-in-binary-search-of-char-.patch
@@ -0,0 +1,86 @@
+From c140a086838e7c9af87842036f891b8393a8c4bc Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Sun, 14 Aug 2022 18:09:38 +0800
+Subject: [PATCH 08/14] font: Fix integer underflow in binary search of char
+ index
+
+If search target is less than all entries in font->index then "hi"
+variable is set to -1, which translates to SIZE_MAX and leads to errors.
+
+This patch fixes the problem by replacing the entire binary search code
+with the libstdc++'s std::lower_bound() implementation.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 40 ++++++++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 18 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index e4cb0d867..abd412a5e 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value)
+ static inline struct char_index_entry *
+ find_glyph (const grub_font_t font, grub_uint32_t code)
+ {
+- struct char_index_entry *table;
+- grub_size_t lo;
+- grub_size_t hi;
+- grub_size_t mid;
++ struct char_index_entry *table, *first, *end;
++ grub_size_t len;
+
+ table = font->char_index;
++ if (table == NULL)
++ return NULL;
+
+ /* Use BMP index if possible. */
+ if (code < 0x10000 && font->bmp_idx)
+@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
+ */
+ }
+
+- /* Do a binary search in `char_index', which is ordered by code point. */
+- lo = 0;
+- hi = font->num_chars - 1;
+-
+- if (!table)
+- return 0;
++ /*
++ * Do a binary search in char_index which is ordered by code point.
++ * The code below is the same as libstdc++'s std::lower_bound().
++ */
++ first = table;
++ len = font->num_chars;
++ end = first + len;
+
+- while (lo <= hi)
++ while (len > 0)
+ {
+- mid = lo + (hi - lo) / 2;
+- if (code < table[mid].code)
+- hi = mid - 1;
+- else if (code > table[mid].code)
+- lo = mid + 1;
++ grub_size_t half = len >> 1;
++ struct char_index_entry *middle = first + half;
++
++ if (middle->code < code)
++ {
++ first = middle + 1;
++ len = len - half - 1;
++ }
+ else
+- return &table[mid];
++ len = half;
+ }
+
+- return 0;
++ return (first < end && first->code == code) ? first : NULL;
+ }
+
+ /* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0009-kern-efi-sb-Enforce-verification-of-font-files.patch b/debian/patches/cve_2022_2601/0009-kern-efi-sb-Enforce-verification-of-font-files.patch
new file mode 100644
index 0000000..705835a
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0009-kern-efi-sb-Enforce-verification-of-font-files.patch
@@ -0,0 +1,54 @@
+From 630deb8c0d8b02b670ced4b7030414bcf17aa080 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Sun, 14 Aug 2022 15:51:54 +0800
+Subject: [PATCH 09/14] kern/efi/sb: Enforce verification of font files
+
+As a mitigation and hardening measure enforce verification of font
+files. Then only trusted font files can be load. This will reduce the
+attack surface at cost of losing the ability of end-users to customize
+fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize
+fonts because they have ability to pack fonts into their GRUB bundles.
+
+This goal is achieved by:
+
+ * Removing GRUB_FILE_TYPE_FONT from shim lock verifier's
+ skip-verification list.
+
+ * Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list,
+ so font files must be verified by a verifier before they can be loaded.
+
+Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/efi/sb.c | 1 -
+ grub-core/kern/lockdown.c | 1 +
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
+index 89c4bb3fd..db42c2539 100644
+--- a/grub-core/kern/efi/sb.c
++++ b/grub-core/kern/efi/sb.c
+@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+ case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
+ case GRUB_FILE_TYPE_TESTLOAD:
+ case GRUB_FILE_TYPE_GET_SIZE:
+- case GRUB_FILE_TYPE_FONT:
+ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
+ case GRUB_FILE_TYPE_CAT:
+ case GRUB_FILE_TYPE_HEXCAT:
+diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
+index 0bc70fd42..af6d493cd 100644
+--- a/grub-core/kern/lockdown.c
++++ b/grub-core/kern/lockdown.c
+@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)),
+ case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
+ case GRUB_FILE_TYPE_ACPI_TABLE:
+ case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
++ case GRUB_FILE_TYPE_FONT:
+ *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+
+ /* Fall through. */
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0010-fbutil-Fix-integer-overflow.patch b/debian/patches/cve_2022_2601/0010-fbutil-Fix-integer-overflow.patch
new file mode 100644
index 0000000..8dcac96
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0010-fbutil-Fix-integer-overflow.patch
@@ -0,0 +1,85 @@
+From 50a11a81bc842c58962244a2dc86bbd31a426e12 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Tue, 6 Sep 2022 03:03:21 +0800
+Subject: [PATCH 10/14] fbutil: Fix integer overflow
+
+Expressions like u64 = u32 * u32 are unsafe because their products are
+truncated to u32 even if left hand side is u64. This patch fixes all
+problems like that one in fbutil.
+
+To get right result not only left hand side have to be u64 but it's also
+necessary to cast at least one of the operands of all leaf operators of
+right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be
+u64 = (u64)u32 * u32 + (u64)u32 * u32.
+
+For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any
+combination of values in (grub_uint64_t)u32 * u32 + u32 expression will
+not overflow grub_uint64_t.
+
+Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable.
+They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32.
+
+This patch also adds a comment to grub_video_fb_get_video_ptr() which
+says it's arguments must be valid and no sanity check is performed
+(like its siblings in grub-core/video/fb/fbutil.c).
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/fb/fbutil.c | 4 ++--
+ include/grub/fbutil.h | 13 +++++++++----
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c
+index b98bb51fe..25ef39f47 100644
+--- a/grub-core/video/fb/fbutil.c
++++ b/grub-core/video/fb/fbutil.c
+@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source,
+ case 1:
+ if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+- int bit_index = y * source->mode_info->width + x;
++ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x;
+ grub_uint8_t *ptr = source->data + bit_index / 8;
+ int bit_pos = 7 - bit_index % 8;
+ color = (*ptr >> bit_pos) & 0x01;
+@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source,
+ case 1:
+ if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+ {
+- int bit_index = y * source->mode_info->width + x;
++ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x;
+ grub_uint8_t *ptr = source->data + bit_index / 8;
+ int bit_pos = 7 - bit_index % 8;
+ *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos);
+diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h
+index 4205eb917..78a1ab3b4 100644
+--- a/include/grub/fbutil.h
++++ b/include/grub/fbutil.h
+@@ -31,14 +31,19 @@ struct grub_video_fbblit_info
+ grub_uint8_t *data;
+ };
+
+-/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level
+- and it doesn't make sense, in general, to ask for a pointer
+- to a particular pixel's data. */
++/*
++ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level
++ * and it doesn't make sense, in general, to ask for a pointer
++ * to a particular pixel's data.
++ *
++ * This function assumes that bounds checking has been done in previous phase
++ * and they are opted out in here.
++ */
+ static inline void *
+ grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source,
+ unsigned int x, unsigned int y)
+ {
+- return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel;
++ return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel;
+ }
+
+ /* Advance pointer by VAL bytes. If there is no unaligned access available,
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0011-font-Fix-an-integer-underflow-in-blit_comb.patch b/debian/patches/cve_2022_2601/0011-font-Fix-an-integer-underflow-in-blit_comb.patch
new file mode 100644
index 0000000..3a2b02c
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0011-font-Fix-an-integer-underflow-in-blit_comb.patch
@@ -0,0 +1,91 @@
+From 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Mon, 24 Oct 2022 08:05:35 +0800
+Subject: [PATCH 11/14] font: Fix an integer underflow in blit_comb()
+
+The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may
+evaluate to a very big invalid value even if both ctx.bounds.height and
+combining_glyphs[i]->height are small integers. For example, if
+ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this
+expression evaluates to 2147483647 (expected -1). This is because
+coordinates are allowed to be negative but ctx.bounds.height is an
+unsigned int. So, the subtraction operates on unsigned ints and
+underflows to a very big value. The division makes things even worse.
+The quotient is still an invalid value even if converted back to int.
+
+This patch fixes the problem by casting ctx.bounds.height to int. As
+a result the subtraction will operate on int and grub_uint16_t which
+will be promoted to an int. So, the underflow will no longer happen. Other
+uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int,
+to ensure coordinates are always calculated on signed integers.
+
+Fixes: CVE-2022-3775
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index abd412a5e..3d3d803e8 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ ctx.bounds.height = main_glyph->height;
+
+ above_rightx = main_glyph->offset_x + main_glyph->width;
+- above_righty = ctx.bounds.y + ctx.bounds.height;
++ above_righty = ctx.bounds.y + (int) ctx.bounds.height;
+
+ above_leftx = main_glyph->offset_x;
+- above_lefty = ctx.bounds.y + ctx.bounds.height;
++ above_lefty = ctx.bounds.y + (int) ctx.bounds.height;
+
+- below_rightx = ctx.bounds.x + ctx.bounds.width;
++ below_rightx = ctx.bounds.x + (int) ctx.bounds.width;
+ below_righty = ctx.bounds.y;
+
+ comb = grub_unicode_get_comb (glyph_id);
+@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+
+ if (!combining_glyphs[i])
+ continue;
+- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
++ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
+ /* CGJ is to avoid diacritics reordering. */
+ if (comb[i].code
+ == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER)
+@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ case GRUB_UNICODE_COMB_OVERLAY:
+ do_blit (combining_glyphs[i],
+ targetx,
+- (ctx.bounds.height - combining_glyphs[i]->height) / 2
+- - (ctx.bounds.height + ctx.bounds.y), &ctx);
++ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2
++ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx);
+ if (min_devwidth < combining_glyphs[i]->width)
+ min_devwidth = combining_glyphs[i]->width;
+ break;
+@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ /* Fallthrough. */
+ case GRUB_UNICODE_STACK_ATTACHED_ABOVE:
+ do_blit (combining_glyphs[i], targetx,
+- -(ctx.bounds.height + ctx.bounds.y + space
++ -((int) ctx.bounds.height + ctx.bounds.y + space
+ + combining_glyphs[i]->height), &ctx);
+ if (min_devwidth < combining_glyphs[i]->width)
+ min_devwidth = combining_glyphs[i]->width;
+@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+
+ case GRUB_UNICODE_COMB_HEBREW_DAGESH:
+ do_blit (combining_glyphs[i], targetx,
+- -(ctx.bounds.height / 2 + ctx.bounds.y
++ -((int) ctx.bounds.height / 2 + ctx.bounds.y
+ + combining_glyphs[i]->height / 2), &ctx);
+ if (min_devwidth < combining_glyphs[i]->width)
+ min_devwidth = combining_glyphs[i]->width;
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0012-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch b/debian/patches/cve_2022_2601/0012-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
new file mode 100644
index 0000000..6296bf5
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0012-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
@@ -0,0 +1,75 @@
+From fcd7aa0c278f7cf3fb9f93f1a3966e1792339eb6 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Mon, 24 Oct 2022 07:15:41 +0800
+Subject: [PATCH 12/14] font: Harden grub_font_blit_glyph() and
+ grub_font_blit_glyph_mirror()
+
+As a mitigation and hardening measure add sanity checks to
+grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch
+makes these two functions do nothing if target blitting area isn't fully
+contained in target bitmap. Therefore, if complex calculations in caller
+overflows and malicious coordinates are given, we are still safe because
+any coordinates which result in out-of-bound-write are rejected. However,
+this patch only checks for invalid coordinates, and doesn't provide any
+protection against invalid source glyph or destination glyph, e.g.
+mismatch between glyph size and buffer size.
+
+This hardening measure is designed to mitigate possible overflows in
+blit_comb(). If overflow occurs, it may return invalid bounding box
+during dry run and call grub_font_blit_glyph() with malicious
+coordinates during actual blitting. However, we are still safe because
+the scratch glyph itself is valid, although its size makes no sense, and
+any invalid coordinates are rejected.
+
+It would be better to call grub_fatal() if illegal parameter is detected.
+However, doing this may end up in a dangerous recursion because grub_fatal()
+would print messages to the screen and we are in the progress of drawing
+characters on the screen.
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 3d3d803e8..cf15dc2f9 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1069,8 +1069,15 @@ static void
+ grub_font_blit_glyph (struct grub_font_glyph *target,
+ struct grub_font_glyph *src, unsigned dx, unsigned dy)
+ {
++ grub_uint16_t max_x, max_y;
+ unsigned src_bit, tgt_bit, src_byte, tgt_byte;
+ unsigned i, j;
++
++ /* Harden against out-of-bound writes. */
++ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) ||
++ (grub_add (dy, src->height, &max_y) || max_y > target->height))
++ return;
++
+ for (i = 0; i < src->height; i++)
+ {
+ src_bit = (src->width * i) % 8;
+@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target,
+ struct grub_font_glyph *src,
+ unsigned dx, unsigned dy)
+ {
++ grub_uint16_t max_x, max_y;
+ unsigned tgt_bit, src_byte, tgt_byte;
+ signed src_bit;
+ unsigned i, j;
++
++ /* Harden against out-of-bound writes. */
++ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) ||
++ (grub_add (dy, src->height, &max_y) || max_y > target->height))
++ return;
++
+ for (i = 0; i < src->height; i++)
+ {
+ src_bit = (src->width * i + src->width - 1) % 8;
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0013-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch b/debian/patches/cve_2022_2601/0013-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
new file mode 100644
index 0000000..2db665f
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0013-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
@@ -0,0 +1,36 @@
+From dd539d695482069d28b40f2d3821f710cdcf6ee6 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 28 Oct 2022 17:29:16 +0800
+Subject: [PATCH 13/14] font: Assign null_font to glyphs in ascii_font_glyph[]
+
+The calculations in blit_comb() need information from glyph's font, e.g.
+grub_font_get_xheight(main_glyph->font). However, main_glyph->font is
+NULL if main_glyph comes from ascii_font_glyph[]. Therefore
+grub_font_get_*() crashes because of NULL pointer.
+
+There is already a solution, the null_font. So, assign it to those glyphs
+in ascii_font_glyph[].
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index cf15dc2f9..3821937e6 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code)
+ ascii_font_glyph[current]->offset_x = 0;
+ ascii_font_glyph[current]->offset_y = -2;
+ ascii_font_glyph[current]->device_width = 8;
+- ascii_font_glyph[current]->font = NULL;
++ ascii_font_glyph[current]->font = &null_font;
+
+ grub_memcpy (ascii_font_glyph[current]->bitmap,
+ &ascii_bitmaps[current * ASCII_BITMAP_SIZE],
+--
+2.30.2
+
diff --git a/debian/patches/cve_2022_2601/0014-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch b/debian/patches/cve_2022_2601/0014-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch
new file mode 100644
index 0000000..a94450a
--- /dev/null
+++ b/debian/patches/cve_2022_2601/0014-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch
@@ -0,0 +1,55 @@
+From da90d62316a3b105d2fbd7334d6521936bd6dcf6 Mon Sep 17 00:00:00 2001
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 28 Oct 2022 21:31:39 +0800
+Subject: [PATCH 14/14] normal/charset: Fix an integer overflow in
+ grub_unicode_aglomerate_comb()
+
+The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255.
+However, code in grub_unicode_aglomerate_comb() doesn't check for an
+overflow when incrementing out->ncomb. If out->ncomb is already 255,
+after incrementing it will get 0 instead of 256, and cause illegal
+memory access in subsequent processing.
+
+This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max
+acceptable value of ncomb. The code now checks for this limit and
+ignores additional combining characters when limit is reached.
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/normal/charset.c | 3 +++
+ include/grub/unicode.h | 2 ++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
+index 000e687bd..4f6647116 100644
+--- a/grub-core/normal/charset.c
++++ b/grub-core/normal/charset.c
+@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
+ if (!haveout)
+ continue;
+
++ if (out->ncomb == GRUB_UNICODE_NCOMB_MAX)
++ continue;
++
+ if (comb_type == GRUB_UNICODE_COMB_MC
+ || comb_type == GRUB_UNICODE_COMB_ME
+ || comb_type == GRUB_UNICODE_COMB_MN)
+diff --git a/include/grub/unicode.h b/include/grub/unicode.h
+index 71a4d1a54..9360b0b97 100644
+--- a/include/grub/unicode.h
++++ b/include/grub/unicode.h
+@@ -147,7 +147,9 @@ struct grub_unicode_glyph
+ grub_uint8_t bidi_level:6; /* minimum: 6 */
+ enum grub_bidi_type bidi_type:5; /* minimum: :5 */
+
++#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1)
+ unsigned ncomb:8;
++
+ /* Hint by unicode subsystem how wide this character usually is.
+ Real width is determined by font. Set only in UTF-8 stream. */
+ int estimated_width:8;
+--
+2.30.2
+
diff --git a/debian/patches/debug_verifiers.patch b/debian/patches/debug_verifiers.patch
new file mode 100644
index 0000000..2d2daca
--- /dev/null
+++ b/debian/patches/debug_verifiers.patch
@@ -0,0 +1,28 @@
+From 55796e3e90a55d54aff94f2dfeb6e02055e08e30 Mon Sep 17 00:00:00 2001
+From: Steve McIntyre <93sam@debian.org>
+Date: Sat, 17 Apr 2021 22:05:47 +0100
+Subject: Add debug to display what's going on with verifiers
+
+Patch-Name: debug_verifiers.patch
+---
+ grub-core/kern/verifiers.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/kern/verifiers.c b/grub-core/kern/verifiers.c
+index 1245d0d9e..5242a723f 100644
+--- a/grub-core/kern/verifiers.c
++++ b/grub-core/kern/verifiers.c
+@@ -100,11 +100,13 @@ grub_verifiers_open (grub_file_t io, enum grub_file_type type)
+ FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
+ {
+ enum grub_verify_flags flags = 0;
++ grub_dprintf ("verify", "trying verifier %s\n", ver->name);
+ err = ver->init (io, type, &context, &flags);
+ if (err)
+ goto fail_noclose;
+ if (flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
+ {
++ grub_dprintf ("verify", "verifier %s said GRUB_VERIFY_FLAGS_DEFER_AUTH\n", ver->name);
+ defer = 1;
+ continue;
+ }
diff --git a/debian/patches/default-grub-d.patch b/debian/patches/default-grub-d.patch
new file mode 100644
index 0000000..f7ca596
--- /dev/null
+++ b/debian/patches/default-grub-d.patch
@@ -0,0 +1,209 @@
+From 4dff7f7df2853c519c4b0f59ff224c0b31f8223e Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:10 +0000
+Subject: Read /etc/default/grub.d/*.cfg after /etc/default/grub
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/901600
+Forwarded: no
+Last-Update: 2021-09-24
+
+Patch-Name: default-grub-d.patch
+---
+ grub-core/osdep/unix/config.c | 128 ++++++++++++++++++++++++++++------
+ util/grub-mkconfig.in | 5 ++
+ 2 files changed, 112 insertions(+), 21 deletions(-)
+
+diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c
+index 7d6325138..545d64b4c 100644
+--- a/grub-core/osdep/unix/config.c
++++ b/grub-core/osdep/unix/config.c
+@@ -24,6 +24,9 @@
+ #include <grub/emu/config.h>
+ #include <grub/util/install.h>
+ #include <grub/util/misc.h>
++#include <grub/list.h>
++#include <grub/safemath.h>
++#include <assert.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+@@ -61,13 +64,27 @@ grub_util_get_localedir (void)
+ return LOCALEDIR;
+ }
+
++struct cfglist
++{
++ struct cfglist *next;
++ struct cfglist *prev;
++ char *path;
++};
++
+ void
+ grub_util_load_config (struct grub_util_config *cfg)
+ {
+ pid_t pid;
+ const char *argv[4];
+- char *script, *ptr;
++ char *script = NULL, *ptr;
+ const char *cfgfile, *iptr;
++ char *cfgdir;
++ grub_util_fd_dir_t d;
++ struct cfglist *cfgpaths = NULL, *cfgpath, *next_cfgpath;
++ int num_cfgpaths = 0;
++ size_t len_cfgpaths = 0;
++ char **sorted_cfgpaths = NULL;
++ int i;
+ FILE *f = NULL;
+ int fd;
+ const char *v;
+@@ -83,29 +100,88 @@ grub_util_load_config (struct grub_util_config *cfg)
+ cfg->grub_distributor = xstrdup (v);
+
+ cfgfile = grub_util_get_config_filename ();
+- if (!grub_util_is_regular (cfgfile))
+- return;
++ if (grub_util_is_regular (cfgfile))
++ {
++ size_t sz;
++
++ ++num_cfgpaths;
++ sz = strlen (cfgfile);
++ if (grub_mul (sz, 4, &sz) ||
++ grub_add (sz, sizeof (". ''; ") - 1, &sz) ||
++ grub_add (len_cfgpaths, sz, &len_cfgpaths))
++ grub_util_error ("%s", _("overflow is detected"));
++ }
++
++ cfgdir = xasprintf ("%s.d", cfgfile);
++ d = grub_util_fd_opendir (cfgdir);
++ if (d)
++ {
++ grub_util_fd_dirent_t de;
++
++ while ((de = grub_util_fd_readdir (d)))
++ {
++ const char *ext = strrchr (de->d_name, '.');
++ size_t sz;
++
++ if (!ext || strcmp (ext, ".cfg") != 0)
++ continue;
++
++ cfgpath = xmalloc (sizeof (*cfgpath));
++ cfgpath->path = grub_util_path_concat (2, cfgdir, de->d_name);
++ grub_list_push (GRUB_AS_LIST_P (&cfgpaths), GRUB_AS_LIST (cfgpath));
++ ++num_cfgpaths;
++ sz = strlen (cfgpath->path);
++ if (grub_mul (sz, 4, &sz) ||
++ grub_add (sz, sizeof (". ''; ") - 1, &sz) ||
++ grub_add (len_cfgpaths, sz, &len_cfgpaths))
++ grub_util_error ("%s", _("overflow is detected"));
++ }
++ grub_util_fd_closedir (d);
++ }
++
++ if (num_cfgpaths == 0)
++ goto out;
++
++ sorted_cfgpaths = xcalloc (num_cfgpaths, sizeof (*sorted_cfgpaths));
++ i = 0;
++ if (grub_util_is_regular (cfgfile))
++ sorted_cfgpaths[i++] = xstrdup (cfgfile);
++ FOR_LIST_ELEMENTS_SAFE (cfgpath, next_cfgpath, cfgpaths)
++ {
++ sorted_cfgpaths[i++] = cfgpath->path;
++ free (cfgpath);
++ }
++ assert (i == num_cfgpaths);
++ qsort (sorted_cfgpaths + 1, num_cfgpaths - 1, sizeof (*sorted_cfgpaths),
++ (int (*) (const void *, const void *)) strcmp);
+
+ argv[0] = "sh";
+ argv[1] = "-c";
+
+- script = xcalloc (4, strlen (cfgfile) + 300);
++ if (grub_add (len_cfgpaths, 300, &len_cfgpaths))
++ grub_util_error ("%s", _("overflow is detected"));
++ script = xmalloc (len_cfgpaths);
+
+ ptr = script;
+- memcpy (ptr, ". '", 3);
+- ptr += 3;
+- for (iptr = cfgfile; *iptr; iptr++)
++ for (i = 0; i < num_cfgpaths; i++)
+ {
+- if (*iptr == '\\')
++ memcpy (ptr, ". '", 3);
++ ptr += 3;
++ for (iptr = sorted_cfgpaths[i]; *iptr; iptr++)
+ {
+- memcpy (ptr, "'\\''", 4);
+- ptr += 4;
+- continue;
++ if (*iptr == '\\')
++ {
++ memcpy (ptr, "'\\''", 4);
++ ptr += 4;
++ continue;
++ }
++ *ptr++ = *iptr;
+ }
+- *ptr++ = *iptr;
++ memcpy (ptr, "'; ", 3);
++ ptr += 3;
+ }
+
+- strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" "
++ strcpy (ptr, "printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" "
+ "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\"");
+
+ argv[2] = script;
+@@ -125,15 +201,25 @@ grub_util_load_config (struct grub_util_config *cfg)
+ waitpid (pid, NULL, 0);
+ }
+ if (f)
+- return;
++ goto out;
+
+- f = grub_util_fopen (cfgfile, "r");
+- if (f)
++ for (i = 0; i < num_cfgpaths; i++)
+ {
+- grub_util_parse_config (f, cfg, 0);
+- fclose (f);
++ f = grub_util_fopen (sorted_cfgpaths[i], "r");
++ if (f)
++ {
++ grub_util_parse_config (f, cfg, 0);
++ fclose (f);
++ }
++ else
++ grub_util_warn (_("cannot open configuration file `%s': %s"),
++ cfgfile, strerror (errno));
+ }
+- else
+- grub_util_warn (_("cannot open configuration file `%s': %s"),
+- cfgfile, strerror (errno));
++
++out:
++ free (script);
++ for (i = 0; i < num_cfgpaths; i++)
++ free (sorted_cfgpaths[i]);
++ free (sorted_cfgpaths);
++ free (cfgdir);
+ }
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index 0fd618e35..0265a5a66 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -160,6 +160,11 @@ fi
+ if test -f ${sysconfdir}/default/grub ; then
+ . ${sysconfdir}/default/grub
+ fi
++for x in ${sysconfdir}/default/grub.d/*.cfg ; do
++ if [ -e "${x}" ]; then
++ . "${x}"
++ fi
++done
+
+ if [ "x${GRUB_DISABLE_UUID}" = "xtrue" ]; then
+ if [ -z "${GRUB_DISABLE_LINUX_UUID}" ]; then
diff --git a/debian/patches/dejavu-font-path.patch b/debian/patches/dejavu-font-path.patch
new file mode 100644
index 0000000..cda9800
--- /dev/null
+++ b/debian/patches/dejavu-font-path.patch
@@ -0,0 +1,23 @@
+From 973e040bdeddcf366a7a45bb5d9f77e06f4784c7 Mon Sep 17 00:00:00 2001
+From: Fabian Greffrath <fabian@greffrath.com>
+Date: Tue, 19 May 2020 12:19:26 +0200
+Subject: add /u/s/fonts/truetype/dejavu to the DejaVu fonts search paths
+
+Patch-Name: dejavu-font-path.patch
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index b3fb7437e..22c6cf7ac 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1719,7 +1719,7 @@ fi
+
+ if test x"$starfield_excuse" = x; then
+ for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
+- for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do
++ for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/dejavu /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do
+ if test -f "$dir/DejaVuSans.$ext"; then
+ DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext"
+ break 2
diff --git a/debian/patches/disable-floppies.patch b/debian/patches/disable-floppies.patch
new file mode 100644
index 0000000..ee4ae5a
--- /dev/null
+++ b/debian/patches/disable-floppies.patch
@@ -0,0 +1,37 @@
+From 6a1ff6845e571d2a9885763a3e52a16a9eec54bb Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:12:54 +0000
+Subject: Disable use of floppy devices
+
+An ugly kludge. Should this be merged upstream?
+
+Author: Robert Millan
+
+Patch-Name: disable-floppies.patch
+---
+ grub-core/kern/emu/hostdisk.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c
+index d975265b2..f90b6c9ce 100644
+--- a/grub-core/kern/emu/hostdisk.c
++++ b/grub-core/kern/emu/hostdisk.c
+@@ -532,6 +532,18 @@ read_device_map (const char *dev_map)
+ continue;
+ }
+
++ if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1))
++ {
++ char *q = p + sizeof ("/dev/fd") - 1;
++ if (*q >= '0' && *q <= '9')
++ {
++ free (map[drive].drive);
++ map[drive].drive = NULL;
++ grub_util_info ("`%s' looks like a floppy drive, skipping", p);
++ continue;
++ }
++ }
++
+ /* On Linux, the devfs uses symbolic links horribly, and that
+ confuses the interface very much, so use realpath to expand
+ symbolic links. */
diff --git a/debian/patches/disk-cryptodisk-when-cheatmounting-use-the-sector-info-of-the-cheat-device.patch b/debian/patches/disk-cryptodisk-when-cheatmounting-use-the-sector-info-of-the-cheat-device.patch
new file mode 100644
index 0000000..1c7d781
--- /dev/null
+++ b/debian/patches/disk-cryptodisk-when-cheatmounting-use-the-sector-info-of-the-cheat-device.patch
@@ -0,0 +1,72 @@
+From: Fabian Vogt <fvogt@suse.de>
+Date: Thu, 12 Jan 2023 17:05:07 -0600
+Subject: disk/cryptodisk: When cheatmounting, use the sector info of the cheat
+ device
+Origin: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=efc9c363b2aab222586b420508eb46fc13242739
+Bug-Debian: https://bugs.debian.org/1028301
+
+When using grub-probe with cryptodisk, the mapped block device from the host
+is used directly instead of decrypting the source device in GRUB code.
+In that case, the sector size and count of the host device needs to be used.
+This is especially important when using LUKS2, which does not assign
+total_sectors and log_sector_size when scanning, but only later when the
+segments in the JSON area are evaluated. With an unset log_sector_size,
+grub_device_open() complains.
+
+This fixes grub-probe failing with
+"error: sector sizes of 1 bytes aren't supported yet.".
+
+Signed-off-by: Fabian Vogt <fvogt@suse.de>
+Reviewed-by: Patrick Steinhardt <ps@pks.im>
+Tested-by: Glenn Washburn <development@efficientek.com>
+Reviewed-by: Glenn Washburn <development@efficientek.com>
+Reviewed-by: Patrick Steinhardt <ps@pks.im>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/disk/cryptodisk.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- a/grub-core/disk/cryptodisk.c
++++ b/grub-core/disk/cryptodisk.c
+@@ -694,16 +694,31 @@ grub_cryptodisk_open (const char *name,
+ if (!dev)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
+
+- disk->log_sector_size = dev->log_sector_size;
+-
+ #ifdef GRUB_UTIL
+ if (dev->cheat)
+ {
++ grub_uint64_t cheat_dev_size;
++ unsigned int cheat_log_sector_size;
++
+ if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd))
+ dev->cheat_fd = grub_util_fd_open (dev->cheat, GRUB_UTIL_FD_O_RDONLY);
+ if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd))
+ return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"),
+ dev->cheat, grub_util_fd_strerror ());
++
++ /* Use the sector size and count of the cheat device. */
++ cheat_dev_size = grub_util_get_fd_size (dev->cheat_fd, dev->cheat, &cheat_log_sector_size);
++ if (cheat_dev_size == -1)
++ {
++ const char *errmsg = grub_util_fd_strerror ();
++ grub_util_fd_close (dev->cheat_fd);
++ dev->cheat_fd = GRUB_UTIL_FD_INVALID;
++ return grub_error (GRUB_ERR_IO, N_("failed to query size of device `%s': %s"),
++ dev->cheat, errmsg);
++ }
++
++ dev->log_sector_size = cheat_log_sector_size;
++ dev->total_sectors = cheat_dev_size >> cheat_log_sector_size;
+ }
+ #endif
+
+@@ -717,6 +732,7 @@ grub_cryptodisk_open (const char *name,
+ }
+
+ disk->data = dev;
++ disk->log_sector_size = dev->log_sector_size;
+ disk->total_sectors = dev->total_sectors;
+ disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
+ disk->id = dev->id;
diff --git a/debian/patches/dpkg-version-comparison.patch b/debian/patches/dpkg-version-comparison.patch
new file mode 100644
index 0000000..d20e986
--- /dev/null
+++ b/debian/patches/dpkg-version-comparison.patch
@@ -0,0 +1,38 @@
+From 562d50025e18052cabc40c8eb63ed4d0bb5de236 Mon Sep 17 00:00:00 2001
+From: Robert Millan <rmh@aybabtu.com>
+Date: Mon, 13 Jan 2014 12:12:52 +0000
+Subject: Improve handling of Debian kernel version numbers
+
+Forwarded: not-needed
+Last-Update: 2013-12-20
+
+Patch-Name: dpkg-version-comparison.patch
+---
+ util/grub-mkconfig_lib.in | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index 301d1ac22..17f9b3e58 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -243,8 +243,9 @@ version_test_numeric ()
+
+ version_test_gt ()
+ {
+- version_test_gt_a="`echo "$1" | sed -e "s/[^-]*-//"`"
+- version_test_gt_b="`echo "$2" | sed -e "s/[^-]*-//"`"
++ version_test_gt_sedexp="s/[^-]*-//;s/[._-]\(pre\|rc\|test\|git\|old\|trunk\)/~\1/g"
++ version_test_gt_a="`echo "$1" | sed -e "$version_test_gt_sedexp"`"
++ version_test_gt_b="`echo "$2" | sed -e "$version_test_gt_sedexp"`"
+ version_test_gt_cmp=gt
+ if [ "x$version_test_gt_b" = "x" ] ; then
+ return 0
+@@ -254,7 +255,7 @@ version_test_gt ()
+ *.old:*) version_test_gt_a="`echo "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;;
+ *:*.old) version_test_gt_b="`echo "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;;
+ esac
+- version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b"
++ dpkg --compare-versions "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b"
+ return "$?"
+ }
+
diff --git a/debian/patches/efi-variable-storage-minimise-writes.patch b/debian/patches/efi-variable-storage-minimise-writes.patch
new file mode 100644
index 0000000..c06dbe8
--- /dev/null
+++ b/debian/patches/efi-variable-storage-minimise-writes.patch
@@ -0,0 +1,895 @@
+From 6e3841fc4abf50d16d819c39ac5de74ccc4de225 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 11 Mar 2019 11:17:43 +0000
+Subject: Minimise writes to EFI variable storage
+
+Some UEFI firmware is easily provoked into running out of space in its
+variable storage. This is usually due to certain kernel drivers (e.g.
+pstore), but regardless of the cause it can cause grub-install to fail
+because it currently asks efibootmgr to delete and re-add entries, and
+the deletion often doesn't result in an immediate garbage collection.
+Writing variables frequently also increases wear on the NVRAM which may
+have limited write cycles. For these reasons, it's desirable to find a
+way to minimise writes while still allowing grub-install to ensure that
+a suitable boot entry exists.
+
+Unfortunately, efibootmgr doesn't offer an interface that would let
+grub-install do this. It doesn't in general make very much effort to
+minimise writes; it doesn't allow modifying an existing Boot* variable
+entry, except in certain limited ways; and current versions don't have a
+way to export the expected variable data so that grub-install can
+compare it to the current data. While it would be possible (and perhaps
+desirable?) to add at least some of this to efibootmgr, that would still
+leave the problem that there isn't a good upstreamable way for
+grub-install to guarantee that it has a new enough version of
+efibootmgr. In any case, it's cumbersome and slow for grub-install to
+have to fork efibootmgr to get things done.
+
+Fortunately, a few years ago Peter Jones helpfully factored out a
+substantial part of efibootmgr to the efivar and efiboot libraries, and
+so it's now possible to have grub-install use those directly. We still
+have to use some code from efibootmgr, but much less than would
+previously have been necessary.
+
+grub-install now reuses existing boot entries where possible, and avoids
+writing to variables when the new contents are the same as the old
+contents. In the common upgrade case where nothing needs to change, it
+no longer writes to NVRAM at all. It's also now slightly faster, since
+using libefivar is faster than forking efibootmgr.
+
+Fixes Debian bug #891434.
+
+Signed-off-by: Colin Watson <cjwatson@ubuntu.com>
+
+Bug-Debian: https://bugs.debian.org/891434
+Forwarded: https://lists.gnu.org/archive/html/grub-devel/2019-03/msg00119.html
+Last-Update: 2019-03-23
+
+Patch-Name: efi-variable-storage-minimise-writes.patch
+---
+ INSTALL | 5 +
+ Makefile.util.def | 20 ++
+ configure.ac | 12 +
+ grub-core/osdep/efivar.c | 3 +
+ grub-core/osdep/unix/efivar.c | 508 ++++++++++++++++++++++++++++++++
+ grub-core/osdep/unix/platform.c | 100 +------
+ include/grub/util/install.h | 5 +
+ util/grub-install.c | 4 +-
+ 8 files changed, 562 insertions(+), 95 deletions(-)
+ create mode 100644 grub-core/osdep/efivar.c
+ create mode 100644 grub-core/osdep/unix/efivar.c
+
+diff --git a/INSTALL b/INSTALL
+index 79a0af7d9..590b52482 100644
+--- a/INSTALL
++++ b/INSTALL
+@@ -23,6 +23,11 @@ configuring the GRUB.
+ * Other standard GNU/Unix tools
+ * a libc with large file support (e.g. glibc 2.1 or later)
+
++On Unix-based systems, you also need:
++
++* libefivar (recommended)
++* libefiboot (recommended; your OS may ship this together with libefivar)
++
+ On GNU/Linux, you also need:
+
+ * libdevmapper 1.02.34 or later (recommended)
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 27f948291..a3d134b03 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -570,6 +570,8 @@ program = {
+ common = grub-core/osdep/compress.c;
+ extra_dist = grub-core/osdep/unix/compress.c;
+ extra_dist = grub-core/osdep/basic/compress.c;
++ common = grub-core/osdep/efivar.c;
++ extra_dist = grub-core/osdep/unix/efivar.c;
+ common = util/editenv.c;
+ common = grub-core/osdep/blocklist.c;
+ common = grub-core/osdep/config.c;
+@@ -583,12 +585,15 @@ program = {
+ common = grub-core/kern/emu/argp_common.c;
+ common = grub-core/osdep/init.c;
+
++ cflags = '$(EFIVAR_CFLAGS)';
++
+ ldadd = '$(LIBLZMA)';
+ ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/lib/gnulib/libgnu.a;
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
++ ldadd = '$(EFIVAR_LIBS)';
+
+ condition = COND_HAVE_EXEC;
+ };
+@@ -617,6 +622,8 @@ program = {
+ extra_dist = grub-core/osdep/basic/no_platform.c;
+ extra_dist = grub-core/osdep/unix/platform.c;
+ common = grub-core/osdep/compress.c;
++ common = grub-core/osdep/efivar.c;
++ extra_dist = grub-core/osdep/unix/efivar.c;
+ common = util/editenv.c;
+ common = grub-core/osdep/blocklist.c;
+ common = grub-core/osdep/config.c;
+@@ -630,12 +637,15 @@ program = {
+ common = grub-core/kern/emu/argp_common.c;
+ common = grub-core/osdep/init.c;
+
++ cflags = '$(EFIVAR_CFLAGS)';
++
+ ldadd = '$(LIBLZMA)';
+ ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/lib/gnulib/libgnu.a;
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
++ ldadd = '$(EFIVAR_LIBS)';
+ };
+
+ program = {
+@@ -657,6 +667,8 @@ program = {
+ common = grub-core/osdep/platform.c;
+ common = grub-core/osdep/platform_unix.c;
+ common = grub-core/osdep/compress.c;
++ common = grub-core/osdep/efivar.c;
++ extra_dist = grub-core/osdep/unix/efivar.c;
+ common = util/editenv.c;
+ common = grub-core/osdep/blocklist.c;
+ common = grub-core/osdep/config.c;
+@@ -669,12 +681,15 @@ program = {
+ common = grub-core/kern/emu/argp_common.c;
+ common = grub-core/osdep/init.c;
+
++ cflags = '$(EFIVAR_CFLAGS)';
++
+ ldadd = '$(LIBLZMA)';
+ ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/lib/gnulib/libgnu.a;
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
++ ldadd = '$(EFIVAR_LIBS)';
+ };
+
+ program = {
+@@ -696,6 +711,8 @@ program = {
+ common = grub-core/osdep/platform.c;
+ common = grub-core/osdep/platform_unix.c;
+ common = grub-core/osdep/compress.c;
++ common = grub-core/osdep/efivar.c;
++ extra_dist = grub-core/osdep/unix/efivar.c;
+ common = util/editenv.c;
+ common = grub-core/osdep/blocklist.c;
+ common = grub-core/osdep/config.c;
+@@ -705,12 +722,15 @@ program = {
+ common = grub-core/kern/emu/argp_common.c;
+ common = grub-core/osdep/init.c;
+
++ cflags = '$(EFIVAR_CFLAGS)';
++
+ ldadd = '$(LIBLZMA)';
+ ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/lib/gnulib/libgnu.a;
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
++ ldadd = '$(EFIVAR_LIBS)';
+ };
+
+ script = {
+diff --git a/configure.ac b/configure.ac
+index e11df6bc5..b3fb7437e 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -452,6 +452,18 @@ AC_CHECK_HEADER([util.h], [
+ ])
+ AC_SUBST([LIBUTIL])
+
++case "$host_os" in
++ cygwin | windows* | mingw32* | aros*)
++ ;;
++ *)
++ # For setting EFI variables in grub-install.
++ PKG_CHECK_MODULES([EFIVAR], [efivar efiboot], [
++ AC_DEFINE([HAVE_EFIVAR], [1],
++ [Define to 1 if you have the efivar and efiboot libraries.])
++ ], [:])
++ ;;
++esac
++
+ AC_CACHE_CHECK([whether -Wtrampolines work], [grub_cv_host_cc_wtrampolines], [
+ SAVED_CFLAGS="$CFLAGS"
+ CFLAGS="$HOST_CFLAGS -Wtrampolines -Werror"
+diff --git a/grub-core/osdep/efivar.c b/grub-core/osdep/efivar.c
+new file mode 100644
+index 000000000..d2750e252
+--- /dev/null
++++ b/grub-core/osdep/efivar.c
+@@ -0,0 +1,3 @@
++#if !defined (__MINGW32__) && !defined (__CYGWIN__) && !defined (__AROS__)
++#include "unix/efivar.c"
++#endif
+diff --git a/grub-core/osdep/unix/efivar.c b/grub-core/osdep/unix/efivar.c
+new file mode 100644
+index 000000000..4a58328b4
+--- /dev/null
++++ b/grub-core/osdep/unix/efivar.c
+@@ -0,0 +1,508 @@
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2013,2019 Free Software Foundation, Inc.
++ *
++ * GRUB is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GRUB is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++/* Contains portions derived from efibootmgr, licensed as follows:
++ *
++ * Copyright (C) 2001-2004 Dell, Inc. <Matt_Domsch@dell.com>
++ * Copyright 2015-2016 Red Hat, Inc. <pjones@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <config.h>
++
++#ifdef HAVE_EFIVAR
++
++#include <grub/util/install.h>
++#include <grub/emu/hostdisk.h>
++#include <grub/util/misc.h>
++#include <grub/list.h>
++#include <grub/misc.h>
++#include <grub/emu/exec.h>
++#include <sys/types.h>
++#include <ctype.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <efiboot.h>
++#include <efivar.h>
++
++struct efi_variable {
++ struct efi_variable *next;
++ struct efi_variable **prev;
++ char *name;
++ efi_guid_t guid;
++ uint8_t *data;
++ size_t data_size;
++ uint32_t attributes;
++ int num;
++};
++
++/* Boot option attributes. */
++#define LOAD_OPTION_ACTIVE 0x00000001
++
++/* GUIDs. */
++#define BLKX_UNKNOWN_GUID \
++ EFI_GUID (0x47c7b225, 0xc42a, 0x11d2, 0x8e57, 0x00, 0xa0, 0xc9, 0x69, \
++ 0x72, 0x3b)
++
++/* Log all errors recorded by libefivar/libefiboot. */
++static void
++show_efi_errors (void)
++{
++ int i;
++ int saved_errno = errno;
++
++ for (i = 0; ; ++i)
++ {
++ char *filename, *function, *message = NULL;
++ int line, error = 0, rc;
++
++ rc = efi_error_get (i, &filename, &function, &line, &message, &error);
++ if (rc < 0)
++ /* Give up. The caller is going to log an error anyway. */
++ break;
++ if (rc == 0)
++ /* No more errors. */
++ break;
++ grub_util_warn ("%s: %s: %s", function, message, strerror (error));
++ }
++
++ efi_error_clear ();
++ errno = saved_errno;
++}
++
++static struct efi_variable *
++new_efi_variable (void)
++{
++ struct efi_variable *new = xmalloc (sizeof (*new));
++ memset (new, 0, sizeof (*new));
++ return new;
++}
++
++static struct efi_variable *
++new_boot_variable (void)
++{
++ struct efi_variable *new = new_efi_variable ();
++ new->guid = EFI_GLOBAL_GUID;
++ new->attributes = EFI_VARIABLE_NON_VOLATILE |
++ EFI_VARIABLE_BOOTSERVICE_ACCESS |
++ EFI_VARIABLE_RUNTIME_ACCESS;
++ return new;
++}
++
++static void
++free_efi_variable (struct efi_variable *entry)
++{
++ if (entry)
++ {
++ free (entry->name);
++ free (entry->data);
++ free (entry);
++ }
++}
++
++static int
++read_efi_variable (const char *name, struct efi_variable **entry)
++{
++ struct efi_variable *new = new_efi_variable ();
++ int rc;
++
++ rc = efi_get_variable (EFI_GLOBAL_GUID, name,
++ &new->data, &new->data_size, &new->attributes);
++ if (rc < 0)
++ {
++ free_efi_variable (new);
++ new = NULL;
++ }
++
++ if (new)
++ {
++ /* Latest Apple firmware sets the high bit which appears invalid
++ to the Linux kernel if we write it back, so let's zero it out if it
++ is set since it would be invalid to set it anyway. */
++ new->attributes = new->attributes & ~(1 << 31);
++
++ new->name = xstrdup (name);
++ new->guid = EFI_GLOBAL_GUID;
++ }
++
++ *entry = new;
++ return rc;
++}
++
++/* Set an EFI variable, but only if it differs from the current value.
++ Some firmware implementations are liable to fill up flash space if we set
++ variables unnecessarily, so try to keep write activity to a minimum. */
++static int
++set_efi_variable (const char *name, struct efi_variable *entry)
++{
++ struct efi_variable *old = NULL;
++ int rc = 0;
++
++ read_efi_variable (name, &old);
++ efi_error_clear ();
++ if (old && old->attributes == entry->attributes &&
++ old->data_size == entry->data_size &&
++ memcmp (old->data, entry->data, entry->data_size) == 0)
++ grub_util_info ("skipping unnecessary update of EFI variable %s", name);
++ else
++ {
++ rc = efi_set_variable (EFI_GLOBAL_GUID, name,
++ entry->data, entry->data_size, entry->attributes,
++ 0644);
++ if (rc < 0)
++ grub_util_warn (_("Cannot set EFI variable %s"), name);
++ }
++ free_efi_variable (old);
++ return rc;
++}
++
++static int
++cmpvarbyname (const void *p1, const void *p2)
++{
++ const struct efi_variable *var1 = *(const struct efi_variable **)p1;
++ const struct efi_variable *var2 = *(const struct efi_variable **)p2;
++ return strcmp (var1->name, var2->name);
++}
++
++static int
++read_boot_variables (struct efi_variable **varlist)
++{
++ int rc;
++ efi_guid_t *guid = NULL;
++ char *name = NULL;
++ struct efi_variable **newlist = NULL;
++ int nentries = 0;
++ int i;
++
++ while ((rc = efi_get_next_variable_name (&guid, &name)) > 0)
++ {
++ const char *snum = name + sizeof ("Boot") - 1;
++ struct efi_variable *var = NULL;
++ unsigned int num;
++
++ if (memcmp (guid, &efi_guid_global, sizeof (efi_guid_global)) != 0 ||
++ strncmp (name, "Boot", sizeof ("Boot") - 1) != 0 ||
++ !grub_isxdigit (snum[0]) || !grub_isxdigit (snum[1]) ||
++ !grub_isxdigit (snum[2]) || !grub_isxdigit (snum[3]))
++ continue;
++
++ rc = read_efi_variable (name, &var);
++ if (rc < 0)
++ break;
++
++ if (sscanf (var->name, "Boot%04X-%*s", &num) == 1 && num < 65536)
++ var->num = num;
++
++ newlist = xrealloc (newlist, (++nentries) * sizeof (*newlist));
++ newlist[nentries - 1] = var;
++ }
++ if (rc == 0 && newlist)
++ {
++ qsort (newlist, nentries, sizeof (*newlist), cmpvarbyname);
++ for (i = nentries - 1; i >= 0; --i)
++ grub_list_push (GRUB_AS_LIST_P (varlist), GRUB_AS_LIST (newlist[i]));
++ }
++ else if (newlist)
++ {
++ for (i = 0; i < nentries; ++i)
++ free_efi_variable (newlist[i]);
++ free (newlist);
++ }
++ return rc;
++}
++
++#define GET_ORDER(data, i) \
++ ((uint16_t) ((data)[(i) * 2]) + ((data)[(i) * 2 + 1] << 8))
++#define SET_ORDER(data, i, num) \
++ do { \
++ (data)[(i) * 2] = (num) & 0xFF; \
++ (data)[(i) * 2 + 1] = ((num) >> 8) & 0xFF; \
++ } while (0)
++
++static void
++remove_from_boot_order (struct efi_variable *order, uint16_t num)
++{
++ unsigned int old_i, new_i;
++
++ /* We've got an array (in order->data) of the order. Squeeze out any
++ instance of the entry we're deleting by shifting the remainder down. */
++ for (old_i = 0, new_i = 0;
++ old_i < order->data_size / sizeof (uint16_t);
++ ++old_i)
++ {
++ uint16_t old_num = GET_ORDER (order->data, old_i);
++ if (old_num != num)
++ {
++ if (new_i != old_i)
++ SET_ORDER (order->data, new_i, old_num);
++ ++new_i;
++ }
++ }
++
++ order->data_size = new_i * sizeof (uint16_t);
++}
++
++static void
++add_to_boot_order (struct efi_variable *order, uint16_t num)
++{
++ int i;
++ size_t new_data_size;
++ uint8_t *new_data;
++
++ /* Check whether this entry is already in the boot order. If it is, leave
++ it alone. */
++ for (i = 0; i < order->data_size / sizeof (uint16_t); ++i)
++ if (GET_ORDER (order->data, i) == num)
++ return;
++
++ new_data_size = order->data_size + sizeof (uint16_t);
++ new_data = xmalloc (new_data_size);
++ SET_ORDER (new_data, 0, num);
++ memcpy (new_data + sizeof (uint16_t), order->data, order->data_size);
++ free (order->data);
++ order->data = new_data;
++ order->data_size = new_data_size;
++}
++
++static int
++find_free_boot_num (struct efi_variable *entries)
++{
++ int num_vars = 0, i;
++ struct efi_variable *entry;
++
++ FOR_LIST_ELEMENTS (entry, entries)
++ ++num_vars;
++
++ if (num_vars == 0)
++ return 0;
++
++ /* O(n^2), but n is small and this is easy. */
++ for (i = 0; i < num_vars; ++i)
++ {
++ int found = 0;
++ FOR_LIST_ELEMENTS (entry, entries)
++ {
++ if (entry->num == i)
++ {
++ found = 1;
++ break;
++ }
++ }
++ if (!found)
++ return i;
++ }
++
++ return i;
++}
++
++static int
++get_edd_version (void)
++{
++ efi_guid_t blkx_guid = BLKX_UNKNOWN_GUID;
++ uint8_t *data = NULL;
++ size_t data_size = 0;
++ uint32_t attributes;
++ efidp_header *path;
++ int rc;
++
++ rc = efi_get_variable (blkx_guid, "blk0", &data, &data_size, &attributes);
++ if (rc < 0)
++ return rc;
++
++ path = (efidp_header *) data;
++ if (path->type == 2 && path->subtype == 1)
++ return 3;
++ return 1;
++}
++
++static struct efi_variable *
++make_boot_variable (int num, const char *disk, int part, const char *loader,
++ const char *label)
++{
++ struct efi_variable *entry = new_boot_variable ();
++ uint32_t options;
++ uint32_t edd10_devicenum;
++ ssize_t dp_needed, loadopt_needed;
++ efidp dp = NULL;
++
++ options = EFIBOOT_ABBREV_HD;
++ switch (get_edd_version ()) {
++ case 1:
++ options = EFIBOOT_ABBREV_EDD10;
++ break;
++ case 3:
++ options = EFIBOOT_ABBREV_NONE;
++ break;
++ }
++
++ /* This may not be the right disk; but it's probably only an issue on very
++ old hardware anyway. */
++ edd10_devicenum = 0x80;
++
++ dp_needed = efi_generate_file_device_path_from_esp (NULL, 0, disk, part,
++ loader, options,
++ edd10_devicenum);
++ if (dp_needed < 0)
++ goto err;
++
++ dp = xmalloc (dp_needed);
++ dp_needed = efi_generate_file_device_path_from_esp ((uint8_t *) dp,
++ dp_needed, disk, part,
++ loader, options,
++ edd10_devicenum);
++ if (dp_needed < 0)
++ goto err;
++
++ loadopt_needed = efi_loadopt_create (NULL, 0, LOAD_OPTION_ACTIVE,
++ dp, dp_needed, (unsigned char *) label,
++ NULL, 0);
++ if (loadopt_needed < 0)
++ goto err;
++ entry->data_size = loadopt_needed;
++ entry->data = xmalloc (entry->data_size);
++ loadopt_needed = efi_loadopt_create (entry->data, entry->data_size,
++ LOAD_OPTION_ACTIVE, dp, dp_needed,
++ (unsigned char *) label, NULL, 0);
++ if (loadopt_needed < 0)
++ goto err;
++
++ entry->name = xasprintf ("Boot%04X", num);
++ entry->num = num;
++
++ return entry;
++
++err:
++ free_efi_variable (entry);
++ free (dp);
++ return NULL;
++}
++
++int
++grub_install_efivar_register_efi (grub_device_t efidir_grub_dev,
++ const char *efifile_path,
++ const char *efi_distributor)
++{
++ const char *efidir_disk;
++ int efidir_part;
++ struct efi_variable *entries = NULL, *entry;
++ struct efi_variable *order;
++ int entry_num = -1;
++ int rc;
++
++ efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
++ efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
++
++#ifdef __linux__
++ /*
++ * Linux uses efivarfs (mounted on /sys/firmware/efi/efivars) to access the
++ * EFI variable store. Some legacy systems may still use the deprecated
++ * efivars interface (accessed through /sys/firmware/efi/vars). Where both
++ * are present, libefivar will use the former in preference, so attempting
++ * to load efivars will not interfere with later operations.
++ */
++ grub_util_exec_redirect_all ((const char * []){ "modprobe", "efivars", NULL },
++ NULL, NULL, "/dev/null");
++#endif
++
++ if (!efi_variables_supported ())
++ {
++ grub_util_warn ("%s",
++ _("EFI variables are not supported on this system."));
++ /* Let the user continue. Perhaps they can still arrange to boot GRUB
++ manually. */
++ return 0;
++ }
++
++ rc = read_boot_variables (&entries);
++ if (rc < 0)
++ {
++ grub_util_warn ("%s", _("Cannot read EFI Boot* variables"));
++ goto err;
++ }
++ rc = read_efi_variable ("BootOrder", &order);
++ if (rc < 0)
++ {
++ order = new_boot_variable ();
++ order->name = xstrdup ("BootOrder");
++ efi_error_clear ();
++ }
++
++ /* Delete old entries from the same distributor. */
++ FOR_LIST_ELEMENTS (entry, entries)
++ {
++ efi_load_option *load_option = (efi_load_option *) entry->data;
++ const char *label;
++
++ if (entry->num < 0)
++ continue;
++ label = (const char *) efi_loadopt_desc (load_option, entry->data_size);
++ if (strcasecmp (label, efi_distributor) != 0)
++ continue;
++
++ /* To avoid problems with some firmware implementations, reuse the first
++ matching variable we find rather than deleting and recreating it. */
++ if (entry_num == -1)
++ entry_num = entry->num;
++ else
++ {
++ grub_util_info ("deleting superfluous EFI variable %s (%s)",
++ entry->name, label);
++ rc = efi_del_variable (EFI_GLOBAL_GUID, entry->name);
++ if (rc < 0)
++ {
++ grub_util_warn (_("Cannot delete EFI variable %s"), entry->name);
++ goto err;
++ }
++ }
++
++ remove_from_boot_order (order, (uint16_t) entry->num);
++ }
++
++ if (entry_num == -1)
++ entry_num = find_free_boot_num (entries);
++ entry = make_boot_variable (entry_num, efidir_disk, efidir_part,
++ efifile_path, efi_distributor);
++ if (!entry)
++ goto err;
++
++ grub_util_info ("setting EFI variable %s", entry->name);
++ rc = set_efi_variable (entry->name, entry);
++ if (rc < 0)
++ goto err;
++
++ add_to_boot_order (order, (uint16_t) entry_num);
++
++ grub_util_info ("setting EFI variable BootOrder");
++ rc = set_efi_variable ("BootOrder", order);
++ if (rc < 0)
++ goto err;
++
++ return 0;
++
++err:
++ show_efi_errors ();
++ return errno;
++}
++
++#endif /* HAVE_EFIVAR */
+diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
+index 9c439326a..b561174ea 100644
+--- a/grub-core/osdep/unix/platform.c
++++ b/grub-core/osdep/unix/platform.c
+@@ -19,15 +19,12 @@
+ #include <config.h>
+
+ #include <grub/util/install.h>
+-#include <grub/emu/hostdisk.h>
+ #include <grub/util/misc.h>
+ #include <grub/misc.h>
+ #include <grub/i18n.h>
+ #include <grub/emu/exec.h>
+ #include <sys/types.h>
+-#include <dirent.h>
+ #include <string.h>
+-#include <errno.h>
+
+ static char *
+ get_ofpathname (const char *dev)
+@@ -78,102 +75,19 @@ get_ofpathname (const char *dev)
+ dev);
+ }
+
+-static int
+-grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
+-{
+- int fd;
+- pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd);
+- char *line = NULL;
+- size_t len = 0;
+- int rc = 0;
+-
+- if (!pid)
+- {
+- grub_util_warn (_("Unable to open stream from %s: %s"),
+- "efibootmgr", strerror (errno));
+- return errno;
+- }
+-
+- FILE *fp = fdopen (fd, "r");
+- if (!fp)
+- {
+- grub_util_warn (_("Unable to open stream from %s: %s"),
+- "efibootmgr", strerror (errno));
+- return errno;
+- }
+-
+- line = xmalloc (80);
+- len = 80;
+- while (1)
+- {
+- int ret;
+- char *bootnum;
+- ret = getline (&line, &len, fp);
+- if (ret == -1)
+- break;
+- if (grub_memcmp (line, "Boot", sizeof ("Boot") - 1) != 0
+- || line[sizeof ("Boot") - 1] < '0'
+- || line[sizeof ("Boot") - 1] > '9')
+- continue;
+- if (!strcasestr (line, efi_distributor))
+- continue;
+- bootnum = line + sizeof ("Boot") - 1;
+- bootnum[4] = '\0';
+- if (!verbosity)
+- rc = grub_util_exec ((const char * []){ "efibootmgr", "-q",
+- "-b", bootnum, "-B", NULL });
+- else
+- rc = grub_util_exec ((const char * []){ "efibootmgr",
+- "-b", bootnum, "-B", NULL });
+- }
+-
+- free (line);
+- return rc;
+-}
+-
+ int
+ grub_install_register_efi (grub_device_t efidir_grub_dev,
+ const char *efifile_path,
+ const char *efi_distributor)
+ {
+- const char * efidir_disk;
+- int efidir_part;
+- int ret;
+- efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
+- efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
+-
+- if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL }))
+- {
+- /* TRANSLATORS: This message is shown when required executable `%s'
+- isn't found. */
+- grub_util_error (_("%s: not found"), "efibootmgr");
+- }
+-
+- /* On Linux, we need the efivars kernel modules. */
+-#ifdef __linux__
+- grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL });
++#ifdef HAVE_EFIVAR
++ return grub_install_efivar_register_efi (efidir_grub_dev, efifile_path,
++ efi_distributor);
++#else
++ grub_util_error ("%s",
++ _("GRUB was not built with efivar support; "
++ "cannot register EFI boot entry"));
+ #endif
+- /* Delete old entries from the same distributor. */
+- ret = grub_install_remove_efi_entries_by_distributor (efi_distributor);
+- if (ret)
+- return ret;
+-
+- char *efidir_part_str = xasprintf ("%d", efidir_part);
+-
+- if (!verbosity)
+- ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
+- "-c", "-d", efidir_disk,
+- "-p", efidir_part_str, "-w",
+- "-L", efi_distributor, "-l",
+- efifile_path, NULL });
+- else
+- ret = grub_util_exec ((const char * []){ "efibootmgr",
+- "-c", "-d", efidir_disk,
+- "-p", efidir_part_str, "-w",
+- "-L", efi_distributor, "-l",
+- efifile_path, NULL });
+- free (efidir_part_str);
+- return ret;
+ }
+
+ void
+diff --git a/include/grub/util/install.h b/include/grub/util/install.h
+index 135ba48d2..134b862ec 100644
+--- a/include/grub/util/install.h
++++ b/include/grub/util/install.h
+@@ -226,6 +226,11 @@ grub_install_get_default_x86_platform (void);
+ const char *
+ grub_install_get_default_powerpc_machtype (void);
+
++int
++grub_install_efivar_register_efi (grub_device_t efidir_grub_dev,
++ const char *efifile_path,
++ const char *efi_distributor);
++
+ int
+ grub_install_register_efi (grub_device_t efidir_grub_dev,
+ const char *efifile_path,
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 58f1453ba..05b695226 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -2086,7 +2086,7 @@ main (int argc, char *argv[])
+ "\\System\\Library\\CoreServices",
+ efi_distributor);
+ if (ret)
+- grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
++ grub_util_error (_("failed to register the EFI boot entry: %s"),
+ strerror (ret));
+ }
+
+@@ -2203,7 +2203,7 @@ main (int argc, char *argv[])
+ ret = grub_install_register_efi (efidir_grub_dev,
+ efifile_path, efi_distributor);
+ if (ret)
+- grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
++ grub_util_error (_("failed to register the EFI boot entry: %s"),
+ strerror (ret));
+ }
+ break;
diff --git a/debian/patches/efinet-set-dns-from-uefi-proto.patch b/debian/patches/efinet-set-dns-from-uefi-proto.patch
new file mode 100644
index 0000000..9b5861b
--- /dev/null
+++ b/debian/patches/efinet-set-dns-from-uefi-proto.patch
@@ -0,0 +1,341 @@
+From 5a2c53dd059351cf385575fa99d5763bc07e0de2 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 27 Oct 2016 17:43:21 -0400
+Subject: efinet: Setting DNS server from UEFI protocol
+
+In the URI device path node, any name rahter than address can be used for
+looking up the resources so that DNS service become needed to get answer of the
+name's address. Unfortunately the DNS is not defined in any of the device path
+nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL
+to obtain it.
+
+These two protcols are defined the sections of UEFI specification.
+
+ 27.5 EFI IPv4 Configuration II Protocol
+ 27.7 EFI IPv6 Configuration Protocol
+
+include/grub/efi/api.h:
+Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and
+EFI_IP6_CONFIG_PROTOCOL.
+
+grub-core/net/drivers/efi/efinet.c:
+Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list
+of DNS server address for IPv4 and IPv6 respectively. The address of DNS
+servers is structured into DHCPACK packet and feed into the same DHCP packet
+processing functions to ensure the network interface is setting up the same way
+it used to be.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Last-Update: 2021-09-24
+
+Patch-Name: efinet-set-dns-from-uefi-proto.patch
+---
+ grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++
+ include/grub/efi/api.h | 76 ++++++++++++++
+ 2 files changed, 239 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 2d3b00f0e..82a28fb6e 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -30,6 +30,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ /* GUID. */
+ static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
+ static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
+
+ static grub_err_t
+ send_card_buffer (struct grub_net_card *dev,
+@@ -325,6 +327,125 @@ grub_efinet_findcards (void)
+ grub_free (handles);
+ }
+
++static grub_efi_handle_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
++ grub_efi_device_path_t **r_device_path)
++{
++ grub_efi_handle_t handle;
++ grub_efi_status_t status;
++
++ status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path,
++ protocol, &device_path, &handle);
++
++ if (status != GRUB_EFI_SUCCESS)
++ return 0;
++
++ if (r_device_path)
++ *r_device_path = device_path;
++
++ return handle;
++}
++
++static grub_efi_ipv4_address_t *
++grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
++{
++ grub_efi_handle_t hnd;
++ grub_efi_status_t status;
++ grub_efi_ip4_config2_protocol_t *conf;
++ grub_efi_ipv4_address_t *addrs;
++ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t);
++
++ hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL);
++
++ if (!hnd)
++ return 0;
++
++ conf = grub_efi_open_protocol (hnd, &ip4_config_guid,
++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++ if (!conf)
++ return 0;
++
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++
++ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++ {
++ grub_free (addrs);
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++ }
++
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ grub_free (addrs);
++ return 0;
++ }
++
++ *num_dns = data_size / sizeof (grub_efi_ipv4_address_t);
++ return addrs;
++}
++
++static grub_efi_ipv6_address_t *
++grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
++{
++ grub_efi_handle_t hnd;
++ grub_efi_status_t status;
++ grub_efi_ip6_config_protocol_t *conf;
++ grub_efi_ipv6_address_t *addrs;
++ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t);
++
++ hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL);
++
++ if (!hnd)
++ return 0;
++
++ conf = grub_efi_open_protocol (hnd, &ip6_config_guid,
++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++ if (!conf)
++ return 0;
++
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++
++ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++ {
++ grub_free (addrs);
++ addrs = grub_malloc (data_size);
++ if (!addrs)
++ return 0;
++
++ status = efi_call_4 (conf->get_data, conf,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++ &data_size, addrs);
++ }
++
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ grub_free (addrs);
++ return 0;
++ }
++
++ *num_dns = data_size / sizeof (grub_efi_ipv6_address_t);
++ return addrs;
++}
++
+ static struct grub_net_buff *
+ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
+ {
+@@ -377,6 +498,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
+ struct grub_net_bootp_packet *bp;
+ grub_uint8_t *ptr;
++ grub_efi_ipv4_address_t *dns;
++ grub_efi_uintn_t num_dns;
+
+ bp = (struct grub_net_bootp_packet *) nb->tail;
+ err = grub_netbuff_put (nb, sizeof (*bp) + 4);
+@@ -438,6 +561,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ *ptr++ = sizeof ("HTTPClient") - 1;
+ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+
++ dns = grub_dns_server_ip4_address (dp, &num_dns);
++ if (dns)
++ {
++ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
++
++ ptr = nb->tail;
++ err = grub_netbuff_put (nb, size_dns + 2);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ *ptr++ = GRUB_NET_BOOTP_DNS;
++ *ptr++ = size_dns;
++ grub_memcpy (ptr, dns, size_dns);
++ grub_free (dns);
++ }
++
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, 1);
+ if (err)
+@@ -470,6 +612,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ struct grub_net_dhcp6_option *opt;
+ struct grub_net_dhcp6_option_iana *iana;
+ struct grub_net_dhcp6_option_iaaddr *iaaddr;
++ grub_efi_ipv6_address_t *dns;
++ grub_efi_uintn_t num_dns;
+
+ d6p = (struct grub_net_dhcp6_packet *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*d6p));
+@@ -533,6 +677,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ opt->len = grub_cpu_to_be16 (uri_len);
+ grub_memcpy (opt->data, uri_dp->uri, uri_len);
+
++ dns = grub_dns_server_ip6_address (dp, &num_dns);
++ if (dns)
++ {
++ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
++
++ opt = (struct grub_net_dhcp6_option *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*opt) + size_dns);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS);
++ opt->len = grub_cpu_to_be16 (size_dns);
++ grub_memcpy (opt->data, dns, size_dns);
++ grub_free (dns);
++ }
++
+ *use_ipv6 = 1;
+ }
+
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 4b4652ca5..9cab1a51d 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -354,6 +354,16 @@
+ { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \
+ }
+
++#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \
++ { 0x5b446ed1, 0xe30b, 0x4faa, \
++ { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
++ }
++
++#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \
++ { 0x937fe521, 0x95ae, 0x4d1a, \
++ { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
++ }
++
+ struct grub_efi_sal_system_table
+ {
+ grub_uint32_t signature;
+@@ -1793,6 +1803,72 @@ struct grub_efi_rng_protocol
+ };
+ typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t;
+
++enum grub_efi_ip4_config2_data_type {
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM
++};
++typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t;
++
++struct grub_efi_ip4_config2_protocol
++{
++ grub_efi_status_t (*set_data) (struct grub_efi_ip4_config2_protocol *this,
++ grub_efi_ip4_config2_data_type_t data_type,
++ grub_efi_uintn_t data_size,
++ void *data);
++
++ grub_efi_status_t (*get_data) (struct grub_efi_ip4_config2_protocol *this,
++ grub_efi_ip4_config2_data_type_t data_type,
++ grub_efi_uintn_t *data_size,
++ void *data);
++
++ grub_efi_status_t (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this,
++ grub_efi_ip4_config2_data_type_t data_type,
++ grub_efi_event_t event);
++
++ grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this,
++ grub_efi_ip4_config2_data_type_t data_type,
++ grub_efi_event_t event);
++};
++typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
++
++enum grub_efi_ip6_config_data_type {
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM
++};
++typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t;
++
++struct grub_efi_ip6_config_protocol
++{
++ grub_efi_status_t (*set_data) (struct grub_efi_ip6_config_protocol *this,
++ grub_efi_ip6_config_data_type_t data_type,
++ grub_efi_uintn_t data_size,
++ void *data);
++
++ grub_efi_status_t (*get_data) (struct grub_efi_ip6_config_protocol *this,
++ grub_efi_ip6_config_data_type_t data_type,
++ grub_efi_uintn_t *data_size,
++ void *data);
++
++ grub_efi_status_t (*register_data_notify) (struct grub_efi_ip6_config_protocol *this,
++ grub_efi_ip6_config_data_type_t data_type,
++ grub_efi_event_t event);
++
++ grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this,
++ grub_efi_ip6_config_data_type_t data_type,
++ grub_efi_event_t event);
++};
++typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
++
+ #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
+ || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
+ || defined(__riscv)
diff --git a/debian/patches/efinet-set-network-from-uefi-devpath.patch b/debian/patches/efinet-set-network-from-uefi-devpath.patch
new file mode 100644
index 0000000..bf97ddf
--- /dev/null
+++ b/debian/patches/efinet-set-network-from-uefi-devpath.patch
@@ -0,0 +1,388 @@
+From 3f85b646c8f6188f6e2122fc90351fb900e1b337 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 27 Oct 2016 17:43:05 -0400
+Subject: efinet: Setting network from UEFI device path
+
+The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
+longer provided for HTTP Boot. Instead, we have to get the HTTP boot
+information from the device path nodes defined in following UEFI Specification
+sections.
+
+ 9.3.5.12 IPv4 Device Path
+ 9.3.5.13 IPv6 Device Path
+ 9.3.5.23 Uniform Resource Identifiers (URI) Device Path
+
+This patch basically does:
+
+include/grub/efi/api.h:
+Add new structure of Uniform Resource Identifiers (URI) Device Path
+
+grub-core/net/drivers/efi/efinet.c:
+Check if PXE Base Code is available, if not it will try to obtain the netboot
+information from the device path where the image booted from. The DHCPACK
+packet is recoverd from the information in device patch and feed into the same
+DHCP packet processing functions to ensure the network interface is setting up
+the same way it used to be.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Patch-Name: efinet-set-network-from-uefi-devpath.patch
+---
+ grub-core/net/drivers/efi/efinet.c | 268 ++++++++++++++++++++++++++++-
+ include/grub/efi/api.h | 11 ++
+ 2 files changed, 270 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index fc90415f2..2d3b00f0e 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -23,6 +23,7 @@
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
+ #include <grub/i18n.h>
++#include <grub/net/netbuff.h>
+
+ GRUB_MOD_LICENSE ("GPLv3+");
+
+@@ -324,6 +325,221 @@ grub_efinet_findcards (void)
+ grub_free (handles);
+ }
+
++static struct grub_net_buff *
++grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
++{
++ grub_efi_uint16_t uri_len;
++ grub_efi_device_path_t *ldp, *ddp;
++ grub_efi_uri_device_path_t *uri_dp;
++ struct grub_net_buff *nb;
++ grub_err_t err;
++
++ ddp = grub_efi_duplicate_device_path (dp);
++ ldp = grub_efi_find_last_device_path (ddp);
++
++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
++ {
++ grub_free (ddp);
++ return NULL;
++ }
++
++ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0;
++
++ if (!uri_len)
++ {
++ grub_free (ddp);
++ return NULL;
++ }
++
++ uri_dp = (grub_efi_uri_device_path_t *) ldp;
++
++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++ ldp->length = sizeof (*ldp);
++
++ ldp = grub_efi_find_last_device_path (ddp);
++
++ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
++ {
++ grub_free (ddp);
++ return NULL;
++ }
++
++ nb = grub_netbuff_alloc (512);
++ if (!nb)
++ return NULL;
++
++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
++ {
++ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
++ struct grub_net_bootp_packet *bp;
++ grub_uint8_t *ptr;
++
++ bp = (struct grub_net_bootp_packet *) nb->tail;
++ err = grub_netbuff_put (nb, sizeof (*bp) + 4);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++
++ if (sizeof(bp->boot_file) < uri_len)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
++ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
++ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip));
++
++ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
++ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1;
++ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2;
++ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3;
++
++ ptr = nb->tail;
++ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ *ptr++ = GRUB_NET_BOOTP_NETMASK;
++ *ptr++ = sizeof (ipv4->subnet_mask);
++ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask));
++
++ ptr = nb->tail;
++ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ *ptr++ = GRUB_NET_BOOTP_ROUTER;
++ *ptr++ = sizeof (ipv4->gateway_ip_address);
++ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address));
++
++ ptr = nb->tail;
++ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER;
++ *ptr++ = sizeof ("HTTPClient") - 1;
++ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
++
++ ptr = nb->tail;
++ err = grub_netbuff_put (nb, 1);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ *ptr = GRUB_NET_BOOTP_END;
++ *use_ipv6 = 0;
++
++ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++ ldp->length = sizeof (*ldp);
++ ldp = grub_efi_find_last_device_path (ddp);
++
++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
++ {
++ grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp;
++ bp->hw_type = mac->if_type;
++ bp->hw_len = sizeof (bp->mac_addr);
++ grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len);
++ }
++ }
++ else
++ {
++ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp;
++
++ struct grub_net_dhcp6_packet *d6p;
++ struct grub_net_dhcp6_option *opt;
++ struct grub_net_dhcp6_option_iana *iana;
++ struct grub_net_dhcp6_option_iaaddr *iaaddr;
++
++ d6p = (struct grub_net_dhcp6_packet *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*d6p));
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ d6p->message_type = GRUB_NET_DHCP6_REPLY;
++
++ opt = (struct grub_net_dhcp6_option *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*opt));
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
++ opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr));
++
++ err = grub_netbuff_put (nb, sizeof(*iana));
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++
++ opt = (struct grub_net_dhcp6_option *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*opt));
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
++ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
++
++ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*iaaddr));
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address));
++
++ opt = (struct grub_net_dhcp6_option *)nb->tail;
++ err = grub_netbuff_put (nb, sizeof(*opt) + uri_len);
++ if (err)
++ {
++ grub_free (ddp);
++ grub_netbuff_free (nb);
++ return NULL;
++ }
++ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL);
++ opt->len = grub_cpu_to_be16 (uri_len);
++ grub_memcpy (opt->data, uri_dp->uri, uri_len);
++
++ *use_ipv6 = 1;
++ }
++
++ grub_free (ddp);
++ return nb;
++}
++
+ static void
+ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ char **path)
+@@ -340,6 +556,11 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ grub_efi_device_path_t *cdp;
+ struct grub_efi_pxe *pxe;
+ struct grub_efi_pxe_mode *pxe_mode;
++ grub_uint8_t *packet_buf;
++ grub_size_t packet_bufsz ;
++ int ipv6;
++ struct grub_net_buff *nb = NULL;
++
+ if (card->driver != &efidriver)
+ continue;
+ cdp = grub_efi_get_device_path (card->efi_handle);
+@@ -359,11 +580,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ ldp = grub_efi_find_last_device_path (dp);
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+- && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
++ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
+ continue;
+ dup_dp = grub_efi_duplicate_device_path (dp);
+ if (!dup_dp)
+ continue;
++
++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
++ {
++ dup_ldp = grub_efi_find_last_device_path (dup_dp);
++ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++ dup_ldp->length = sizeof (*dup_ldp);
++ }
++
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+@@ -375,16 +606,31 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ }
+ pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+- if (! pxe)
+- continue;
+- pxe_mode = pxe->mode;
++ if (!pxe)
++ {
++ nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6);
++ if (!nb)
++ {
++ grub_print_error ();
++ continue;
++ }
++ packet_buf = nb->head;
++ packet_bufsz = nb->tail - nb->head;
++ }
++ else
++ {
++ pxe_mode = pxe->mode;
++ packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack;
++ packet_bufsz = sizeof (pxe_mode->dhcp_ack);
++ ipv6 = pxe_mode->using_ipv6;
++ }
+
+- if (pxe_mode->using_ipv6)
++ if (ipv6)
+ {
+ grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
+ (struct grub_net_dhcp6_packet *)
+- &pxe_mode->dhcp_ack,
+- sizeof (pxe_mode->dhcp_ack),
++ packet_buf,
++ packet_bufsz,
+ 1, device, path);
+ if (grub_errno)
+ grub_print_error ();
+@@ -393,10 +639,14 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ {
+ grub_net_configure_by_dhcp_ack (card->name, card, 0,
+ (struct grub_net_bootp_packet *)
+- &pxe_mode->dhcp_ack,
+- sizeof (pxe_mode->dhcp_ack),
++ packet_buf,
++ packet_bufsz,
+ 1, device, path);
+ }
++
++ if (nb)
++ grub_netbuff_free (nb);
++
+ return;
+ }
+ }
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 50ab8e844..4b4652ca5 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -849,6 +849,8 @@ struct grub_efi_ipv4_device_path
+ grub_efi_uint16_t remote_port;
+ grub_efi_uint16_t protocol;
+ grub_efi_uint8_t static_ip_address;
++ grub_efi_ipv4_address_t gateway_ip_address;
++ grub_efi_ipv4_address_t subnet_mask;
+ } GRUB_PACKED;
+ typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
+
+@@ -903,6 +905,15 @@ struct grub_efi_sata_device_path
+ } GRUB_PACKED;
+ typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t;
+
++#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24
++
++struct grub_efi_uri_device_path
++{
++ grub_efi_device_path_t header;
++ grub_efi_uint8_t uri[0];
++} GRUB_PACKED;
++typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
++
+ #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10
+
+ /* Media Device Path. */
diff --git a/debian/patches/efinet-uefi-ipv6-pxe-support.patch b/debian/patches/efinet-uefi-ipv6-pxe-support.patch
new file mode 100644
index 0000000..3a75beb
--- /dev/null
+++ b/debian/patches/efinet-uefi-ipv6-pxe-support.patch
@@ -0,0 +1,126 @@
+From a124f295433d6d3f371730b93d6468e6d5ad58e1 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 27 Oct 2016 17:41:21 -0400
+Subject: efinet: UEFI IPv6 PXE support
+
+When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is
+cached in firmware buffer which can be obtained by PXE Base Code protocol. The
+network interface can be setup through the parameters in that obtained packet.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Patch-Name: efinet-uefi-ipv6-pxe-support.patch
+---
+ grub-core/net/drivers/efi/efinet.c | 24 ++++++++++---
+ include/grub/efi/api.h | 55 +++++++++++++++++++++++++++++-
+ 2 files changed, 73 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 5388f952b..fc90415f2 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -378,11 +378,25 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ if (! pxe)
+ continue;
+ pxe_mode = pxe->mode;
+- grub_net_configure_by_dhcp_ack (card->name, card, 0,
+- (struct grub_net_bootp_packet *)
+- &pxe_mode->dhcp_ack,
+- sizeof (pxe_mode->dhcp_ack),
+- 1, device, path);
++
++ if (pxe_mode->using_ipv6)
++ {
++ grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
++ (struct grub_net_dhcp6_packet *)
++ &pxe_mode->dhcp_ack,
++ sizeof (pxe_mode->dhcp_ack),
++ 1, device, path);
++ if (grub_errno)
++ grub_print_error ();
++ }
++ else
++ {
++ grub_net_configure_by_dhcp_ack (card->name, card, 0,
++ (struct grub_net_bootp_packet *)
++ &pxe_mode->dhcp_ack,
++ sizeof (pxe_mode->dhcp_ack),
++ 1, device, path);
++ }
+ return;
+ }
+ }
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index f1a52210c..50ab8e844 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -1476,14 +1476,67 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output
+
+ typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
+
++typedef struct {
++ grub_uint8_t addr[4];
++} grub_efi_pxe_ipv4_address_t;
++
++typedef struct {
++ grub_uint8_t addr[16];
++} grub_efi_pxe_ipv6_address_t;
++
++typedef struct {
++ grub_uint8_t addr[32];
++} grub_efi_pxe_mac_address_t;
++
++typedef union {
++ grub_uint32_t addr[4];
++ grub_efi_pxe_ipv4_address_t v4;
++ grub_efi_pxe_ipv6_address_t v6;
++} grub_efi_pxe_ip_address_t;
++
++#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
++typedef struct {
++ grub_uint8_t filters;
++ grub_uint8_t ip_cnt;
++ grub_uint16_t reserved;
++ grub_efi_pxe_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT];
++} grub_efi_pxe_ip_filter_t;
++
++typedef struct {
++ grub_efi_pxe_ip_address_t ip_addr;
++ grub_efi_pxe_mac_address_t mac_addr;
++} grub_efi_pxe_arp_entry_t;
++
++typedef struct {
++ grub_efi_pxe_ip_address_t ip_addr;
++ grub_efi_pxe_ip_address_t subnet_mask;
++ grub_efi_pxe_ip_address_t gw_addr;
++} grub_efi_pxe_route_entry_t;
++
++
++#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8
++#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8
++
+ typedef struct grub_efi_pxe_mode
+ {
+- grub_uint8_t unused[52];
++ grub_uint8_t started;
++ grub_uint8_t ipv6_available;
++ grub_uint8_t ipv6_supported;
++ grub_uint8_t using_ipv6;
++ grub_uint8_t unused[16];
++ grub_efi_pxe_ip_address_t station_ip;
++ grub_efi_pxe_ip_address_t subnet_mask;
+ grub_efi_pxe_packet_t dhcp_discover;
+ grub_efi_pxe_packet_t dhcp_ack;
+ grub_efi_pxe_packet_t proxy_offer;
+ grub_efi_pxe_packet_t pxe_discover;
+ grub_efi_pxe_packet_t pxe_reply;
++ grub_efi_pxe_packet_t pxe_bis_reply;
++ grub_efi_pxe_ip_filter_t ip_filter;
++ grub_uint32_t arp_cache_entries;
++ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES];
++ grub_uint32_t route_table_entries;
++ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES];
+ } grub_efi_pxe_mode_t;
+
+ typedef struct grub_efi_pxe
diff --git a/debian/patches/fix-lockdown.patch b/debian/patches/fix-lockdown.patch
new file mode 100644
index 0000000..54a7928
--- /dev/null
+++ b/debian/patches/fix-lockdown.patch
@@ -0,0 +1,45 @@
+From b2c4515a832f82a4fe4ee8d32faa16b48de63d12 Mon Sep 17 00:00:00 2001
+From: Luca Boccassi <bluca@debian.org>
+Date: Tue, 15 May 2018 11:36:46 +0100
+Subject: Do not overwrite sentinel byte in boot_params, breaks lockdown
+
+grub currently copies the entire boot_params, which includes setting
+sentinel byte to 0xff, which triggers sanitize_boot_params in the kernel
+which in turn clears various boot_params variables, including the
+indication that the bootloader chain is verified and thus the kernel
+disables lockdown mode. According to the information on the Fedora bug
+tracker, only the information from byte 0x1f1 is necessary, so start
+copying from there instead.
+
+Author: Luca Boccassi <bluca@debian.org>
+Bug-Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1418360
+Forwarded: no
+
+Patch-Name: fix-lockdown.patch
+---
+ grub-core/loader/i386/efi/linux.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 45b68c05a..532e4e512 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -29,6 +29,7 @@
+ #include <grub/linux.h>
+ #include <grub/efi/efi.h>
+ #include <grub/efi/sb.h>
++#include <stddef.h>
+
+ GRUB_MOD_LICENSE ("GPLv3+");
+
+@@ -336,7 +337,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+ }
+
+- grub_memcpy (params, &lh, 2 * 512);
++ /* do not overwrite below boot_params->hdr to avoid setting the sentinel byte */
++ start = offsetof (struct linux_kernel_params, setup_sects);
++ grub_memcpy ((grub_uint8_t *)params + start, (grub_uint8_t *)&lh + start, 2 * 512 - start);
+
+ params->type_of_loader = 0x21;
+
diff --git a/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch b/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch
new file mode 100644
index 0000000..7c9209a
--- /dev/null
+++ b/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch
@@ -0,0 +1,76 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Wed, 16 Nov 2022 14:40:04 +0000
+Subject: font: Try opening fonts from the bundled memdisk
+
+---
+ grub-core/font/font.c | 48 +++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 31 insertions(+), 17 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index e6616e6..e421d1a 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -409,6 +409,27 @@ read_section_as_short (struct font_file_section *section,
+ return 0;
+ }
+
++static grub_file_t
++try_open_from_prefix (const char *prefix, const char *filename)
++{
++ grub_file_t file;
++ char *fullname, *ptr;
++
++ fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1
++ + sizeof ("/fonts/") + sizeof (".pf2"));
++ if (!fullname)
++ return 0;
++ ptr = grub_stpcpy (fullname, prefix);
++ ptr = grub_stpcpy (ptr, "/fonts/");
++ ptr = grub_stpcpy (ptr, filename);
++ ptr = grub_stpcpy (ptr, ".pf2");
++ *ptr = 0;
++
++ file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024);
++ grub_free (fullname);
++ return file;
++}
++
+ /* Load a font and add it to the beginning of the global font list.
+ Returns 0 upon success, nonzero upon failure. */
+ grub_font_t
+@@ -427,25 +448,18 @@ grub_font_load (const char *filename)
+ file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
+ else
+ {
+- const char *prefix = grub_env_get ("prefix");
+- char *fullname, *ptr;
+- if (!prefix)
++ file = try_open_from_prefix ("(memdisk)", filename);
++ if (!file)
+ {
+- grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
+- "prefix");
+- goto fail;
++ const char *prefix = grub_env_get ("prefix");
++ if (!prefix)
++ {
++ grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
++ "prefix");
++ goto fail;
++ }
++ file = try_open_from_prefix (prefix, filename);
+ }
+- fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1
+- + sizeof ("/fonts/") + sizeof (".pf2"));
+- if (!fullname)
+- goto fail;
+- ptr = grub_stpcpy (fullname, prefix);
+- ptr = grub_stpcpy (ptr, "/fonts/");
+- ptr = grub_stpcpy (ptr, filename);
+- ptr = grub_stpcpy (ptr, ".pf2");
+- *ptr = 0;
+- file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024);
+- grub_free (fullname);
+ }
+ if (!file)
+ goto fail;
diff --git a/debian/patches/fs-tester-time-fail.patch b/debian/patches/fs-tester-time-fail.patch
new file mode 100644
index 0000000..43675db
--- /dev/null
+++ b/debian/patches/fs-tester-time-fail.patch
@@ -0,0 +1,27 @@
+Explicitly unset SOURCE_DATE_EPOCH before running fs tests. In some
+filesystem utils like mksquashfs, it will silently change behaviour
+and cause timestamps to unexpectedly change. Reproducible builds are
+good and useful for shipped artifacts, but this causes build-time
+tests to fail.
+
+Author: Steve McIntyre
+
+Patch-Name: fs-tester-time-fail.patch
+---
+ tests/util/grub-fs-tester.in | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in
+index bfc425e1f..660691302 100644
+--- a/tests/util/grub-fs-tester.in
++++ b/tests/util/grub-fs-tester.in
+@@ -4,6 +4,9 @@ set -e
+
+ fs="$1"
+
++# We can't have this set, or filesystem tests will fail
++unset SOURCE_DATE_EPOCH
++
+ GRUBFSTEST="@builddir@/grub-fstest"
+
+ tempdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
diff --git a/debian/patches/gcc12_build_array_bounds.patch b/debian/patches/gcc12_build_array_bounds.patch
new file mode 100644
index 0000000..c28bcb6
--- /dev/null
+++ b/debian/patches/gcc12_build_array_bounds.patch
@@ -0,0 +1,493 @@
+Borrowed and tweaked fix from:
+
+commit acffb81485e35e1f28152949a1c6e1d4dbf5172e
+Author: Michael Chang <mchang@suse.com>
+Date: Mon Mar 28 15:00:53 2022 +0800
+
+build: Fix -Werror=array-bounds array subscript 0 is outside array bounds
+
+diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c
+index 8c90ed598..cd0a45e58 100644
+--- a/grub-core/bus/cs5536.c
++++ b/grub-core/bus/cs5536.c
+@@ -331,8 +331,9 @@ grub_cs5536_init_geode (grub_pci_device_t dev)
+
+ {
+ volatile grub_uint32_t *oc;
+- oc = grub_pci_device_map_range (dev, 0x05022000,
+- GRUB_CS5536_USB_OPTION_REGS_SIZE);
++
++ oc = grub_absolute_pointer (grub_pci_device_map_range (dev, 0x05022000,
++ GRUB_CS5536_USB_OPTION_REGS_SIZE));
+
+ oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] =
+ (oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX]
+diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
+index 1215f2a62..fda62f4ea 100644
+--- a/grub-core/commands/acpi.c
++++ b/grub-core/commands/acpi.c
+@@ -168,7 +168,7 @@ grub_acpi_create_ebda (void)
+ struct grub_acpi_rsdp_v10 *v1;
+ struct grub_acpi_rsdp_v20 *v2;
+
+- ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
++ ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4);
+ grub_dprintf ("acpi", "EBDA @%p\n", ebda);
+ if (ebda)
+ ebda_kb_len = *(grub_uint16_t *) ebda;
+@@ -298,7 +298,7 @@ grub_acpi_create_ebda (void)
+ *target = 0;
+
+ grub_dprintf ("acpi", "Switching EBDA\n");
+- (*((grub_uint16_t *) 0x40e)) = ((grub_addr_t) targetebda) >> 4;
++ (*((grub_uint16_t *) grub_absolute_pointer (0x40e))) = ((grub_addr_t) targetebda) >> 4;
+ grub_dprintf ("acpi", "EBDA switched\n");
+
+ return GRUB_ERR_NONE;
+diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c
+index 5c7725f8b..574e41046 100644
+--- a/grub-core/commands/efi/loadbios.c
++++ b/grub-core/commands/efi/loadbios.c
+@@ -46,7 +46,7 @@ enable_rom_area (void)
+ grub_uint32_t *rom_ptr;
+ grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
+
+- rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
++ rom_ptr = grub_absolute_pointer (VBIOS_ADDR);
+ if (*rom_ptr != BLANK_MEM)
+ {
+ grub_puts_ (N_("ROM image is present."));
+@@ -96,8 +96,8 @@ fake_bios_data (int use_rom)
+ void *acpi, *smbios;
+ grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
+
+- ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR;
+- low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR;
++ ebda_seg_ptr = grub_absolute_pointer (EBDA_SEG_ADDR);
++ low_mem_ptr = grub_absolute_pointer (LOW_MEM_ADDR);
+ if ((*ebda_seg_ptr) || (*low_mem_ptr))
+ return;
+
+@@ -132,7 +132,8 @@ fake_bios_data (int use_rom)
+ *ebda_seg_ptr = FAKE_EBDA_SEG;
+ *low_mem_ptr = (FAKE_EBDA_SEG >> 6);
+
+- *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr;
++ /* *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr; */
++ *((grub_uint16_t *) (grub_absolute_pointer (FAKE_EBDA_SEG << 4))) = 640 - *low_mem_ptr;
+
+ if (acpi)
+ grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16);
+diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c
+index 3fb22dc46..a7ee4c9bd 100644
+--- a/grub-core/commands/i386/pc/drivemap.c
++++ b/grub-core/commands/i386/pc/drivemap.c
+@@ -31,9 +31,6 @@
+
+ GRUB_MOD_LICENSE ("GPLv3+");
+
+-/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
+-static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13);
+-
+ /* Remember to update enum opt_idxs accordingly. */
+ static const struct grub_arg_option options[] = {
+ /* TRANSLATORS: In this file "mapping" refers to a change GRUB makes so if
+@@ -280,6 +277,8 @@ install_int13_handler (int noret __attribute__ ((unused)))
+ grub_uint8_t *handler_base = 0;
+ /* Address of the map within the deployed bundle. */
+ int13map_node_t *handler_map;
++ /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
++ grub_uint32_t *int13slot = (grub_uint32_t *) grub_absolute_pointer (4 * 0x13);
+
+ int i;
+ int entries = 0;
+@@ -354,6 +353,9 @@ install_int13_handler (int noret __attribute__ ((unused)))
+ static grub_err_t
+ uninstall_int13_handler (void)
+ {
++ /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
++ grub_uint32_t *int13slot = (grub_uint32_t *) grub_absolute_pointer (4 * 0x13);
++
+ if (! grub_drivemap_oldhandler)
+ return GRUB_ERR_NONE;
+
+diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c
+index 81fd4e832..49e4e8a14 100644
+--- a/grub-core/disk/i386/pc/biosdisk.c
++++ b/grub-core/disk/i386/pc/biosdisk.c
+@@ -367,7 +367,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
+ if (version)
+ {
+ struct grub_biosdisk_drp *drp
+- = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ = (struct grub_biosdisk_drp *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+
+ /* Clear out the DRP. */
+ grub_memset (drp, 0, sizeof (*drp));
+@@ -654,7 +654,7 @@ grub_disk_biosdisk_fini (void)
+ GRUB_MOD_INIT(biosdisk)
+ {
+ struct grub_biosdisk_cdrp *cdrp
+- = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ = (struct grub_biosdisk_cdrp *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ grub_uint8_t boot_drive;
+
+ if (grub_disk_firmware_is_tainted)
+diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
+index 581215ef1..8ab7106af 100644
+--- a/grub-core/fs/cbfs.c
++++ b/grub-core/fs/cbfs.c
+@@ -342,7 +342,7 @@ init_cbfsdisk (void)
+ grub_uint32_t ptr;
+ struct cbfs_header *head;
+
+- ptr = *(grub_uint32_t *) 0xfffffffc;
++ ptr = *((grub_uint32_t *) grub_absolute_pointer (0xfffffffc));
+ head = (struct cbfs_header *) (grub_addr_t) ptr;
+ grub_dprintf ("cbfs", "head=%p\n", head);
+
+diff --git a/grub-core/kern/i386/pc/acpi.c b/grub-core/kern/i386/pc/acpi.c
+index 297f5d05f..0a69eba7b 100644
+--- a/grub-core/kern/i386/pc/acpi.c
++++ b/grub-core/kern/i386/pc/acpi.c
+@@ -27,7 +27,7 @@ grub_machine_acpi_get_rsdpv1 (void)
+ grub_uint8_t *ebda, *ptr;
+
+ grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
+- ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
++ ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4);
+ ebda_len = * (grub_uint16_t *) ebda;
+ if (! ebda_len) /* FIXME do we really need this check? */
+ goto scan_bios;
+@@ -55,7 +55,7 @@ grub_machine_acpi_get_rsdpv2 (void)
+ grub_uint8_t *ebda, *ptr;
+
+ grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
+- ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
++ ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4);
+ ebda_len = * (grub_uint16_t *) ebda;
+ if (! ebda_len) /* FIXME do we really need this check? */
+ goto scan_bios;
+diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c
+index ef2faa2ab..53fcf45af 100644
+--- a/grub-core/kern/i386/pc/mmap.c
++++ b/grub-core/kern/i386/pc/mmap.c
+@@ -143,7 +143,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+ {
+ grub_uint32_t cont = 0;
+ struct grub_machine_mmap_entry *entry
+- = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ = (struct grub_machine_mmap_entry *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ int e820_works = 0;
+
+ while (1)
+diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
+index 6d680d671..00a48413c 100644
+--- a/grub-core/loader/multiboot_mbi2.c
++++ b/grub-core/loader/multiboot_mbi2.c
+@@ -504,7 +504,7 @@ static void
+ fill_vbe_tag (struct multiboot_tag_vbe *tag)
+ {
+ grub_vbe_status_t status;
+- void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+
+ tag->type = MULTIBOOT_TAG_TYPE_VBE;
+ tag->size = 0;
+@@ -577,7 +577,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig)
+ #if defined (GRUB_MACHINE_PCBIOS)
+ {
+ grub_vbe_status_t status;
+- void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ status = grub_vbe_bios_get_mode (scratch);
+ vbe_mode = *(grub_uint32_t *) scratch;
+ if (status != GRUB_VBE_STATUS_OK)
+diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c
+index 6ab4f6730..b9c5b0a00 100644
+--- a/grub-core/mmap/i386/pc/mmap.c
++++ b/grub-core/mmap/i386/pc/mmap.c
+@@ -80,13 +80,13 @@ preboot (int noreturn __attribute__ ((unused)))
+ = min (grub_mmap_get_post64 (), 0xfc000000ULL) >> 16;
+
+ /* Correct BDA. */
+- *((grub_uint16_t *) 0x413) = grub_mmap_get_lower () >> 10;
++ *((grub_uint16_t *) grub_absolute_pointer (0x413)) = grub_mmap_get_lower () >> 10;
+
+ /* Save old interrupt handlers. */
+- grub_machine_mmaphook_int12offset = *((grub_uint16_t *) 0x48);
+- grub_machine_mmaphook_int12segment = *((grub_uint16_t *) 0x4a);
+- grub_machine_mmaphook_int15offset = *((grub_uint16_t *) 0x54);
+- grub_machine_mmaphook_int15segment = *((grub_uint16_t *) 0x56);
++ grub_machine_mmaphook_int12offset = *((grub_uint16_t *) grub_absolute_pointer (0x48));
++ grub_machine_mmaphook_int12segment = *((grub_uint16_t *) grub_absolute_pointer (0x4a));
++ grub_machine_mmaphook_int15offset = *((grub_uint16_t *) grub_absolute_pointer (0x54));
++ grub_machine_mmaphook_int15segment = *((grub_uint16_t *) grub_absolute_pointer (0x56));
+
+ grub_dprintf ("mmap", "hooktarget = %p\n", hooktarget);
+
+@@ -94,11 +94,11 @@ preboot (int noreturn __attribute__ ((unused)))
+ grub_memcpy (hooktarget, &grub_machine_mmaphook_start,
+ &grub_machine_mmaphook_end - &grub_machine_mmaphook_start);
+
+- *((grub_uint16_t *) 0x4a) = ((grub_addr_t) hooktarget) >> 4;
+- *((grub_uint16_t *) 0x56) = ((grub_addr_t) hooktarget) >> 4;
+- *((grub_uint16_t *) 0x48) = &grub_machine_mmaphook_int12
++ *((grub_uint16_t *) grub_absolute_pointer (0x4a)) = ((grub_addr_t) hooktarget) >> 4;
++ *((grub_uint16_t *) grub_absolute_pointer (0x56)) = ((grub_addr_t) hooktarget) >> 4;
++ *((grub_uint16_t *) grub_absolute_pointer (0x48)) = &grub_machine_mmaphook_int12
+ - &grub_machine_mmaphook_start;
+- *((grub_uint16_t *) 0x54) = &grub_machine_mmaphook_int15
++ *((grub_uint16_t *) grub_absolute_pointer (0x54)) = &grub_machine_mmaphook_int15
+ - &grub_machine_mmaphook_start;
+
+ return GRUB_ERR_NONE;
+@@ -108,10 +108,10 @@ static grub_err_t
+ preboot_rest (void)
+ {
+ /* Restore old interrupt handlers. */
+- *((grub_uint16_t *) 0x48) = grub_machine_mmaphook_int12offset;
+- *((grub_uint16_t *) 0x4a) = grub_machine_mmaphook_int12segment;
+- *((grub_uint16_t *) 0x54) = grub_machine_mmaphook_int15offset;
+- *((grub_uint16_t *) 0x56) = grub_machine_mmaphook_int15segment;
++ *((grub_uint16_t *) grub_absolute_pointer (0x48)) = grub_machine_mmaphook_int12offset;
++ *((grub_uint16_t *) grub_absolute_pointer (0x4a)) = grub_machine_mmaphook_int12segment;
++ *((grub_uint16_t *) grub_absolute_pointer (0x54)) = grub_machine_mmaphook_int15offset;
++ *((grub_uint16_t *) grub_absolute_pointer (0x56)) = grub_machine_mmaphook_int15segment;
+
+ return GRUB_ERR_NONE;
+ }
+diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c
+index 997010cf1..db17186ee 100644
+--- a/grub-core/net/drivers/i386/pc/pxe.c
++++ b/grub-core/net/drivers/i386/pc/pxe.c
+@@ -174,7 +174,7 @@ grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)))
+ grub_uint8_t *ptr, *end;
+ struct grub_net_buff *buf;
+
+- isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ isr = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+
+ if (!in_progress)
+ {
+@@ -256,11 +256,11 @@ grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)),
+ struct grub_pxe_undi_tbd *tbd;
+ char *buf;
+
+- trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ trans = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ grub_memset (trans, 0, sizeof (*trans));
+- tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128);
++ tbd = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128);
+ grub_memset (tbd, 0, sizeof (*tbd));
+- buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256);
++ buf = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256);
+ grub_memcpy (buf, pack->data, pack->tail - pack->data);
+
+ trans->tbd = SEGOFS ((grub_addr_t) tbd);
+@@ -287,7 +287,7 @@ static grub_err_t
+ grub_pxe_open (struct grub_net_card *dev __attribute__ ((unused)))
+ {
+ struct grub_pxe_undi_open *ou;
+- ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ ou = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ grub_memset (ou, 0, sizeof (*ou));
+ ou->pkt_filter = 4;
+ grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry);
+@@ -382,7 +382,7 @@ GRUB_MOD_INIT(pxe)
+ if (! pxenv)
+ return;
+
+- ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ ui = (void *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ grub_memset (ui, 0, sizeof (*ui));
+ grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry);
+
+diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c
+index d44937c30..9403390f1 100644
+--- a/grub-core/term/i386/pc/console.c
++++ b/grub-core/term/i386/pc/console.c
+@@ -238,12 +238,11 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
+ return (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL);
+ }
+
+-static const struct grub_machine_bios_data_area *bios_data_area =
+- (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR;
+-
+ static int
+ grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused)))
+ {
++ const struct grub_machine_bios_data_area *bios_data_area =
++ (struct grub_machine_bios_data_area *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR);
+ /* conveniently GRUB keystatus is modelled after BIOS one. */
+ return bios_data_area->keyboard_flag_lower & ~0x80;
+ }
+diff --git a/grub-core/term/i386/pc/vga_text.c b/grub-core/term/i386/pc/vga_text.c
+index 88fecc5ea..669d06fad 100644
+--- a/grub-core/term/i386/pc/vga_text.c
++++ b/grub-core/term/i386/pc/vga_text.c
+@@ -45,15 +45,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ static struct grub_term_coordinate grub_curr_pos;
+
+ #ifdef __mips__
+-#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb00b8000)
++#define VGA_TEXT_SCREEN ((grub_uint16_t *) grub_absolute_pointer (0xb00b8000))
+ #define cr_read grub_vga_cr_read
+ #define cr_write grub_vga_cr_write
+ #elif defined (MODE_MDA)
+-#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb0000)
++#define VGA_TEXT_SCREEN ((grub_uint16_t *) grub_absolute_pointer (0xb0000))
+ #define cr_read grub_vga_cr_bw_read
+ #define cr_write grub_vga_cr_bw_write
+ #else
+-#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb8000)
++#define VGA_TEXT_SCREEN ((grub_uint16_t *) grub_absolute_pointer (0xb8000))
+ #define cr_read grub_vga_cr_read
+ #define cr_write grub_vga_cr_write
+ #endif
+diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c
+index 59801839b..83b25990c 100644
+--- a/grub-core/term/ns8250.c
++++ b/grub-core/term/ns8250.c
+@@ -28,7 +28,6 @@
+
+ #ifdef GRUB_MACHINE_PCBIOS
+ #include <grub/machine/memory.h>
+-static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR;
+ #define GRUB_SERIAL_PORT_NUM 4
+ #else
+ #include <grub/machine/serial.h>
+@@ -237,6 +236,9 @@ static struct grub_serial_port com_ports[GRUB_SERIAL_PORT_NUM];
+ void
+ grub_ns8250_init (void)
+ {
++#ifdef GRUB_MACHINE_PCBIOS
++ const unsigned short *serial_hw_io_addr = (const unsigned short *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR);
++#endif
+ unsigned i;
+ for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
+ if (serial_hw_io_addr[i])
+@@ -272,6 +274,9 @@ grub_ns8250_init (void)
+ grub_port_t
+ grub_ns8250_hw_get_port (const unsigned int unit)
+ {
++#ifdef GRUB_MACHINE_PCBIOS
++ const unsigned short *serial_hw_io_addr = (const unsigned short *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR);
++#endif
+ if (unit < GRUB_SERIAL_PORT_NUM
+ && !(dead_ports & (1 << unit)))
+ return serial_hw_io_addr[unit];
+diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c
+index 0e65b5206..a0bb9af09 100644
+--- a/grub-core/video/i386/pc/vbe.c
++++ b/grub-core/video/i386/pc/vbe.c
+@@ -514,7 +514,7 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block)
+
+ /* Use low memory scratch area as temporary storage
+ for VESA BIOS call. */
+- vbe_ib = (struct grub_vbe_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ vbe_ib = (struct grub_vbe_info_block *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+
+ /* Prepare info block. */
+ grub_memset (vbe_ib, 0, sizeof (*vbe_ib));
+@@ -574,7 +574,7 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height)
+
+ /* Use low memory scratch area as temporary storage for VESA BIOS calls. */
+ flat_panel_info = (struct grub_vbe_flat_panel_info *)
+- (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info));
++ grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info));
+
+ if (controller_info.version >= 0x200
+ && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff)
+@@ -676,7 +676,7 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode,
+ == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+ {
+ struct grub_vbe_palette_data *palette
+- = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ = (struct grub_vbe_palette_data *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+ unsigned i;
+
+ /* Make sure that the BIOS can reach the palette. */
+diff --git a/include/grub/types.h b/include/grub/types.h
+index 0a3ff1591..5ae0ced38 100644
+--- a/include/grub/types.h
++++ b/include/grub/types.h
+@@ -340,4 +340,28 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
+ dd->d = val;
+ }
+
++/*
++ * The grub_absolute_pointer() macro borrows the idea from Linux kernel of using
++ * RELOC_HIDE() macro to stop GCC from checking the result of pointer arithmetic
++ * and also it's conversion to be inside the symbol's boundary [1]. The check
++ * is sometimes false positive, especially it is controversial to emit the array
++ * bounds [-Warray-bounds] warning on all hardwired literal pointers since GCC
++ * 11/12 [2]. Unless a good solution can be settled, for the time being we
++ * would be in favor of the macro instead of GCC pragmas which cannot match the
++ * places the warning needs to be ignored in an exact way.
++ *
++ * [1] https://lists.linuxcoding.com/kernel/2006-q3/msg17979.html
++ * [2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578
++ */
++#if defined(__GNUC__)
++# define grub_absolute_pointer(val) \
++({ \
++ grub_addr_t __ptr; \
++ asm ("" : "=r" (__ptr) : "0" ((void *) (val))); \
++ (void *) (__ptr); \
++})
++#else
++# define grub_absolute_pointer(val) ((void *) (val))
++#endif
++
+ #endif /* ! GRUB_TYPES_HEADER */
+diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
+index a67d9d0a8..434e694ff 100644
+--- a/grub-core/loader/i386/multiboot_mbi.c
++++ b/grub-core/loader/i386/multiboot_mbi.c
+@@ -293,7 +293,7 @@ fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig,
+ struct grub_vbe_mode_info_block *mode_info;
+ #if GRUB_MACHINE_HAS_VBE
+ grub_vbe_status_t status;
+- void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++ void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+
+ status = grub_vbe_bios_get_controller_info (scratch);
+ if (status != GRUB_VBE_STATUS_OK)
+diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c
+index 26d9acd3d..9fbd8cb2c 100644
+--- a/grub-core/commands/i386/pc/sendkey.c
++++ b/grub-core/commands/i386/pc/sendkey.c
+@@ -216,12 +216,12 @@ static grub_err_t
+ grub_sendkey_postboot (void)
+ {
+ /* For convention: pointer to flags. */
+- grub_uint32_t *flags = (grub_uint32_t *) 0x417;
++ grub_uint32_t *flags = grub_absolute_pointer (0x417);
+
+ *flags = oldflags;
+
+- *((char *) 0x41a) = 0x1e;
+- *((char *) 0x41c) = 0x1e;
++ *((volatile char *) grub_absolute_pointer (0x41a)) = 0x1e;
++ *((volatile char *) grub_absolute_pointer (0x41c)) = 0x1e;
+
+ return GRUB_ERR_NONE;
+ }
+@@ -231,13 +231,13 @@ static grub_err_t
+ grub_sendkey_preboot (int noret __attribute__ ((unused)))
+ {
+ /* For convention: pointer to flags. */
+- grub_uint32_t *flags = (grub_uint32_t *) 0x417;
++ grub_uint32_t *flags = grub_absolute_pointer (0x417);
+
+ oldflags = *flags;
+
+ /* Set the sendkey. */
+- *((char *) 0x41a) = 0x1e;
+- *((char *) 0x41c) = keylen + 0x1e;
++ *((volatile char *) grub_absolute_pointer (0x41a)) = 0x1e;
++ *((volatile char *) grub_absolute_pointer (0x41c)) = keylen + 0x1e;
+ grub_memcpy ((char *) 0x41e, sendkey, 0x20);
+
+ /* Transform "any ctrl" to "right ctrl" flag. */
diff --git a/debian/patches/gcc12_build_array_bounds2.patch b/debian/patches/gcc12_build_array_bounds2.patch
new file mode 100644
index 0000000..6036eba
--- /dev/null
+++ b/debian/patches/gcc12_build_array_bounds2.patch
@@ -0,0 +1,46 @@
+commit 3ce13d974b887338ae972c79b41ff6fc0eee6388
+Author: Michael Chang <mchang@suse.com>
+Date: Mon Mar 28 15:00:54 2022 +0800
+
+ lib/reed_solomon: Fix array subscript 0 is outside array bounds
+
+ The grub_absolute_pointer() is a compound expression that can only work
+ within a function. We are out of luck here when the pointer variables
+ require global definition due to ATTRIBUTE_TEXT that have to use fully
+ initialized global definition because of the way linkers work.
+
+ static gf_single_t * const gf_powx ATTRIBUTE_TEXT = (void *) 0x100000;
+
+ For the reason given above, use GCC diagnostic pragmas to suppress the
+ array-bounds warning.
+
+ Signed-off-by: Michael Chang <mchang@suse.com>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c
+index 82779a296..562bd2e3e 100644
+--- a/grub-core/lib/reed_solomon.c
++++ b/grub-core/lib/reed_solomon.c
+@@ -102,6 +102,11 @@ static gf_single_t errvals[256];
+ static gf_single_t eqstat[65536 + 256];
+ #endif
+
++#if __GNUC__ == 12
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Warray-bounds"
++#endif
++
+ static gf_single_t
+ gf_mul (gf_single_t a, gf_single_t b)
+ {
+@@ -319,6 +324,10 @@ decode_block (gf_single_t *ptr, grub_size_t s,
+ }
+ }
+
++#if __GNUC__ == 12
++#pragma GCC diagnostic pop
++#endif
++
+ #if !defined (STANDALONE)
+ static void
+ encode_block (gf_single_t *ptr, grub_size_t s,
diff --git a/debian/patches/gcc12_build_dangling_pointer.patch b/debian/patches/gcc12_build_dangling_pointer.patch
new file mode 100644
index 0000000..78bbacb
--- /dev/null
+++ b/debian/patches/gcc12_build_dangling_pointer.patch
@@ -0,0 +1,67 @@
+Borrowed and tweaked fix from:
+
+commit be8eb0eed69f8bc9ac20837eae58e55218011880
+Author: Michael Chang <mchang@suse.com>
+Date: Mon Mar 28 15:00:52 2022 +0800
+
+ util/mkimage: Fix dangling pointer may be used error
+
+diff --git a/util/mkimage.c b/util/mkimage.c
+index a26cf76f7..58c199f7c 100644
+--- a/util/mkimage 2022-12-11 15:41:56.717934782 +0000
++++ b/util/mkimage.c 2022-12-11 15:43:05.318432532 +0000
+@@ -1383,6 +1383,10 @@
+ section = (struct grub_pe32_section_table *)(o64 + 1);
+ }
+
++#if __GNUC__ >= 12
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wdangling-pointer"
++#endif
+ PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
+ PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
+ PE_OHDR (o32, o64, image_base) = 0;
+@@ -1402,6 +1406,9 @@
+ /* The sections. */
+ PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (vma);
+ PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
++#if __GNUC__ >= 12
++#pragma GCC diagnostic pop
++#endif
+ section = init_pe_section (image_target, section, ".text",
+ &vma, layout.exec_size,
+ image_target->section_align,
+@@ -1413,10 +1420,17 @@
+ raw_size = layout.kernel_size - layout.exec_size;
+ scn_size = ALIGN_UP (raw_size, GRUB_PE32_FILE_ALIGNMENT);
+ /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
++#if __GNUC__ >= 12
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wdangling-pointer"
++#endif
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size +
+ ALIGN_UP (total_module_size,
+ GRUB_PE32_FILE_ALIGNMENT));
+
++#if __GNUC__ >= 12
++#pragma GCC diagnostic pop
++#endif
+ section = init_pe_section (image_target, section, ".data",
+ &vma, scn_size, image_target->section_align,
+ &raw_data, raw_size,
+@@ -1448,8 +1462,15 @@
+ }
+
+ scn_size = ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
++#if __GNUC__ >= 12
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wdangling-pointer"
++#endif
+ PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
+ PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
++#if __GNUC__ >= 12
++#pragma GCC diagnostic pop
++#endif
+ memcpy (pe_img + raw_data, layout.reloc_section, scn_size);
+ init_pe_section (image_target, section, ".reloc",
+ &vma, scn_size, image_target->section_align,
diff --git a/debian/patches/gettext-quiet.patch b/debian/patches/gettext-quiet.patch
new file mode 100644
index 0000000..eddcce7
--- /dev/null
+++ b/debian/patches/gettext-quiet.patch
@@ -0,0 +1,30 @@
+From ddc3423d5c2bf1fb83a6f378726ff87b12794d19 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:02 +0000
+Subject: Silence error messages when translations are unavailable
+
+Bug: https://savannah.gnu.org/bugs/?35880
+Forwarded: https://savannah.gnu.org/bugs/?35880
+Last-Update: 2013-11-14
+
+Patch-Name: gettext-quiet.patch
+---
+ grub-core/gettext/gettext.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
+index 4d02e62c1..2a19389f2 100644
+--- a/grub-core/gettext/gettext.c
++++ b/grub-core/gettext/gettext.c
+@@ -427,6 +427,11 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx,
+ if (locale[0] == 'e' && locale[1] == 'n'
+ && (locale[2] == '\0' || locale[2] == '_'))
+ grub_errno = err = GRUB_ERR_NONE;
++
++ /* If no translations are available, fall back to untranslated text. */
++ if (err == GRUB_ERR_FILE_NOT_FOUND)
++ grub_errno = err = GRUB_ERR_NONE;
++
+ return err;
+ }
+
diff --git a/debian/patches/gfxpayload-dynamic.patch b/debian/patches/gfxpayload-dynamic.patch
new file mode 100644
index 0000000..b0a19b3
--- /dev/null
+++ b/debian/patches/gfxpayload-dynamic.patch
@@ -0,0 +1,290 @@
+From bc7f762a1d253537eb524946884b0f3e50a419f0 Mon Sep 17 00:00:00 2001
+From: Evan Broder <evan@ebroder.net>
+Date: Mon, 13 Jan 2014 12:13:29 +0000
+Subject: Add configure option to enable gfxpayload=keep dynamically
+
+Set GRUB_GFXPAYLOAD_LINUX=keep unless it's known to be unsupported on
+the current hardware. See
+https://blueprints.launchpad.net/ubuntu/+spec/packageselection-foundations-n-grub2-boot-framebuffer.
+
+Author: Colin Watson <cjwatson@ubuntu.com>
+Forwarded: no
+Last-Update: 2019-05-25
+
+Patch-Name: gfxpayload-dynamic.patch
+---
+ configure.ac | 11 ++
+ grub-core/Makefile.core.def | 8 ++
+ grub-core/commands/i386/pc/hwmatch.c | 146 +++++++++++++++++++++++++++
+ include/grub/file.h | 1 +
+ util/grub.d/10_linux.in | 37 ++++++-
+ 5 files changed, 200 insertions(+), 3 deletions(-)
+ create mode 100644 grub-core/commands/i386/pc/hwmatch.c
+
+diff --git a/configure.ac b/configure.ac
+index c42e4c784..947fd529f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1937,6 +1937,17 @@ else
+ fi
+ AC_SUBST([QUICK_BOOT])
+
++AC_ARG_ENABLE([gfxpayload-dynamic],
++ [AS_HELP_STRING([--enable-gfxpayload-dynamic],
++ [use GRUB_GFXPAYLOAD_LINUX=keep unless explicitly unsupported on current hardware (default=no)])],
++ [], [enable_gfxpayload_dynamic=no])
++if test x"$enable_gfxpayload_dynamic" = xyes ; then
++ GFXPAYLOAD_DYNAMIC=1
++else
++ GFXPAYLOAD_DYNAMIC=0
++fi
++AC_SUBST([GFXPAYLOAD_DYNAMIC])
++
+ LIBS=""
+
+ AC_SUBST([FONT_SOURCE])
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index e5b3d27f5..2ff266806 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -964,6 +964,14 @@ module = {
+ common = lib/hexdump.c;
+ };
+
++module = {
++ name = hwmatch;
++ i386_pc = commands/i386/pc/hwmatch.c;
++ enable = i386_pc;
++ cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
++ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
++};
++
+ module = {
+ name = keystatus;
+ common = commands/keystatus.c;
+diff --git a/grub-core/commands/i386/pc/hwmatch.c b/grub-core/commands/i386/pc/hwmatch.c
+new file mode 100644
+index 000000000..6de07cecc
+--- /dev/null
++++ b/grub-core/commands/i386/pc/hwmatch.c
+@@ -0,0 +1,146 @@
++/* hwmatch.c - Match hardware against a whitelist/blacklist. */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2011 Free Software Foundation, Inc.
++ *
++ * GRUB is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GRUB is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/dl.h>
++#include <grub/misc.h>
++#include <grub/command.h>
++#include <grub/pci.h>
++#include <grub/normal.h>
++#include <grub/file.h>
++#include <grub/env.h>
++#include <grub/i18n.h>
++#include <regex.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++/* Context for grub_cmd_hwmatch. */
++struct hwmatch_ctx
++{
++ grub_file_t matches_file;
++ int class_match;
++ int match;
++};
++
++/* Helper for grub_cmd_hwmatch. */
++static int
++hwmatch_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
++{
++ struct hwmatch_ctx *ctx = data;
++ grub_pci_address_t addr;
++ grub_uint32_t class, baseclass, vendor, device;
++ grub_pci_id_t subpciid;
++ grub_uint32_t subvendor, subdevice, subclass;
++ char *id, *line;
++
++ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
++ class = grub_pci_read (addr);
++ baseclass = class >> 24;
++
++ if (ctx->class_match != baseclass)
++ return 0;
++
++ vendor = pciid & 0xffff;
++ device = pciid >> 16;
++
++ addr = grub_pci_make_address (dev, GRUB_PCI_REG_SUBVENDOR);
++ subpciid = grub_pci_read (addr);
++
++ subclass = (class >> 16) & 0xff;
++ subvendor = subpciid & 0xffff;
++ subdevice = subpciid >> 16;
++
++ id = grub_xasprintf ("v%04xd%04xsv%04xsd%04xbc%02xsc%02x",
++ vendor, device, subvendor, subdevice,
++ baseclass, subclass);
++
++ grub_file_seek (ctx->matches_file, 0);
++ while ((line = grub_file_getline (ctx->matches_file)) != NULL)
++ {
++ char *anchored_line;
++ regex_t regex;
++ int ret;
++
++ if (! *line || *line == '#')
++ {
++ grub_free (line);
++ continue;
++ }
++
++ anchored_line = grub_xasprintf ("^%s$", line);
++ ret = regcomp (&regex, anchored_line, REG_EXTENDED | REG_NOSUB);
++ grub_free (anchored_line);
++ if (ret)
++ {
++ grub_free (line);
++ continue;
++ }
++
++ ret = regexec (&regex, id, 0, NULL, 0);
++ regfree (&regex);
++ grub_free (line);
++ if (! ret)
++ {
++ ctx->match = 1;
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++static grub_err_t
++grub_cmd_hwmatch (grub_command_t cmd __attribute__ ((unused)),
++ int argc, char **args)
++{
++ struct hwmatch_ctx ctx = { .match = 0 };
++ char *match_str;
++
++ if (argc < 2)
++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "list file and class required");
++
++ ctx.matches_file = grub_file_open (args[0], GRUB_FILE_TYPE_HWMATCH);
++ if (! ctx.matches_file)
++ return grub_errno;
++
++ ctx.class_match = grub_strtol (args[1], 0, 10);
++
++ grub_pci_iterate (hwmatch_iter, &ctx);
++
++ match_str = grub_xasprintf ("%d", ctx.match);
++ grub_env_set ("match", match_str);
++ grub_free (match_str);
++
++ grub_file_close (ctx.matches_file);
++
++ return GRUB_ERR_NONE;
++}
++
++static grub_command_t cmd;
++
++GRUB_MOD_INIT(hwmatch)
++{
++ cmd = grub_register_command ("hwmatch", grub_cmd_hwmatch,
++ N_("MATCHES-FILE CLASS"),
++ N_("Match PCI devices."));
++}
++
++GRUB_MOD_FINI(hwmatch)
++{
++ grub_unregister_command (cmd);
++}
+diff --git a/include/grub/file.h b/include/grub/file.h
+index 31567483c..e3c4cae2b 100644
+--- a/include/grub/file.h
++++ b/include/grub/file.h
+@@ -122,6 +122,7 @@ enum grub_file_type
+ GRUB_FILE_TYPE_FS_SEARCH,
+ GRUB_FILE_TYPE_AUDIO,
+ GRUB_FILE_TYPE_VBE_DUMP,
++ GRUB_FILE_TYPE_HWMATCH,
+
+ GRUB_FILE_TYPE_LOADENV,
+ GRUB_FILE_TYPE_SAVEENV,
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 80315a31b..d46d7852b 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -23,6 +23,7 @@ datarootdir="@datarootdir@"
+ ubuntu_recovery="@UBUNTU_RECOVERY@"
+ quiet_boot="@QUIET_BOOT@"
+ quick_boot="@QUICK_BOOT@"
++gfxpayload_dynamic="@GFXPAYLOAD_DYNAMIC@"
+
+ . "$pkgdatadir/grub-mkconfig_lib"
+
+@@ -145,9 +146,10 @@ linux_entry ()
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+ fi
+- if [ "$ubuntu_recovery" = 0 ] || [ x$type != xrecovery ]; then
+- echo " set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
+- fi
++ fi
++ if ([ "$ubuntu_recovery" = 0 ] || [ x$type != xrecovery ]) && \
++ ([ "x$GRUB_GFXPAYLOAD_LINUX" != x ] || [ "$gfxpayload_dynamic" = 1 ]); then
++ echo " set gfxpayload=\$linux_gfx_mode" | sed "s/^/$submenu_indentation/"
+ fi
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
+@@ -226,6 +228,35 @@ prepare_root_cache=
+ boot_device_id=
+ title_correction_code=
+
++# Use ELILO's generic "efifb" when it's known to be available.
++# FIXME: We need an interface to select vesafb in case efifb can't be used.
++if [ "x$GRUB_GFXPAYLOAD_LINUX" != x ] || [ "$gfxpayload_dynamic" = 0 ]; then
++ echo "set linux_gfx_mode=$GRUB_GFXPAYLOAD_LINUX"
++else
++ cat << EOF
++if [ "\${recordfail}" != 1 ]; then
++ if [ -e \${prefix}/gfxblacklist.txt ]; then
++ if hwmatch \${prefix}/gfxblacklist.txt 3; then
++ if [ \${match} = 0 ]; then
++ set linux_gfx_mode=keep
++ else
++ set linux_gfx_mode=text
++ fi
++ else
++ set linux_gfx_mode=text
++ fi
++ else
++ set linux_gfx_mode=keep
++ fi
++else
++ set linux_gfx_mode=text
++fi
++EOF
++fi
++cat << EOF
++export linux_gfx_mode
++EOF
++
+ # Extra indentation to add to menu entries in a submenu. We're not in a submenu
+ # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
+ submenu_indentation=""
diff --git a/debian/patches/gfxpayload-keep-default.patch b/debian/patches/gfxpayload-keep-default.patch
new file mode 100644
index 0000000..1308966
--- /dev/null
+++ b/debian/patches/gfxpayload-keep-default.patch
@@ -0,0 +1,39 @@
+From 70a2b23aadd93955a3869aa1c29a7f09c0696b95 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:12:57 +0000
+Subject: Disable gfxpayload=keep by default
+
+Setting gfxpayload=keep has been known to cause efifb to be
+inappropriately enabled. In any case, with the current Linux kernel the
+result of this option is that early kernelspace will be unable to print
+anything to the console, so (for example) if boot fails and you end up
+dumped to an initramfs prompt, you won't be able to see anything on the
+screen. As such it shouldn't be enabled by default in Debian, no matter
+what kernel options are enabled.
+
+gfxpayload=keep is a good idea but rather ahead of its time ...
+
+Bug-Debian: http://bugs.debian.org/567245
+Forwarded: no
+Last-Update: 2013-12-25
+
+Patch-Name: gfxpayload-keep-default.patch
+---
+ util/grub.d/10_linux.in | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index e8b01c0d0..9446d6833 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -114,10 +114,6 @@ linux_entry ()
+ # FIXME: We need an interface to select vesafb in case efifb can't be used.
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+- if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
+- && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
+- echo " set gfxpayload=keep" | sed "s/^/$submenu_indentation/"
+- fi
+ else
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
diff --git a/debian/patches/grub-install-extra-removable.patch b/debian/patches/grub-install-extra-removable.patch
new file mode 100644
index 0000000..1e7d2b4
--- /dev/null
+++ b/debian/patches/grub-install-extra-removable.patch
@@ -0,0 +1,202 @@
+From a0bfbdf9139bc127d28c4102b941ee504f7f0041 Mon Sep 17 00:00:00 2001
+From: Steve McIntyre <93sam@debian.org>
+Date: Wed, 3 Dec 2014 01:25:12 +0000
+Subject: Add support for forcing EFI installation to the removable media path
+
+Add an extra option to grub-install "--force-extra-removable". On EFI
+platforms, this will cause an extra copy of the grub-efi image to be
+written to the appropriate removable media patch
+/boot/efi/EFI/BOOT/BOOT$ARCH.EFI as well. This will help with broken
+UEFI implementations where the firmware does not work when configured
+with new boot paths.
+
+Signed-off-by: Steve McIntyre <93sam@debian.org>
+
+Bug-Debian: https://bugs.debian.org/767037 https://bugs.debian.org/773092
+Forwarded: Not yet
+Last-Update: 2021-09-24
+
+Patch-Name: grub-install-extra-removable.patch
+---
+ util/grub-install.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 108 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 2304cc5c4..b51fe4710 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -56,6 +56,7 @@
+
+ static char *target;
+ static int removable = 0;
++static int force_extra_removable = 0;
+ static int recheck = 0;
+ static int update_nvram = 1;
+ static char *install_device = NULL;
+@@ -113,7 +114,8 @@ enum
+ OPTION_LABEL_BGCOLOR,
+ OPTION_PRODUCT_VERSION,
+ OPTION_UEFI_SECURE_BOOT,
+- OPTION_NO_UEFI_SECURE_BOOT
++ OPTION_NO_UEFI_SECURE_BOOT,
++ OPTION_FORCE_EXTRA_REMOVABLE
+ };
+
+ static int fs_probe = 1;
+@@ -216,6 +218,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
+ removable = 1;
+ return 0;
+
++ case OPTION_FORCE_EXTRA_REMOVABLE:
++ force_extra_removable = 1;
++ return 0;
++
+ case OPTION_ALLOW_FLOPPY:
+ allow_floppy = 1;
+ return 0;
+@@ -322,6 +328,9 @@ static struct argp_option options[] = {
+ N_("do not install an image usable with UEFI Secure Boot, even if the "
+ "system was currently started using it. "
+ "This option is only available on EFI."), 2},
++ {"force-extra-removable", OPTION_FORCE_EXTRA_REMOVABLE, 0, 0,
++ N_("force installation to the removable media path also. "
++ "This option is only available on EFI."), 2},
+ {0, 0, 0, 0, 0, 0}
+ };
+
+@@ -847,6 +856,91 @@ fill_core_services (const char *core_services)
+ free (sysv_plist);
+ }
+
++/* Helper routine for also_install_removable() below. Walk through the
++ specified dir, looking to see if there is a file/dir that matches
++ the search string exactly, but in a case-insensitive manner. If so,
++ return a copy of the exact file/dir that *does* exist. If not,
++ return NULL */
++static char *
++check_component_exists(const char *dir,
++ const char *search)
++{
++ grub_util_fd_dir_t d;
++ grub_util_fd_dirent_t de;
++ char *found = NULL;
++
++ d = grub_util_fd_opendir (dir);
++ if (!d)
++ grub_util_error (_("cannot open directory `%s': %s"),
++ dir, grub_util_fd_strerror ());
++
++ while ((de = grub_util_fd_readdir (d)))
++ {
++ if (strcasecmp (de->d_name, search) == 0)
++ {
++ found = xstrdup (de->d_name);
++ break;
++ }
++ }
++ grub_util_fd_closedir (d);
++ return found;
++}
++
++/* Some complex directory-handling stuff in here, to cope with
++ * case-insensitive FAT/VFAT filesystem semantics. Ugh. */
++static void
++also_install_removable(const char *src,
++ const char *base_efidir,
++ const char *efi_suffix_upper)
++{
++ char *efi_file = NULL;
++ char *dst = NULL;
++ char *cur = NULL;
++ char *found = NULL;
++
++ if (!efi_suffix_upper)
++ grub_util_error ("%s", _("efi_suffix_upper not set"));
++ efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
++
++ /* We need to install in $base_efidir/EFI/BOOT/$efi_file, but we
++ * need to cope with case-insensitive stuff here. Build the path one
++ * component at a time, checking for existing matches each time. */
++
++ /* Look for "EFI" in base_efidir. Make it if it does not exist in
++ * some form. */
++ found = check_component_exists(base_efidir, "EFI");
++ if (found == NULL)
++ found = xstrdup("EFI");
++ dst = grub_util_path_concat (2, base_efidir, found);
++ cur = xstrdup (dst);
++ free (dst);
++ free (found);
++ grub_install_mkdir_p (cur);
++
++ /* Now BOOT */
++ found = check_component_exists(cur, "BOOT");
++ if (found == NULL)
++ found = xstrdup("BOOT");
++ dst = grub_util_path_concat (2, cur, found);
++ cur = xstrdup (dst);
++ free (dst);
++ free (found);
++ grub_install_mkdir_p (cur);
++
++ /* Now $efi_file */
++ found = check_component_exists(cur, efi_file);
++ if (found == NULL)
++ found = xstrdup(efi_file);
++ dst = grub_util_path_concat (2, cur, found);
++ cur = xstrdup (dst);
++ free (dst);
++ free (found);
++ grub_install_copy_file (src, cur, 1);
++
++ free (cur);
++ free (efi_file);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -864,6 +958,7 @@ main (int argc, char *argv[])
+ char *relative_grubdir;
+ char **efidir_device_names = NULL;
+ grub_device_t efidir_grub_dev = NULL;
++ char *base_efidir = NULL;
+ char *efidir_grub_devname;
+ int efidir_is_mac = 0;
+ int is_prep = 0;
+@@ -896,6 +991,9 @@ main (int argc, char *argv[])
+ bootloader_id = xstrdup ("grub");
+ }
+
++ if (removable && force_extra_removable)
++ grub_util_error (_("Invalid to use both --removable and --force_extra_removable"));
++
+ if (!grub_install_source_directory)
+ {
+ if (!target)
+@@ -1115,6 +1213,8 @@ main (int argc, char *argv[])
+ if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0)
+ grub_util_error (_("%s doesn't look like an EFI partition"), efidir);
+
++ base_efidir = xstrdup(efidir);
++
+ /* The EFI specification requires that an EFI System Partition must
+ contain an "EFI" subdirectory, and that OS loaders are stored in
+ subdirectories below EFI. Vendors are expected to pick names that do
+@@ -2048,9 +2148,15 @@ main (int argc, char *argv[])
+ fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
+ fclose (config_dst_f);
+ free (config_dst);
++ if (force_extra_removable)
++ also_install_removable(efi_signed, base_efidir, efi_suffix_upper);
+ }
+ else
+- grub_install_copy_file (imgfile, dst, 1);
++ {
++ grub_install_copy_file (imgfile, dst, 1);
++ if (force_extra_removable)
++ also_install_removable(imgfile, base_efidir, efi_suffix_upper);
++ }
+
+ grub_set_install_backup_ponr ();
+
diff --git a/debian/patches/grub-install-pvxen-paths.patch b/debian/patches/grub-install-pvxen-paths.patch
new file mode 100644
index 0000000..88987a2
--- /dev/null
+++ b/debian/patches/grub-install-pvxen-paths.patch
@@ -0,0 +1,71 @@
+From 4e93755cd1c371ba856b375f453664fd07a67205 Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc@hellion.org.uk>
+Date: Sat, 6 Sep 2014 12:20:12 +0100
+Subject: grub-install: Install PV Xen binaries into the upstream specified
+ path
+
+Upstream have defined a specification for where guests ought to place their
+xenpv grub binaries in order to facilitate chainloading from a stage 1 grub
+loaded from dom0.
+
+http://xenbits.xen.org/docs/unstable-staging/misc/x86-xenpv-bootloader.html
+
+The spec calls for installation into /boot/xen/pvboot-i386.elf or
+/boot/xen/pvboot-x86_64.elf.
+
+Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
+
+Bug-Debian: https://bugs.debian.org/762307
+Forwarded: http://lists.gnu.org/archive/html/grub-devel/2014-10/msg00041.html
+Last-Update: 2014-10-24
+
+Patch-Name: grub-install-pvxen-paths.patch
+
+---
+v2: Respect bootdir, create /boot/xen as needed.
+---
+ util/grub-install.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index d02bd488a..2304cc5c4 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -2085,6 +2085,28 @@ main (int argc, char *argv[])
+ }
+ break;
+
++ case GRUB_INSTALL_PLATFORM_I386_XEN:
++ {
++ char *path = grub_util_path_concat (2, bootdir, "xen");
++ char *dst = grub_util_path_concat (2, path, "pvboot-i386.elf");
++ grub_install_mkdir_p (path);
++ grub_install_copy_file (imgfile, dst, 1);
++ free (dst);
++ free (path);
++ }
++ break;
++
++ case GRUB_INSTALL_PLATFORM_X86_64_XEN:
++ {
++ char *path = grub_util_path_concat (2, bootdir, "xen");
++ char *dst = grub_util_path_concat (2, path, "pvboot-x86_64.elf");
++ grub_install_mkdir_p (path);
++ grub_install_copy_file (imgfile, dst, 1);
++ free (dst);
++ free (path);
++ }
++ break;
++
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+@@ -2094,8 +2116,6 @@ main (int argc, char *argv[])
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+- case GRUB_INSTALL_PLATFORM_I386_XEN:
+- case GRUB_INSTALL_PLATFORM_X86_64_XEN:
+ case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
+ grub_util_warn ("%s",
+ _("WARNING: no platform-specific install was performed"));
diff --git a/debian/patches/grub-install-removable-shim.patch b/debian/patches/grub-install-removable-shim.patch
new file mode 100644
index 0000000..21b87c4
--- /dev/null
+++ b/debian/patches/grub-install-removable-shim.patch
@@ -0,0 +1,196 @@
+From c8351a8a7a7664dfac4de63fb6df185b2a52a346 Mon Sep 17 00:00:00 2001
+From: Steve McIntyre <93sam@debian.org>
+Date: Fri, 14 Jun 2019 16:37:11 +0100
+Subject: Deal with --force-extra-removable with signed shim too
+
+In this case, we need both the signed shim as /EFI/BOOT/BOOTXXX.EFI
+and signed Grub as /EFI/BOOT/grubXXX.efi.
+
+Also install the BOOTXXX.CSV into /EFI/debian, and FBXXX.EFI into
+/EFI/BOOT/ so that it can work when needed (*iff* we're updating the
+NVRAM).
+
+[cjwatson: Refactored also_install_removable somewhat for brevity and so
+that we're using consistent case-insensitive logic.]
+
+Bug-Debian: https://bugs.debian.org/930531
+Last-Update: 2021-09-24
+
+Patch-Name: grub-install-removable-shim.patch
+---
+ util/grub-install.c | 83 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 66 insertions(+), 17 deletions(-)
+
+Index: grub.git/util/grub-install.c
+===================================================================
+--- grub.git.orig/util/grub-install.c
++++ grub.git/util/grub-install.c
+@@ -891,17 +891,13 @@ check_component_exists(const char *dir,
+ static void
+ also_install_removable(const char *src,
+ const char *base_efidir,
+- const char *efi_suffix_upper)
++ const char *efi_file,
++ int is_needed)
+ {
+- char *efi_file = NULL;
+ char *dst = NULL;
+ char *cur = NULL;
+ char *found = NULL;
+
+- if (!efi_suffix_upper)
+- grub_util_error ("%s", _("efi_suffix_upper not set"));
+- efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
+-
+ /* We need to install in $base_efidir/EFI/BOOT/$efi_file, but we
+ * need to cope with case-insensitive stuff here. Build the path one
+ * component at a time, checking for existing matches each time. */
+@@ -935,10 +931,9 @@ also_install_removable(const char *src,
+ cur = xstrdup (dst);
+ free (dst);
+ free (found);
+- grub_install_copy_file (src, cur, 1);
++ grub_install_copy_file (src, cur, is_needed);
+
+ free (cur);
+- free (efi_file);
+ }
+
+ int
+@@ -2103,11 +2098,14 @@ main (int argc, char *argv[])
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ {
+ char *dst = grub_util_path_concat (2, efidir, efi_file);
++ char *removable_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
++
+ if (uefi_secure_boot)
+ {
+ char *shim_signed = NULL;
+ char *mok_signed = NULL, *mok_file = NULL;
+ char *fb_signed = NULL, *fb_file = NULL;
++ char *csv_file = NULL;
+ char *config_dst;
+ FILE *config_dst_f;
+
+@@ -2116,11 +2114,15 @@ main (int argc, char *argv[])
+ mok_file = xasprintf ("mm%s.efi", efi_suffix);
+ fb_signed = xasprintf ("fb%s.efi.signed", efi_suffix);
+ fb_file = xasprintf ("fb%s.efi", efi_suffix);
++ csv_file = xasprintf ("BOOT%s.CSV", efi_suffix_upper);
++
++ /* If we have a signed shim binary, install that and all
++ its helpers in the normal vendor path */
+
+ if (grub_util_is_regular (shim_signed))
+ {
+ char *chained_base, *chained_dst;
+- char *mok_src, *mok_dst, *fb_src, *fb_dst;
++ char *mok_src, *mok_dst, *fb_src, *fb_dst, *csv_src, *csv_dst;
+ if (!removable)
+ {
+ free (efi_file);
+@@ -2132,8 +2134,6 @@ main (int argc, char *argv[])
+ chained_base = xasprintf ("grub%s.efi", efi_suffix);
+ chained_dst = grub_util_path_concat (2, efidir, chained_base);
+ grub_install_copy_file (efi_signed, chained_dst, 1);
+- free (chained_dst);
+- free (chained_base);
+
+ /* Not critical, so not an error if they are not present (as it
+ won't be for older releases); but if we have them, make
+@@ -2144,8 +2144,6 @@ main (int argc, char *argv[])
+ mok_file);
+ grub_install_copy_file (mok_src,
+ mok_dst, 0);
+- free (mok_src);
+- free (mok_dst);
+
+ fb_src = grub_util_path_concat (2, "/usr/lib/shim/",
+ fb_signed);
+@@ -2154,30 +2152,82 @@ main (int argc, char *argv[])
+ if (!removable)
+ grub_install_copy_file (fb_src,
+ fb_dst, 0);
++
++ csv_src = grub_util_path_concat (2, "/usr/lib/shim/",
++ csv_file);
++ csv_dst = grub_util_path_concat (2, efidir,
++ csv_file);
++ grub_install_copy_file (csv_src,
++ csv_dst, 0);
++
++ /* Install binaries into .../EFI/BOOT too:
++ the shim binary
++ the grub binary
++ the shim fallback binary (not fatal on failure) */
++ if (force_extra_removable)
++ {
++ grub_util_info ("Secure boot: installing shim and image into rm path");
++ also_install_removable (shim_signed, base_efidir, removable_file, 1);
++
++ also_install_removable (efi_signed, base_efidir, chained_base, 1);
++ also_install_removable (mok_src, base_efidir, mok_file, 0);
++
++ /* If we're updating the NVRAM, add fallback too - it
++ will re-update the NVRAM later if things break */
++ if (update_nvram)
++ also_install_removable (fb_src, base_efidir, fb_file, 0);
++ }
++
++ free (chained_dst);
++ free (chained_base);
++ free (mok_src);
++ free (mok_dst);
+ free (fb_src);
+ free (fb_dst);
++ free (csv_src);
++ free (csv_dst);
+ }
+ else
+- grub_install_copy_file (efi_signed, dst, 1);
++ {
++ /* Tried to install for secure boot, but no signed
++ shim found. Fall back to just installing the signed
++ grub binary */
++ grub_util_info ("Secure boot (no shim): installing signed grub binary");
++ grub_install_copy_file (efi_signed, dst, 1);
++ if (force_extra_removable)
++ {
++ grub_util_info ("Secure boot (no shim): installing signed grub binary into rm path");
++ also_install_removable (efi_signed, base_efidir, removable_file, 1);
++ }
++ }
+
++ /* In either case, install our grub.cfg */
+ config_dst = grub_util_path_concat (2, efidir, "grub.cfg");
+ grub_install_copy_file (load_cfg, config_dst, 1);
+ config_dst_f = grub_util_fopen (config_dst, "ab");
+ fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
+ fclose (config_dst_f);
+ free (config_dst);
+- if (force_extra_removable)
+- also_install_removable(efi_signed, base_efidir, efi_suffix_upper);
++
++ free (csv_file);
++ free (fb_file);
++ free (fb_signed);
++ free (mok_file);
++ free (mok_signed);
++ free (shim_signed);
+ }
+ else
+ {
++ /* No secure boot - just install our newly-generated image */
++ grub_util_info ("No Secure Boot: installing core image");
+ grub_install_copy_file (imgfile, dst, 1);
+ if (force_extra_removable)
+- also_install_removable(imgfile, base_efidir, efi_suffix_upper);
++ also_install_removable (imgfile, base_efidir, removable_file, 1);
+ }
+
+ grub_set_install_backup_ponr ();
+
++ free (removable_file);
+ free (dst);
+ }
+ if (!removable && update_nvram)
diff --git a/debian/patches/grub-legacy-0-based-partitions.patch b/debian/patches/grub-legacy-0-based-partitions.patch
new file mode 100644
index 0000000..31dc3c1
--- /dev/null
+++ b/debian/patches/grub-legacy-0-based-partitions.patch
@@ -0,0 +1,39 @@
+From ae648ba6160a334707f8a8fc0768ec1bc60c4442 Mon Sep 17 00:00:00 2001
+From: Robert Millan <rmh@aybabtu.com>
+Date: Mon, 13 Jan 2014 12:12:53 +0000
+Subject: Support running grub-probe in grub-legacy's update-grub
+
+Author: Colin Watson <cjwatson@debian.org>
+Forwarded: not-needed
+Last-Update: 2013-12-25
+
+Patch-Name: grub-legacy-0-based-partitions.patch
+---
+ util/getroot.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/util/getroot.c b/util/getroot.c
+index a5eaa64fd..6ae35ecaa 100644
+--- a/util/getroot.c
++++ b/util/getroot.c
+@@ -245,6 +245,20 @@ find_partition (grub_disk_t dsk __attribute__ ((unused)),
+
+ if (ctx->start == part_start)
+ {
++ /* This is dreadfully hardcoded, but there's a limit to what GRUB
++ Legacy was able to deal with anyway. */
++ if (getenv ("GRUB_LEGACY_0_BASED_PARTITIONS"))
++ {
++ if (partition->parent)
++ /* Probably a BSD slice. */
++ ctx->partname = xasprintf ("%d,%d", partition->parent->number,
++ partition->number + 1);
++ else
++ ctx->partname = xasprintf ("%d", partition->number);
++
++ return 1;
++ }
++
+ ctx->partname = grub_partition_get_name (partition);
+ return 1;
+ }
diff --git a/debian/patches/grub.cfg-400.patch b/debian/patches/grub.cfg-400.patch
new file mode 100644
index 0000000..2f1c304
--- /dev/null
+++ b/debian/patches/grub.cfg-400.patch
@@ -0,0 +1,25 @@
+From 2f1be2e80ba5dd1278401f21cfe07526312838e9 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:12:55 +0000
+Subject: Make grub.cfg world-readable if it contains no passwords
+
+Patch-Name: grub.cfg-400.patch
+---
+ util/grub-mkconfig.in | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index f8cbb8d7a..0fd618e35 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -289,6 +289,10 @@ for i in "${grub_mkconfig_dir}"/* ; do
+ esac
+ done
+
++if [ "x${grub_cfg}" != "x" ] && ! grep "^password" ${grub_cfg}.new >/dev/null; then
++ chmod 444 ${grub_cfg}.new || true
++fi
++
+ if test "x${grub_cfg}" != "x" ; then
+ if ! ${grub_script_check} ${grub_cfg}.new; then
+ # TRANSLATORS: %s is replaced by filename
diff --git a/debian/patches/grub_mkconfig_restore_umask.patch b/debian/patches/grub_mkconfig_restore_umask.patch
new file mode 100644
index 0000000..bd85cfc
--- /dev/null
+++ b/debian/patches/grub_mkconfig_restore_umask.patch
@@ -0,0 +1,36 @@
+commit 0adec29674561034771c13e446069b41ef41e4d4
+Author: Michael Chang <mchang@suse.com>
+Date: Fri Dec 3 16:13:28 2021 +0800
+
+ grub-mkconfig: Restore umask for the grub.cfg
+
+ The commit ab2e53c8a (grub-mkconfig: Honor a symlink when generating
+ configuration by grub-mkconfig) has inadvertently discarded umask for
+ creating grub.cfg in the process of running grub-mkconfig. The resulting
+ wrong permission (0644) would allow unprivileged users to read GRUB
+ configuration file content. This presents a low confidentiality risk
+ as grub.cfg may contain non-secured plain-text passwords.
+
+ This patch restores the missing umask and sets the creation file mode
+ to 0600 preventing unprivileged access.
+
+ Fixes: CVE-2021-3981
+
+ Signed-off-by: Michael Chang <mchang@suse.com>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index c3ea7612e..62335d027 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -301,7 +301,10 @@ and /etc/grub.d/* files or please file a bug report with
+ exit 1
+ else
+ # none of the children aborted with error, install the new grub.cfg
++ oldumask=$(umask)
++ umask 077
+ cat ${grub_cfg}.new > ${grub_cfg}
++ umask $oldumask
+ rm -f ${grub_cfg}.new
+ fi
+ fi
diff --git a/debian/patches/grub_os-prober.patch b/debian/patches/grub_os-prober.patch
new file mode 100644
index 0000000..e226eab
--- /dev/null
+++ b/debian/patches/grub_os-prober.patch
@@ -0,0 +1,22 @@
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 225a3baf7..ea3f3f804 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -40,13 +40,13 @@ EOF
+ fi
+ }
+
+-if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
+- grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.")"
++if ! command -v os-prober > /dev/null || ! command -v linux-boot-prober > /dev/null ; then
++ # missing os-prober and/or linux-boot-prober
+ exit 0
+ fi
+
+-if ! command -v os-prober > /dev/null || ! command -v linux-boot-prober > /dev/null ; then
+- # missing os-prober and/or linux-boot-prober
++if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
++ grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.")"
+ exit 0
+ fi
+
diff --git a/debian/patches/ieee1275-clear-reset.patch b/debian/patches/ieee1275-clear-reset.patch
new file mode 100644
index 0000000..c528944
--- /dev/null
+++ b/debian/patches/ieee1275-clear-reset.patch
@@ -0,0 +1,32 @@
+From 791c1034910b5e87ec7ff4166300f0f26b647625 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
+Date: Thu, 25 Sep 2014 18:41:29 -0300
+Subject: Include a text attribute reset in the clear command for ppc
+
+Always clear text attribute for clear command in order to avoid problems
+after it boots.
+
+* grub-core/term/terminfo.c: Add escape for text attribute reset
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1295255
+Origin: other, https://lists.gnu.org/archive/html/grub-devel/2014-09/msg00076.html
+Last-Update: 2014-09-26
+
+Patch-Name: ieee1275-clear-reset.patch
+---
+ grub-core/term/terminfo.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
+index 85ecf06b4..e5ec77107 100644
+--- a/grub-core/term/terminfo.c
++++ b/grub-core/term/terminfo.c
+@@ -151,7 +151,7 @@ grub_terminfo_set_current (struct grub_term_output *term,
+ /* Clear the screen. Using serial console, screen(1) only recognizes the
+ * ANSI escape sequence. Using video console, Apple Open Firmware
+ * (version 3.1.1) only recognizes the literal ^L. So use both. */
+- data->cls = grub_strdup (" \e[2J");
++ data->cls = grub_strdup (" \e[2J\e[m");
+ data->reverse_video_on = grub_strdup ("\e[7m");
+ data->reverse_video_off = grub_strdup ("\e[m");
+ if (grub_strcmp ("ieee1275", str) == 0)
diff --git a/debian/patches/ignore-grub_func_test-failures.patch b/debian/patches/ignore-grub_func_test-failures.patch
new file mode 100644
index 0000000..6275b26
--- /dev/null
+++ b/debian/patches/ignore-grub_func_test-failures.patch
@@ -0,0 +1,29 @@
+From f8d8c2e9dfd49bd0e59e27c09fc535a547d13c01 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:13:32 +0000
+Subject: Ignore functional test failures for now as they are broken
+
+See: https://lists.gnu.org/archive/html/grub-devel/2013-11/msg00242.html
+
+Forwarded: not-needed
+Last-Update: 2013-11-19
+
+Patch-Name: ignore-grub_func_test-failures.patch
+---
+ tests/grub_func_test.in | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tests/grub_func_test.in b/tests/grub_func_test.in
+index c67f9e422..728cd6e06 100644
+--- a/tests/grub_func_test.in
++++ b/tests/grub_func_test.in
+@@ -16,6 +16,8 @@ out=`echo all_functional_test | @builddir@/grub-shell --timeout=3600 --files="/b
+
+ if [ "$(echo "$out" | tail -n 1)" != "ALL TESTS PASSED" ]; then
+ echo "Functional test failure: $out"
+- exit 1
++ # Disabled temporarily due to unrecognised video checksum failures.
++ #exit 1
++ exit 0
+ fi
+
diff --git a/debian/patches/ignore_checksum_seed_incompat_feature.patch b/debian/patches/ignore_checksum_seed_incompat_feature.patch
new file mode 100644
index 0000000..cd9b897
--- /dev/null
+++ b/debian/patches/ignore_checksum_seed_incompat_feature.patch
@@ -0,0 +1,54 @@
+commit 7fd5feff97c4b1f446f8fcf6d37aca0c64e7c763
+Author: Javier Martinez Canillas <javierm@redhat.com>
+Date: Fri Jun 11 21:36:16 2021 +0200
+
+ fs/ext2: Ignore checksum seed incompat feature
+
+ This incompat feature is used to denote that the filesystem stored its
+ metadata checksum seed in the superblock. This is used to allow tune2fs
+ changing the UUID on a mounted metdata_csum filesystem without having
+ to rewrite all the disk metadata. However, the GRUB doesn't use the
+ metadata checksum at all. So, it can just ignore this feature if it
+ is enabled. This is consistent with the GRUB filesystem code in general
+ which just does a best effort to access the filesystem's data.
+
+ The checksum seed incompat feature has to be removed from the ignore
+ list if the support for metadata checksum verification is added to the
+ GRUB ext2 driver later.
+
+ Suggested-by: Eric Sandeen <esandeen@redhat.com>
+ Suggested-by: Lukas Czerner <lczerner@redhat.com>
+ Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+ Reviewed-by: Lukas Czerner <lczerner@redhat.com>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
+index e7dd78e66..4953a1591 100644
+--- a/grub-core/fs/ext2.c
++++ b/grub-core/fs/ext2.c
+@@ -103,6 +103,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
+ #define EXT4_FEATURE_INCOMPAT_MMP 0x0100
+ #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
++#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000
+ #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000
+
+ /* The set of back-incompatible features this driver DOES support. Add (OR)
+@@ -123,10 +124,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ * mmp: Not really back-incompatible - was added as such to
+ * avoid multiple read-write mounts. Safe to ignore for this
+ * RO driver.
++ * checksum seed: Not really back-incompatible - was added to allow tools
++ * such as tune2fs to change the UUID on a mounted metadata
++ * checksummed filesystem. Safe to ignore for now since the
++ * driver doesn't support checksum verification. However, it
++ * has to be removed from this list if the support is added later.
+ */
+ #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \
+- | EXT4_FEATURE_INCOMPAT_MMP)
+-
++ | EXT4_FEATURE_INCOMPAT_MMP \
++ | EXT4_FEATURE_INCOMPAT_CSUM_SEED)
+
+ #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
+
diff --git a/debian/patches/ignore_the_large_dir_incompat_feature.patch b/debian/patches/ignore_the_large_dir_incompat_feature.patch
new file mode 100644
index 0000000..ea6ec5f
--- /dev/null
+++ b/debian/patches/ignore_the_large_dir_incompat_feature.patch
@@ -0,0 +1,53 @@
+commit 2e9fa73a040462b81bfbfe56c0bc7ad2d30b446b
+Author: Theodore Ts'o <tytso@mit.edu>
+Date: Tue Aug 30 22:41:59 2022 -0400
+
+ fs/ext2: Ignore the large_dir incompat feature
+
+ Recently, ext4 added the large_dir feature, which adds support for
+ a 3 level htree directory support.
+
+ The GRUB supports existing file systems with htree directories by
+ ignoring their existence, and since the index nodes for the hash tree
+ look like deleted directory entries (by design), the GRUB can simply do
+ a brute force O(n) linear search of directories. The same is true for
+ 3 level deep htrees indicated by large_dir feature flag.
+
+ Hence, it is safe for the GRUB to ignore the large_dir incompat feature.
+
+ Fixes: https://savannah.gnu.org/bugs/?61606
+
+ Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
+index 0989e26e1..e1cc5e62a 100644
+--- a/grub-core/fs/ext2.c
++++ b/grub-core/fs/ext2.c
+@@ -104,6 +104,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ #define EXT4_FEATURE_INCOMPAT_MMP 0x0100
+ #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
+ #define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000
++#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3 level htree */
+ #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000
+
+ /* The set of back-incompatible features this driver DOES support. Add (OR)
+@@ -129,10 +130,17 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ * checksummed filesystem. Safe to ignore for now since the
+ * driver doesn't support checksum verification. However, it
+ * has to be removed from this list if the support is added later.
++ * large_dir: Not back-incompatible given that the GRUB ext2 driver does
++ * not implement EXT2_FEATURE_COMPAT_DIR_INDEX. If the GRUB
++ * eventually supports the htree feature (aka dir_index)
++ * it should support 3 level htrees and then move
++ * EXT4_FEATURE_INCOMPAT_LARGEDIR to
++ * EXT2_DRIVER_SUPPORTED_INCOMPAT.
+ */
+ #define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \
+ | EXT4_FEATURE_INCOMPAT_MMP \
+- | EXT4_FEATURE_INCOMPAT_CSUM_SEED)
++ | EXT4_FEATURE_INCOMPAT_CSUM_SEED \
++ | EXT4_FEATURE_INCOMPAT_LARGEDIR)
+
+ #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
+
diff --git a/debian/patches/insmod-xzio-and-lzopio-on-xen.patch b/debian/patches/insmod-xzio-and-lzopio-on-xen.patch
new file mode 100644
index 0000000..fb48118
--- /dev/null
+++ b/debian/patches/insmod-xzio-and-lzopio-on-xen.patch
@@ -0,0 +1,33 @@
+From bc8ec86089a4f6eb2ea19499a2b335dccdebd577 Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc@debian.org>
+Date: Sun, 30 Nov 2014 12:12:52 +0000
+Subject: Arrange to insmod xzio and lzopio when booting a kernel as a Xen
+ guest
+
+This is needed in case the Linux kernel is compiled with CONFIG_KERNEL_XZ or
+CONFIG_KERNEL_LZO rather than CONFIG_KERNEL_GZ (gzio is already loaded by
+grub.cfg today).
+
+Signed-off-by: Ian Campbell <ijc@debian.org>
+
+Bug-Debian: https://bugs.debian.org/755256
+Forwarded: http://lists.gnu.org/archive/html/grub-devel/2014-11/msg00091.html
+Last-Update: 2014-11-30
+
+Patch-Name: insmod-xzio-and-lzopio-on-xen.patch
+---
+ util/grub.d/10_linux.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index f88a2de10..635c609d6 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -162,6 +162,7 @@ linux_entry ()
+ fi
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
++ echo " if [ x\$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi" | sed "s/^/$submenu_indentation/"
+
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
diff --git a/debian/patches/install-efi-adjust-distributor.patch b/debian/patches/install-efi-adjust-distributor.patch
new file mode 100644
index 0000000..f802618
--- /dev/null
+++ b/debian/patches/install-efi-adjust-distributor.patch
@@ -0,0 +1,34 @@
+From 11ea79546da850296fabeb94bfc8c110a98fe7f6 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:27 +0000
+Subject: Adjust efi_distributor for some distributions
+
+This is not a very good approach, and certainly not sanely upstreamable;
+we probably need to split GRUB_DISTRIBUTOR into a couple of different
+variables.
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1242417
+Bug-Debian: https://bugs.debian.org/932966
+Forwarded: not-needed
+Last-Update: 2019-08-06
+
+Patch-Name: install-efi-adjust-distributor.patch
+---
+ util/grub-install.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index f49c78d0b..48c8c0364 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -1123,6 +1123,10 @@ main (int argc, char *argv[])
+ */
+ char *t;
+ efi_distributor = bootloader_id;
++ if (strcmp (efi_distributor, "kubuntu") == 0)
++ efi_distributor = "ubuntu";
++ else if (strcmp (efi_distributor, "devuan") == 0)
++ efi_distributor = "debian";
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
diff --git a/debian/patches/install-efi-fallback.patch b/debian/patches/install-efi-fallback.patch
new file mode 100644
index 0000000..6501d8a
--- /dev/null
+++ b/debian/patches/install-efi-fallback.patch
@@ -0,0 +1,91 @@
+From 7cf3ac7be59ef377a98ead5c7d3d5cb537c159c4 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:05 +0000
+Subject: Fall back to non-EFI if booted using EFI but -efi is missing
+
+It may be possible, particularly in recovery situations, to be booted
+using EFI on x86 when only the i386-pc target is installed, or on ARM
+when only the arm-uboot target is installed. There's nothing actually
+stopping us installing i386-pc or arm-uboot from an EFI environment, and
+it's better than returning a confusing error.
+
+Author: Steve McIntyre <93sam@debian.org>
+Forwarded: no
+Last-Update: 2019-05-24
+
+Patch-Name: install-efi-fallback.patch
+---
+ grub-core/osdep/linux/platform.c | 40 ++++++++++++++++++++++++++++----
+ 1 file changed, 35 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c
+index e28a79dab..2e7f72086 100644
+--- a/grub-core/osdep/linux/platform.c
++++ b/grub-core/osdep/linux/platform.c
+@@ -19,10 +19,12 @@
+ #include <config.h>
+
+ #include <grub/util/install.h>
++#include <grub/emu/config.h>
+ #include <grub/emu/exec.h>
+ #include <grub/emu/misc.h>
+ #include <sys/types.h>
+ #include <dirent.h>
++#include <stdlib.h>
+ #include <string.h>
+
+ #include <sys/utsname.h>
+@@ -128,9 +130,24 @@ const char *
+ grub_install_get_default_arm_platform (void)
+ {
+ if (is_efi_system())
+- return "arm-efi";
+- else
+- return "arm-uboot";
++ {
++ const char *pkglibdir = grub_util_get_pkglibdir ();
++ const char *platform;
++ char *pd;
++ int found;
++
++ platform = "arm-efi";
++
++ pd = grub_util_path_concat (2, pkglibdir, platform);
++ found = grub_util_is_directory (pd);
++ free (pd);
++ if (found)
++ return platform;
++ else
++ grub_util_info ("... but %s platform not available", platform);
++ }
++
++ return "arm-uboot";
+ }
+
+ const char *
+@@ -138,10 +155,23 @@ grub_install_get_default_x86_platform (void)
+ {
+ if (is_efi_system())
+ {
++ const char *pkglibdir = grub_util_get_pkglibdir ();
++ const char *platform;
++ char *pd;
++ int found;
++
+ if (read_platform_size() == 64)
+- return "x86_64-efi";
++ platform = "x86_64-efi";
++ else
++ platform = "i386-efi";
++
++ pd = grub_util_path_concat (2, pkglibdir, platform);
++ found = grub_util_is_directory (pd);
++ free (pd);
++ if (found)
++ return platform;
+ else
+- return "i386-efi";
++ grub_util_info ("... but %s platform not available", platform);
+ }
+
+ grub_util_info ("Looking for /proc/device-tree ..");
diff --git a/debian/patches/install-locale-langpack.patch b/debian/patches/install-locale-langpack.patch
new file mode 100644
index 0000000..ae96bab
--- /dev/null
+++ b/debian/patches/install-locale-langpack.patch
@@ -0,0 +1,116 @@
+From 31e9c5eaec14e18251db1fb7e6e44add22e56526 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:07 +0000
+Subject: Prefer translations from Ubuntu language packs if available
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998
+Forwarded: not-needed
+Last-Update: 2013-12-25
+
+Patch-Name: install-locale-langpack.patch
+---
+ util/grub-install-common.c | 37 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 30 insertions(+), 7 deletions(-)
+
+diff --git a/util/grub-install-common.c b/util/grub-install-common.c
+index 4e212e690..e53730485 100644
+--- a/util/grub-install-common.c
++++ b/util/grub-install-common.c
+@@ -774,17 +774,25 @@ get_localedir (void)
+ }
+
+ static void
+-copy_locales (const char *dstd)
++copy_locales (const char *dstd, int langpack)
+ {
+ grub_util_fd_dir_t d;
+ grub_util_fd_dirent_t de;
+ const char *locale_dir = get_localedir ();
++ char *dir;
+
+- d = grub_util_fd_opendir (locale_dir);
++ if (langpack)
++ dir = xasprintf ("%s-langpack", locale_dir);
++ else
++ dir = xstrdup (locale_dir);
++
++ d = grub_util_fd_opendir (dir);
+ if (!d)
+ {
+- grub_util_warn (_("cannot open directory `%s': %s"),
+- locale_dir, grub_util_fd_strerror ());
++ if (!langpack)
++ grub_util_warn (_("cannot open directory `%s': %s"),
++ dir, grub_util_fd_strerror ());
++ free (dir);
+ return;
+ }
+
+@@ -801,14 +809,14 @@ copy_locales (const char *dstd)
+ if (ext && (grub_strcmp (ext, ".mo") == 0
+ || grub_strcmp (ext, ".gmo") == 0))
+ {
+- srcf = grub_util_path_concat (2, locale_dir, de->d_name);
++ srcf = grub_util_path_concat (2, dir, de->d_name);
+ dstf = grub_util_path_concat (2, dstd, de->d_name);
+ ext = grub_strrchr (dstf, '.');
+ grub_strcpy (ext, ".mo");
+ }
+ else
+ {
+- srcf = grub_util_path_concat_ext (4, locale_dir, de->d_name,
++ srcf = grub_util_path_concat_ext (4, dir, de->d_name,
+ "LC_MESSAGES", PACKAGE, ".mo");
+ dstf = grub_util_path_concat_ext (2, dstd, de->d_name, ".mo");
+ }
+@@ -817,6 +825,7 @@ copy_locales (const char *dstd)
+ free (dstf);
+ }
+ grub_util_fd_closedir (d);
++ free (dir);
+ }
+ #endif
+
+@@ -835,13 +844,15 @@ grub_install_copy_nls(const char *src __attribute__ ((unused)),
+ {
+ char *srcd = grub_util_path_concat (2, src, "po");
+ copy_by_ext (srcd, dst_locale, ".mo", 0);
+- copy_locales (dst_locale);
++ copy_locales (dst_locale, 0);
++ copy_locales (dst_locale, 1);
+ free (srcd);
+ }
+ else
+ {
+ size_t i;
+ const char *locale_dir = get_localedir ();
++ char *locale_langpack_dir = xasprintf ("%s-langpack", locale_dir);
+
+ for (i = 0; i < install_locales.n_entries; i++)
+ {
+@@ -858,6 +869,16 @@ grub_install_copy_nls(const char *src __attribute__ ((unused)),
+ continue;
+ }
+ free (srcf);
++ srcf = grub_util_path_concat_ext (4, locale_langpack_dir,
++ install_locales.entries[i],
++ "LC_MESSAGES", PACKAGE, ".mo");
++ if (grub_install_compress_file (srcf, dstf, 0))
++ {
++ free (srcf);
++ free (dstf);
++ continue;
++ }
++ free (srcf);
+ srcf = grub_util_path_concat_ext (4, locale_dir,
+ install_locales.entries[i],
+ "LC_MESSAGES", PACKAGE, ".mo");
+@@ -867,6 +888,8 @@ grub_install_copy_nls(const char *src __attribute__ ((unused)),
+ free (srcf);
+ free (dstf);
+ }
++
++ free (locale_langpack_dir);
+ }
+ free (dst_locale);
+ #endif
diff --git a/debian/patches/install-powerpc-machtypes.patch b/debian/patches/install-powerpc-machtypes.patch
new file mode 100644
index 0000000..385174f
--- /dev/null
+++ b/debian/patches/install-powerpc-machtypes.patch
@@ -0,0 +1,220 @@
+From 4b6f846398109576c218394c3d10bcb075c065a7 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Tue, 28 Jan 2014 14:40:02 +0000
+Subject: Port yaboot logic for various powerpc machine types
+
+Some powerpc machines require not updating the NVRAM. This can be handled
+by existing grub-install command-line options, but it's friendlier to detect
+this automatically.
+
+On chrp_ibm machines, use the nvram utility rather than nvsetenv. (This
+is possibly suitable for other machines too, but that needs to be
+verified.)
+
+Forwarded: no
+Last-Update: 2014-10-15
+
+Patch-Name: install-powerpc-machtypes.patch
+---
+ grub-core/osdep/basic/platform.c | 5 +++
+ grub-core/osdep/linux/platform.c | 72 ++++++++++++++++++++++++++++++
+ grub-core/osdep/unix/platform.c | 28 +++++++++---
+ grub-core/osdep/windows/platform.c | 6 +++
+ include/grub/util/install.h | 3 ++
+ util/grub-install.c | 11 +++++
+ 6 files changed, 119 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/osdep/basic/platform.c b/grub-core/osdep/basic/platform.c
+index a7dafd85a..6c293ed2d 100644
+--- a/grub-core/osdep/basic/platform.c
++++ b/grub-core/osdep/basic/platform.c
+@@ -30,3 +30,8 @@ grub_install_get_default_x86_platform (void)
+ return "i386-pc";
+ }
+
++const char *
++grub_install_get_default_powerpc_machtype (void)
++{
++ return "generic";
++}
+diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c
+index 2e7f72086..5b37366d4 100644
+--- a/grub-core/osdep/linux/platform.c
++++ b/grub-core/osdep/linux/platform.c
+@@ -24,6 +24,7 @@
+ #include <grub/emu/misc.h>
+ #include <sys/types.h>
+ #include <dirent.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+@@ -184,3 +185,74 @@ grub_install_get_default_x86_platform (void)
+ grub_util_info ("... not found");
+ return "i386-pc";
+ }
++
++const char *
++grub_install_get_default_powerpc_machtype (void)
++{
++ FILE *fp;
++ char *buf = NULL;
++ size_t len = 0;
++ const char *machtype = "generic";
++
++ fp = grub_util_fopen ("/proc/cpuinfo", "r");
++ if (! fp)
++ return machtype;
++
++ while (getline (&buf, &len, fp) > 0)
++ {
++ if (strncmp (buf, "pmac-generation",
++ sizeof ("pmac-generation") - 1) == 0)
++ {
++ if (strstr (buf, "NewWorld"))
++ {
++ machtype = "pmac_newworld";
++ break;
++ }
++ if (strstr (buf, "OldWorld"))
++ {
++ machtype = "pmac_oldworld";
++ break;
++ }
++ }
++
++ if (strncmp (buf, "motherboard", sizeof ("motherboard") - 1) == 0 &&
++ strstr (buf, "AAPL"))
++ {
++ machtype = "pmac_oldworld";
++ break;
++ }
++
++ if (strncmp (buf, "machine", sizeof ("machine") - 1) == 0 &&
++ strstr (buf, "CHRP IBM"))
++ {
++ if (strstr (buf, "qemu"))
++ {
++ machtype = "chrp_ibm_qemu";
++ break;
++ }
++ else
++ {
++ machtype = "chrp_ibm";
++ break;
++ }
++ }
++
++ if (strncmp (buf, "platform", sizeof ("platform") - 1) == 0)
++ {
++ if (strstr (buf, "Maple"))
++ {
++ machtype = "maple";
++ break;
++ }
++ if (strstr (buf, "Cell"))
++ {
++ machtype = "cell";
++ break;
++ }
++ }
++ }
++
++ free (buf);
++ fclose (fp);
++ return machtype;
++}
+diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
+index 55b8f4016..9c439326a 100644
+--- a/grub-core/osdep/unix/platform.c
++++ b/grub-core/osdep/unix/platform.c
+@@ -218,13 +218,29 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
+ else
+ boot_device = get_ofpathname (install_device);
+
+- if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
+- boot_device, NULL }))
++ if (strcmp (grub_install_get_default_powerpc_machtype (), "chrp_ibm") == 0)
+ {
+- char *cmd = xasprintf ("setenv boot-device %s", boot_device);
+- grub_util_error (_("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n"),
+- cmd);
+- free (cmd);
++ char *arg = xasprintf ("boot-device=%s", boot_device);
++ if (grub_util_exec ((const char * []){ "nvram",
++ "--update-config", arg, NULL }))
++ {
++ char *cmd = xasprintf ("setenv boot-device %s", boot_device);
++ grub_util_error (_("`nvram' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n"),
++ cmd);
++ free (cmd);
++ }
++ free (arg);
++ }
++ else
++ {
++ if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
++ boot_device, NULL }))
++ {
++ char *cmd = xasprintf ("setenv boot-device %s", boot_device);
++ grub_util_error (_("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n"),
++ cmd);
++ free (cmd);
++ }
+ }
+
+ free (boot_device);
+diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
+index 253f8d101..d18488f20 100644
+--- a/grub-core/osdep/windows/platform.c
++++ b/grub-core/osdep/windows/platform.c
+@@ -128,6 +128,12 @@ grub_install_get_default_x86_platform (void)
+ return "i386-efi";
+ }
+
++const char *
++grub_install_get_default_powerpc_machtype (void)
++{
++ return "generic";
++}
++
+ static void *
+ get_efi_variable (const wchar_t *varname, ssize_t *len)
+ {
+diff --git a/include/grub/util/install.h b/include/grub/util/install.h
+index 7df3191f4..135ba48d2 100644
+--- a/include/grub/util/install.h
++++ b/include/grub/util/install.h
+@@ -223,6 +223,9 @@ grub_install_get_default_arm_platform (void);
+ const char *
+ grub_install_get_default_x86_platform (void);
+
++const char *
++grub_install_get_default_powerpc_machtype (void);
++
+ int
+ grub_install_register_efi (grub_device_t efidir_grub_dev,
+ const char *efifile_path,
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 48c8c0364..d02bd488a 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -1187,7 +1187,18 @@ main (int argc, char *argv[])
+
+ if (platform == GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
+ {
++ const char *machtype = grub_install_get_default_powerpc_machtype ();
+ int is_guess = 0;
++
++ if (strcmp (machtype, "pmac_oldworld") == 0)
++ update_nvram = 0;
++ else if (strcmp (machtype, "cell") == 0)
++ update_nvram = 0;
++ else if (strcmp (machtype, "generic") == 0)
++ update_nvram = 0;
++ else if (strcmp (machtype, "chrp_ibm_qemu") == 0)
++ update_nvram = 0;
++
+ if (!macppcdir)
+ {
+ char *d;
diff --git a/debian/patches/install-signed.patch b/debian/patches/install-signed.patch
new file mode 100644
index 0000000..62f315f
--- /dev/null
+++ b/debian/patches/install-signed.patch
@@ -0,0 +1,309 @@
+From 0bd31f4c7468f0b42ff6673f47112b9167c6381c Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:22 +0000
+Subject: Install signed images if UEFI Secure Boot is enabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Author: Stéphane Graber <stgraber@ubuntu.com>
+Author: Steve Langasek <steve.langasek@ubuntu.com>
+Author: Linn Crosetto <linn@hpe.com>
+Author: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
+Forwarded: no
+Last-Update: 2023-01-15
+
+Patch-Name: install-signed.patch
+---
+ util/grub-install.c | 212 ++++++++++++++++++++++++++++++++------------
+ 1 file changed, 153 insertions(+), 59 deletions(-)
+
+Index: grub.git/util/grub-install.c
+===================================================================
+--- grub.git.orig/util/grub-install.c
++++ grub.git/util/grub-install.c
+@@ -79,6 +79,7 @@ static char *label_color;
+ static char *label_bgcolor;
+ static char *product_version;
+ static int add_rs_codes = 1;
++static int uefi_secure_boot = 1;
+
+ enum
+ {
+@@ -109,7 +110,9 @@ enum
+ OPTION_LABEL_FONT,
+ OPTION_LABEL_COLOR,
+ OPTION_LABEL_BGCOLOR,
+- OPTION_PRODUCT_VERSION
++ OPTION_PRODUCT_VERSION,
++ OPTION_UEFI_SECURE_BOOT,
++ OPTION_NO_UEFI_SECURE_BOOT
+ };
+
+ static int fs_probe = 1;
+@@ -233,6 +236,14 @@ argp_parser (int key, char *arg, struct
+ bootloader_id = xstrdup (arg);
+ return 0;
+
++ case OPTION_UEFI_SECURE_BOOT:
++ uefi_secure_boot = 1;
++ return 0;
++
++ case OPTION_NO_UEFI_SECURE_BOOT:
++ uefi_secure_boot = 0;
++ return 0;
++
+ case ARGP_KEY_ARG:
+ if (install_device)
+ grub_util_error ("%s", _("More than one install device?"));
+@@ -302,6 +313,14 @@ static struct argp_option options[] = {
+ {"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
+ {"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
+ {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
++ {"uefi-secure-boot", OPTION_UEFI_SECURE_BOOT, 0, 0,
++ N_("install an image usable with UEFI Secure Boot. "
++ "This option is only available on EFI and if the grub-efi-amd64-signed "
++ "package is installed."), 2},
++ {"no-uefi-secure-boot", OPTION_NO_UEFI_SECURE_BOOT, 0, 0,
++ N_("do not install an image usable with UEFI Secure Boot, even if the "
++ "system was currently started using it. "
++ "This option is only available on EFI."), 2},
+ {0, 0, 0, 0, 0, 0}
+ };
+
+@@ -832,7 +851,8 @@ main (int argc, char *argv[])
+ {
+ int is_efi = 0;
+ const char *efi_distributor = NULL;
+- const char *efi_file = NULL;
++ const char *efi_suffix = NULL, *efi_suffix_upper = NULL;
++ char *efi_file = NULL;
+ char **grub_devices;
+ grub_fs_t grub_fs;
+ grub_device_t grub_dev = NULL;
+@@ -1102,6 +1122,39 @@ main (int argc, char *argv[])
+ */
+ char *t;
+ efi_distributor = bootloader_id;
++ switch (platform)
++ {
++ case GRUB_INSTALL_PLATFORM_I386_EFI:
++ efi_suffix = "ia32";
++ efi_suffix_upper = "IA32";
++ break;
++ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
++ efi_suffix = "x64";
++ efi_suffix_upper = "X64";
++ break;
++ case GRUB_INSTALL_PLATFORM_IA64_EFI:
++ efi_suffix = "ia64";
++ efi_suffix_upper = "IA64";
++ break;
++ case GRUB_INSTALL_PLATFORM_ARM_EFI:
++ efi_suffix = "arm";
++ efi_suffix_upper = "ARM";
++ break;
++ case GRUB_INSTALL_PLATFORM_ARM64_EFI:
++ efi_suffix = "aa64";
++ efi_suffix_upper = "AA64";
++ break;
++ case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
++ efi_suffix = "riscv32";
++ efi_suffix_upper = "RISCV32";
++ break;
++ case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
++ efi_suffix = "riscv64";
++ efi_suffix_upper = "RISCV64";
++ break;
++ default:
++ break;
++ }
+ if (removable)
+ {
+ /* The specification makes stricter requirements of removable
+@@ -1110,66 +1163,16 @@ main (int argc, char *argv[])
+ must have a specific file name depending on the architecture.
+ */
+ efi_distributor = "BOOT";
+- switch (platform)
+- {
+- case GRUB_INSTALL_PLATFORM_I386_EFI:
+- efi_file = "BOOTIA32.EFI";
+- break;
+- case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+- efi_file = "BOOTX64.EFI";
+- break;
+- case GRUB_INSTALL_PLATFORM_IA64_EFI:
+- efi_file = "BOOTIA64.EFI";
+- break;
+- case GRUB_INSTALL_PLATFORM_ARM_EFI:
+- efi_file = "BOOTARM.EFI";
+- break;
+- case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+- efi_file = "BOOTAA64.EFI";
+- break;
+- case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+- efi_file = "BOOTRISCV32.EFI";
+- break;
+- case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+- efi_file = "BOOTRISCV64.EFI";
+- break;
+- default:
+- grub_util_error ("%s", _("You've found a bug"));
+- break;
+- }
++ if (!efi_suffix)
++ grub_util_error ("%s", _("You've found a bug"));
++ efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
+ }
+ else
+ {
+ /* It is convenient for each architecture to have a different
+ efi_file, so that different versions can be installed in parallel.
+ */
+- switch (platform)
+- {
+- case GRUB_INSTALL_PLATFORM_I386_EFI:
+- efi_file = "grubia32.efi";
+- break;
+- case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+- efi_file = "grubx64.efi";
+- break;
+- case GRUB_INSTALL_PLATFORM_IA64_EFI:
+- efi_file = "grubia64.efi";
+- break;
+- case GRUB_INSTALL_PLATFORM_ARM_EFI:
+- efi_file = "grubarm.efi";
+- break;
+- case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+- efi_file = "grubaa64.efi";
+- break;
+- case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+- efi_file = "grubriscv32.efi";
+- break;
+- case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+- efi_file = "grubriscv64.efi";
+- break;
+- default:
+- efi_file = "grub.efi";
+- break;
+- }
++ efi_file = xasprintf ("grub%s.efi", efi_suffix);
+ }
+ t = grub_util_path_concat (3, efidir, "EFI", efi_distributor);
+ free (efidir);
+@@ -1375,14 +1378,38 @@ main (int argc, char *argv[])
+ }
+ }
+
+- if (!have_abstractions)
++ char *efi_signed = NULL;
++ switch (platform)
++ {
++ case GRUB_INSTALL_PLATFORM_I386_EFI:
++ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
++ case GRUB_INSTALL_PLATFORM_ARM_EFI:
++ case GRUB_INSTALL_PLATFORM_ARM64_EFI:
++ case GRUB_INSTALL_PLATFORM_IA64_EFI:
++ {
++ char *dir = xasprintf ("%s-signed", grub_install_source_directory);
++ char *signed_image;
++ signed_image = xasprintf ("grub%s.efi.signed", efi_suffix);
++ efi_signed = grub_util_path_concat (2, dir, signed_image);
++ break;
++ }
++
++ default:
++ break;
++ }
++
++ if (!efi_signed || !grub_util_is_regular (efi_signed))
++ uefi_secure_boot = 0;
++
++ if (!have_abstractions || uefi_secure_boot)
+ {
+ if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
+ || grub_drives[1]
+ || (!install_drive
+ && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
+ || (install_drive && !is_same_disk (grub_drives[0], install_drive))
+- || !have_bootdev (platform))
++ || !have_bootdev (platform)
++ || uefi_secure_boot)
+ {
+ char *uuid = NULL;
+ /* generic method (used on coreboot and ata mod). */
+@@ -1927,7 +1957,72 @@ main (int argc, char *argv[])
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ {
+ char *dst = grub_util_path_concat (2, efidir, efi_file);
+- grub_install_copy_file (imgfile, dst, 1);
++ if (uefi_secure_boot)
++ {
++ char *shim_signed = NULL;
++ char *mok_signed = NULL, *mok_file = NULL;
++ char *fb_signed = NULL, *fb_file = NULL;
++ char *config_dst;
++ FILE *config_dst_f;
++
++ shim_signed = xasprintf ("/usr/lib/shim/shim%s.efi.signed", efi_suffix);
++ mok_signed = xasprintf ("mm%s.efi.signed", efi_suffix);
++ mok_file = xasprintf ("mm%s.efi", efi_suffix);
++ fb_signed = xasprintf ("fb%s.efi.signed", efi_suffix);
++ fb_file = xasprintf ("fb%s.efi", efi_suffix);
++
++ if (grub_util_is_regular (shim_signed))
++ {
++ char *chained_base, *chained_dst;
++ char *mok_src, *mok_dst, *fb_src, *fb_dst;
++ if (!removable)
++ {
++ free (efi_file);
++ efi_file = xasprintf ("shim%s.efi", efi_suffix);
++ free (dst);
++ dst = grub_util_path_concat (2, efidir, efi_file);
++ }
++ grub_install_copy_file (shim_signed, dst, 1);
++ chained_base = xasprintf ("grub%s.efi", efi_suffix);
++ chained_dst = grub_util_path_concat (2, efidir, chained_base);
++ grub_install_copy_file (efi_signed, chained_dst, 1);
++ free (chained_dst);
++ free (chained_base);
++
++ /* Not critical, so not an error if they are not present (as it
++ won't be for older releases); but if we have them, make
++ sure they are installed. */
++ mok_src = grub_util_path_concat (2, "/usr/lib/shim/",
++ mok_signed);
++ mok_dst = grub_util_path_concat (2, efidir,
++ mok_file);
++ grub_install_copy_file (mok_src,
++ mok_dst, 0);
++ free (mok_src);
++ free (mok_dst);
++
++ fb_src = grub_util_path_concat (2, "/usr/lib/shim/",
++ fb_signed);
++ fb_dst = grub_util_path_concat (2, efidir,
++ fb_file);
++ if (!removable)
++ grub_install_copy_file (fb_src,
++ fb_dst, 0);
++ free (fb_src);
++ free (fb_dst);
++ }
++ else
++ grub_install_copy_file (efi_signed, dst, 1);
++
++ config_dst = grub_util_path_concat (2, efidir, "grub.cfg");
++ grub_install_copy_file (load_cfg, config_dst, 1);
++ config_dst_f = grub_util_fopen (config_dst, "ab");
++ fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
++ fclose (config_dst_f);
++ free (config_dst);
++ }
++ else
++ grub_install_copy_file (imgfile, dst, 1);
+
+ grub_set_install_backup_ponr ();
+
diff --git a/debian/patches/install-stage2-confusion.patch b/debian/patches/install-stage2-confusion.patch
new file mode 100644
index 0000000..d7e60d3
--- /dev/null
+++ b/debian/patches/install-stage2-confusion.patch
@@ -0,0 +1,46 @@
+From 07ebcd8f769c2522b9a3a79c3d92082747f83781 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:12:58 +0000
+Subject: If GRUB Legacy is still around, tell packaging to ignore it
+
+Bug-Debian: http://bugs.debian.org/586143
+Forwarded: not-needed
+Last-Update: 2021-09-24
+
+Patch-Name: install-stage2-confusion.patch
+---
+ util/grub-install.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 0fbe7f78c..48e2d3779 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -42,6 +42,7 @@
+ #include <grub/emu/config.h>
+ #include <grub/util/ofpath.h>
+ #include <grub/hfsplus.h>
++#include <grub/emu/hostfile.h>
+
+ #include <string.h>
+
+@@ -1727,6 +1728,19 @@ main (int argc, char *argv[])
+
+ grub_set_install_backup_ponr ();
+ }
++
++ /* If vestiges of GRUB Legacy still exist, tell the Debian packaging
++ that they can ignore them. */
++ if (!rootdir && grub_util_is_regular ("/boot/grub/stage2") &&
++ grub_util_is_regular ("/boot/grub/menu.lst"))
++ {
++ grub_util_fd_t fd;
++
++ fd = grub_util_fd_open ("/boot/grub/grub2-installed",
++ GRUB_UTIL_FD_O_WRONLY);
++ grub_util_fd_close (fd);
++ }
++
+ break;
+ }
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
diff --git a/debian/patches/kern-file-Fix-error-handling-in-grub_file_open.patch b/debian/patches/kern-file-Fix-error-handling-in-grub_file_open.patch
new file mode 100644
index 0000000..d64c88e
--- /dev/null
+++ b/debian/patches/kern-file-Fix-error-handling-in-grub_file_open.patch
@@ -0,0 +1,37 @@
+From aee575ddefd35f0fd6592171ae48ab6a4bb27464 Mon Sep 17 00:00:00 2001
+From: Steve McIntyre <steve@einval.com>
+Date: Mon, 5 Dec 2022 23:14:10 +0000
+Subject: [PATCH] kern/file: Fix error handling in grub_file_open()
+
+grub_file_open() calls grub_file_get_device_name(), but doesn't check
+the return. Instead, it checks if grub_errno is set.
+
+However, nothing initialises grub_errno here when grub_file_open()
+starts. This means that trying to open one file that doesn't exist and
+then trying to open another file that does will (incorrectly) also
+fail to open that second file.
+
+Let's fix that.
+
+Signed-off-by: Steve McIntyre <steve@einval.com>
+---
+ grub-core/kern/file.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
+index 8d48fd50d..668b149c3 100644
+--- a/grub-core/kern/file.c
++++ b/grub-core/kern/file.c
+@@ -66,6 +66,9 @@ grub_file_open (const char *name, enum grub_file_type type)
+ const char *file_name;
+ grub_file_filter_id_t filter;
+
++ /* Reset grub_errno before we start */
++ grub_errno = GRUB_ERR_NONE;
++
+ device_name = grub_file_get_device_name (name);
+ if (grub_errno)
+ goto fail;
+--
+2.30.2
+
diff --git a/debian/patches/linuxefi.patch b/debian/patches/linuxefi.patch
new file mode 100644
index 0000000..20fe4de
--- /dev/null
+++ b/debian/patches/linuxefi.patch
@@ -0,0 +1,552 @@
+From fc550c31c25dcf9eb58ca1e987f3ce2be8ebac28 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg@redhat.com>
+Date: Mon, 13 Jan 2014 12:13:15 +0000
+Subject: Add "linuxefi" loader which avoids ExitBootServices
+
+Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub2-linuxefi.patch
+Author: Colin Watson <cjwatson@ubuntu.com>
+Author: Steve Langasek <steve.langasek@canonical.com>
+Author: Linn Crosetto <linn@hpe.com>
+Forwarded: no
+Last-Update: 2021-09-24
+
+Patch-Name: linuxefi.patch
+---
+ grub-core/Makefile.core.def | 7 +
+ grub-core/kern/efi/mm.c | 32 +++
+ grub-core/loader/i386/efi/linux.c | 383 ++++++++++++++++++++++++++++++
+ grub-core/loader/i386/linux.c | 41 ++++
+ include/grub/efi/efi.h | 3 +
+ 5 files changed, 466 insertions(+)
+ create mode 100644 grub-core/loader/i386/efi/linux.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 8022e1c0a..e5b3d27f5 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1874,6 +1874,13 @@ module = {
+ enable = x86_64_efi;
+ };
+
++module = {
++ name = linuxefi;
++ efi = loader/i386/efi/linux.c;
++ enable = i386_efi;
++ enable = x86_64_efi;
++};
++
+ module = {
+ name = chain;
+ efi = loader/efi/chainloader.c;
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index 9838fb2f5..f6aef0ef6 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
+ }
+ }
+
++/* Allocate pages below a specified address */
++void *
++grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
++ grub_efi_uintn_t pages)
++{
++ grub_efi_status_t status;
++ grub_efi_boot_services_t *b;
++ grub_efi_physical_address_t address = max;
++
++ if (max > 0xffffffff)
++ return 0;
++
++ b = grub_efi_system_table->boot_services;
++ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
++
++ if (status != GRUB_EFI_SUCCESS)
++ return 0;
++
++ if (address == 0)
++ {
++ /* Uggh, the address 0 was allocated... This is too annoying,
++ so reallocate another one. */
++ address = max;
++ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
++ grub_efi_free_pages (0, pages);
++ if (status != GRUB_EFI_SUCCESS)
++ return 0;
++ }
++
++ return (void *) ((grub_addr_t) address);
++}
++
+ /* Allocate pages. Return the pointer to the first of allocated pages. */
+ void *
+ grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+new file mode 100644
+index 000000000..45b68c05a
+--- /dev/null
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -0,0 +1,383 @@
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2012 Free Software Foundation, Inc.
++ *
++ * GRUB is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GRUB is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/loader.h>
++#include <grub/file.h>
++#include <grub/err.h>
++#include <grub/misc.h>
++#include <grub/types.h>
++#include <grub/mm.h>
++#include <grub/cpu/linux.h>
++#include <grub/command.h>
++#include <grub/i18n.h>
++#include <grub/lib/cmdline.h>
++#include <grub/linux.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/sb.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++static grub_dl_t my_mod;
++static int loaded;
++static void *kernel_mem;
++static grub_uint64_t kernel_size;
++static grub_uint8_t *initrd_mem;
++static grub_uint32_t handover_offset;
++struct linux_kernel_params *params;
++static char *linux_cmdline;
++
++#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
++
++#define SHIM_LOCK_GUID \
++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
++
++struct grub_efi_shim_lock
++{
++ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
++};
++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
++
++static grub_efi_boolean_t
++grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
++{
++ grub_efi_guid_t guid = SHIM_LOCK_GUID;
++ grub_efi_shim_lock_t *shim_lock;
++ grub_efi_status_t status;
++
++ if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++ {
++ grub_dprintf ("linuxefi", "secure boot not enabled, not validating");
++ return 1;
++ }
++
++ grub_dprintf ("linuxefi", "Locating shim protocol\n");
++ shim_lock = grub_efi_locate_protocol(&guid, NULL);
++
++ if (!shim_lock)
++ {
++ grub_dprintf ("linuxefi", "shim not available\n");
++ return 0;
++ }
++
++ grub_dprintf ("linuxefi", "Asking shim to verify kernel signature\n");
++ status = shim_lock->verify(data, size);
++ if (status == GRUB_EFI_SUCCESS)
++ {
++ grub_dprintf ("linuxefi", "Kernel signature verification passed\n");
++ return 1;
++ }
++
++ grub_dprintf ("linuxefi", "Kernel signature verification failed (0x%lx)\n",
++ (unsigned long) status);
++ return 0;
++}
++
++typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
++
++static grub_err_t
++grub_linuxefi_boot (void)
++{
++ handover_func hf;
++ int offset = 0;
++
++#ifdef __x86_64__
++ offset = 512;
++#endif
++
++ hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
++
++ asm volatile ("cli");
++
++ hf (grub_efi_image_handle, grub_efi_system_table, params);
++
++ /* Not reached */
++ return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_linuxefi_unload (void)
++{
++ grub_dl_unref (my_mod);
++ loaded = 0;
++ if (initrd_mem)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
++ if (linux_cmdline)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
++ if (kernel_mem)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
++ if (params)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
++ return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
++ int argc, char *argv[])
++{
++ grub_size_t size = 0;
++ struct grub_linux_initrd_context initrd_ctx;
++
++ if (argc == 0)
++ {
++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
++ goto fail;
++ }
++
++ if (!loaded)
++ {
++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
++ goto fail;
++ }
++
++ if (grub_initrd_init (argc, argv, &initrd_ctx))
++ goto fail;
++
++ size = grub_get_initrd_size (&initrd_ctx);
++
++ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
++
++ if (!initrd_mem)
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
++ goto fail;
++ }
++
++ grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem);
++
++ params->ramdisk_size = size;
++ params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
++
++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
++ goto fail;
++
++ params->ramdisk_size = size;
++
++ fail:
++ grub_initrd_close (&initrd_ctx);
++
++ if (initrd_mem && grub_errno)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(size));
++
++ return grub_errno;
++}
++
++static grub_err_t
++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
++ int argc, char *argv[])
++{
++ grub_file_t file = 0;
++ struct linux_i386_kernel_header lh;
++ grub_ssize_t len, start, filelen;
++ void *kernel;
++
++ grub_dl_ref (my_mod);
++
++ if (argc == 0)
++ {
++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
++ goto fail;
++ }
++
++ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
++ if (! file)
++ goto fail;
++
++ filelen = grub_file_size (file);
++
++ kernel = grub_malloc(filelen);
++
++ if (!kernel)
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
++ goto fail;
++ }
++
++ if (grub_file_read (file, kernel, filelen) != filelen)
++ {
++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
++ goto fail;
++ }
++
++ if (! grub_linuxefi_secure_validate (kernel, filelen))
++ {
++ grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]);
++ grub_free (kernel);
++ goto fail;
++ }
++
++ grub_file_seek (file, 0);
++
++ grub_free(kernel);
++
++ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
++
++ if (! params)
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
++ goto fail;
++ }
++
++ grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params);
++
++ grub_memset (params, 0, 16384);
++
++ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
++ {
++ if (!grub_errno)
++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
++ argv[0]);
++ goto fail;
++ }
++
++ if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
++ {
++ grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
++ goto fail;
++ }
++
++ if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
++ {
++ grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
++ goto fail;
++ }
++
++ if (lh.version < grub_cpu_to_le16 (0x020b))
++ {
++ grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
++ goto fail;
++ }
++
++ if (!lh.handover_offset)
++ {
++ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
++ goto fail;
++ }
++
++ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
++ BYTES_TO_PAGES(lh.cmdline_size + 1));
++
++ if (!linux_cmdline)
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
++ goto fail;
++ }
++
++ grub_dprintf ("linuxefi", "linux_cmdline = %lx\n",
++ (unsigned long) linux_cmdline);
++
++ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
++ {
++ grub_err_t err;
++ err = grub_create_loader_cmdline (argc, argv,
++ linux_cmdline
++ + sizeof (LINUX_IMAGE) - 1,
++ lh.cmdline_size
++ - (sizeof (LINUX_IMAGE) - 1),
++ GRUB_VERIFY_KERNEL_CMDLINE);
++ if (err)
++ goto fail;
++ }
++
++ lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
++
++ handover_offset = lh.handover_offset;
++
++ start = (lh.setup_sects + 1) * 512;
++ len = grub_file_size(file) - start;
++
++ kernel_mem = grub_efi_allocate_fixed(lh.pref_address,
++ BYTES_TO_PAGES(lh.init_size));
++
++ if (!kernel_mem)
++ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
++ BYTES_TO_PAGES(lh.init_size));
++
++ if (!kernel_mem)
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
++ goto fail;
++ }
++ grub_errno = GRUB_ERR_NONE;
++
++ grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
++
++ if (grub_file_seek (file, start) == (grub_off_t) -1)
++ {
++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
++ argv[0]);
++ goto fail;
++ }
++
++ if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
++ {
++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
++ argv[0]);
++ }
++
++ if (grub_errno == GRUB_ERR_NONE)
++ {
++ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
++ loaded = 1;
++ lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
++ }
++
++ grub_memcpy (params, &lh, 2 * 512);
++
++ params->type_of_loader = 0x21;
++
++ fail:
++
++ if (file)
++ grub_file_close (file);
++
++ if (grub_errno != GRUB_ERR_NONE)
++ {
++ grub_dl_unref (my_mod);
++ loaded = 0;
++ }
++
++ if (linux_cmdline && !loaded)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
++
++ if (kernel_mem && !loaded)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
++
++ if (params && !loaded)
++ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
++
++ return grub_errno;
++}
++
++static grub_command_t cmd_linux, cmd_initrd;
++
++GRUB_MOD_INIT(linuxefi)
++{
++ cmd_linux =
++ grub_register_command ("linuxefi", grub_cmd_linux,
++ 0, N_("Load Linux."));
++ cmd_initrd =
++ grub_register_command ("initrdefi", grub_cmd_initrd,
++ 0, N_("Load initrd."));
++ my_mod = mod;
++}
++
++GRUB_MOD_FINI(linuxefi)
++{
++ grub_unregister_command (cmd_linux);
++ grub_unregister_command (cmd_initrd);
++}
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 9f74a96b1..be37a1640 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -78,6 +78,8 @@ static grub_size_t maximal_cmdline_size;
+ static struct linux_kernel_params linux_params;
+ static char *linux_cmdline;
+ #ifdef GRUB_MACHINE_EFI
++static int using_linuxefi;
++static grub_command_t initrdefi_cmd;
+ static grub_efi_uintn_t efi_mmap_size;
+ #else
+ static const grub_size_t efi_mmap_size = 0;
+@@ -659,6 +661,39 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+
+ grub_dl_ref (my_mod);
+
++#ifdef GRUB_MACHINE_EFI
++ using_linuxefi = 0;
++ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++ {
++ /* linuxefi requires a successful signature check and then hand over
++ to the kernel without calling ExitBootServices. */
++ grub_dl_t mod;
++ grub_command_t linuxefi_cmd;
++
++ grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
++
++ mod = grub_dl_load ("linuxefi");
++ if (mod)
++ {
++ grub_dl_ref (mod);
++ linuxefi_cmd = grub_command_find ("linuxefi");
++ initrdefi_cmd = grub_command_find ("initrdefi");
++ if (linuxefi_cmd && initrdefi_cmd)
++ {
++ (linuxefi_cmd->func) (linuxefi_cmd, argc, argv);
++ if (grub_errno == GRUB_ERR_NONE)
++ {
++ grub_dprintf ("linux", "Handing off to linuxefi\n");
++ using_linuxefi = 1;
++ return GRUB_ERR_NONE;
++ }
++ grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
++ goto fail;
++ }
++ }
++ }
++#endif
++
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -1042,6 +1077,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ grub_err_t err;
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+
++#ifdef GRUB_MACHINE_EFI
++ /* If we're using linuxefi, just forward to initrdefi. */
++ if (using_linuxefi && initrdefi_cmd)
++ return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv);
++#endif
++
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index 83d958f99..08f6ee00a 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -47,6 +47,9 @@ EXPORT_FUNC(grub_efi_allocate_fixed) (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages);
+ void *
+ EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages);
++void *
++EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max,
++ grub_efi_uintn_t pages);
+ void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
+ grub_efi_uintn_t pages);
+ grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);
diff --git a/debian/patches/maybe-quiet.patch b/debian/patches/maybe-quiet.patch
new file mode 100644
index 0000000..33d1e0f
--- /dev/null
+++ b/debian/patches/maybe-quiet.patch
@@ -0,0 +1,386 @@
+From 0b33def5d9ace3488fa612e09a5bb813c5e3cd90 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:26 +0000
+Subject: Add configure option to reduce visual clutter at boot time
+
+If this option is enabled, then do all of the following:
+
+Don't display introductory message about line editing unless we're
+actually offering a shell prompt. (This is believed to be a workaround
+for a different bug. We'll go with this for now, but will drop this in
+favour of a better fix upstream if somebody figures out what that is.)
+
+Don't clear the screen just before booting if we never drew the menu in
+the first place.
+
+Remove verbose messages printed before reading configuration. In some
+ways this is awkward because it makes debugging harder, but it's a
+requirement for a smooth-looking boot process; we may be able to do
+better in future. Upstream doesn't want this, though.
+
+Disable the cursor as well, for similar reasons of tidiness.
+
+Suppress kernel/initrd progress messages, except in recovery mode.
+
+Suppress "GRUB loading" message unless Shift is held down. Upstream
+doesn't want this, as it makes debugging harder. Ubuntu wants it to
+provide a cleaner boot experience.
+
+Author: Will Thompson <will@willthompson.co.uk>
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/386922
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/861048
+Forwarded: (partial) http://lists.gnu.org/archive/html/grub-devel/2009-09/msg00056.html
+Last-Update: 2021-09-24
+
+Patch-Name: maybe-quiet.patch
+---
+ config.h.in | 2 ++
+ configure.ac | 16 ++++++++++++++++
+ grub-core/boot/i386/pc/boot.S | 11 +++++++++++
+ grub-core/boot/i386/pc/diskboot.S | 26 ++++++++++++++++++++++++++
+ grub-core/kern/main.c | 17 +++++++++++++++++
+ grub-core/kern/rescue_reader.c | 2 ++
+ grub-core/normal/main.c | 11 +++++++++++
+ grub-core/normal/menu.c | 17 +++++++++++++++--
+ util/grub.d/10_linux.in | 15 +++++++++++----
+ 9 files changed, 111 insertions(+), 6 deletions(-)
+
+diff --git a/config.h.in b/config.h.in
+index 9e8f9911b..d2c4ce8e5 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -12,6 +12,8 @@
+ /* Define to 1 to enable disk cache statistics. */
+ #define DISK_CACHE_STATS @DISK_CACHE_STATS@
+ #define BOOT_TIME_STATS @BOOT_TIME_STATS@
++/* Define to 1 to make GRUB quieter at boot time. */
++#define QUIET_BOOT @QUIET_BOOT@
+
+ /* We don't need those. */
+ #define MINILZO_CFG_SKIP_LZO_PTR 1
+diff --git a/configure.ac b/configure.ac
+index 74778a6f8..256fc44ef 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1915,6 +1915,17 @@ else
+ fi
+ AC_SUBST([UBUNTU_RECOVERY])
+
++AC_ARG_ENABLE([quiet-boot],
++ [AS_HELP_STRING([--enable-quiet-boot],
++ [emit fewer messages at boot time (default=no)])],
++ [], [enable_quiet_boot=no])
++if test x"$enable_quiet_boot" = xyes ; then
++ QUIET_BOOT=1
++else
++ QUIET_BOOT=0
++fi
++AC_SUBST([QUIET_BOOT])
++
+ LIBS=""
+
+ AC_SUBST([FONT_SOURCE])
+@@ -2177,5 +2188,10 @@ echo "With stack smashing protector: Yes"
+ else
+ echo "With stack smashing protector: No"
+ fi
++if [ x"$enable_quiet_boot" = xyes ]; then
++echo With quiet boot: Yes
++else
++echo With quiet boot: No
++fi
+ echo "*******************************************************"
+ ]
+diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S
+index 2bd0b2d28..b0c0f2225 100644
+--- a/grub-core/boot/i386/pc/boot.S
++++ b/grub-core/boot/i386/pc/boot.S
+@@ -19,6 +19,9 @@
+
+ #include <grub/symbol.h>
+ #include <grub/machine/boot.h>
++#if QUIET_BOOT && !defined(HYBRID_BOOT)
++#include <grub/machine/memory.h>
++#endif
+
+ /*
+ * defines for the code go here
+@@ -249,9 +252,17 @@ real_start:
+ /* save drive reference first thing! */
+ pushw %dx
+
++#if QUIET_BOOT && !defined(HYBRID_BOOT)
++ /* is either shift key held down? */
++ movw $(GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR + 0x17), %bx
++ testb $3, (%bx)
++ jz 2f
++#endif
++
+ /* print a notification message on the screen */
+ MSG(notification_string)
+
++2:
+ /* set %si to the disk address packet */
+ movw $disk_address_packet, %si
+
+diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
+index c1addc0df..9b6d7a7ed 100644
+--- a/grub-core/boot/i386/pc/diskboot.S
++++ b/grub-core/boot/i386/pc/diskboot.S
+@@ -18,6 +18,9 @@
+
+ #include <grub/symbol.h>
+ #include <grub/machine/boot.h>
++#if QUIET_BOOT
++#include <grub/machine/memory.h>
++#endif
+
+ /*
+ * defines for the code go here
+@@ -25,6 +28,12 @@
+
+ #define MSG(x) movw $x, %si; call LOCAL(message)
+
++#if QUIET_BOOT
++#define SILENT(x) call LOCAL(check_silent); jz LOCAL(x)
++#else
++#define SILENT(x)
++#endif
++
+ .file "diskboot.S"
+
+ .text
+@@ -50,11 +59,14 @@ _start:
+ /* save drive reference first thing! */
+ pushw %dx
+
++ SILENT(after_notification_string)
++
+ /* print a notification message on the screen */
+ pushw %si
+ MSG(notification_string)
+ popw %si
+
++LOCAL(after_notification_string):
+ /* this sets up for the first run through "bootloop" */
+ movw $LOCAL(firstlist), %di
+
+@@ -279,7 +291,10 @@ LOCAL(copy_buffer):
+ /* restore addressing regs and print a dot with correct DS
+ (MSG modifies SI, which is saved, and unused AX and BX) */
+ popw %ds
++ SILENT(after_notification_step)
+ MSG(notification_step)
++
++LOCAL(after_notification_step):
+ popa
+
+ /* check if finished with this dataset */
+@@ -295,8 +310,11 @@ LOCAL(copy_buffer):
+ /* END OF MAIN LOOP */
+
+ LOCAL(bootit):
++ SILENT(after_notification_done)
+ /* print a newline */
+ MSG(notification_done)
++
++LOCAL(after_notification_done):
+ popw %dx /* this makes sure %dl is our "boot" drive */
+ ljmp $0, $(GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
+
+@@ -320,6 +338,14 @@ LOCAL(general_error):
+ /* go here when you need to stop the machine hard after an error condition */
+ LOCAL(stop): jmp LOCAL(stop)
+
++#if QUIET_BOOT
++LOCAL(check_silent):
++ /* is either shift key held down? */
++ movw $(GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR + 0x17), %bx
++ testb $3, (%bx)
++ ret
++#endif
++
+ notification_string: .asciz "loading"
+
+ notification_step: .asciz "."
+diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
+index 73967e2f5..2879d644a 100644
+--- a/grub-core/kern/main.c
++++ b/grub-core/kern/main.c
+@@ -265,15 +265,25 @@ reclaim_module_space (void)
+ void __attribute__ ((noreturn))
+ grub_main (void)
+ {
++#if QUIET_BOOT
++ struct grub_term_output *term;
++#endif
++
+ /* First of all, initialize the machine. */
+ grub_machine_init ();
+
+ grub_boot_time ("After machine init.");
+
++#if QUIET_BOOT
++ /* Disable the cursor until we need it. */
++ FOR_ACTIVE_TERM_OUTPUTS(term)
++ grub_term_setcursor (term, 0);
++#else
+ /* Hello. */
+ grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+ grub_printf ("Welcome to GRUB!\n\n");
+ grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
++#endif
+
+ /* Init verifiers API. */
+ grub_verifiers_init ();
+@@ -312,5 +322,12 @@ grub_main (void)
+ grub_boot_time ("After execution of embedded config. Attempt to go to normal mode");
+
+ grub_load_normal_mode ();
++
++#if QUIET_BOOT
++ /* If we have to enter rescue mode, enable the cursor again. */
++ FOR_ACTIVE_TERM_OUTPUTS(term)
++ grub_term_setcursor (term, 1);
++#endif
++
+ grub_rescue_run ();
+ }
+diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c
+index dcd7d4439..a93524eab 100644
+--- a/grub-core/kern/rescue_reader.c
++++ b/grub-core/kern/rescue_reader.c
+@@ -78,7 +78,9 @@ grub_rescue_read_line (char **line, int cont,
+ void __attribute__ ((noreturn))
+ grub_rescue_run (void)
+ {
++#if QUIET_BOOT
+ grub_printf ("Entering rescue mode...\n");
++#endif
+
+ while (1)
+ {
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index c4ebe9e22..a1750e09c 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -407,6 +407,15 @@ static grub_err_t
+ grub_normal_read_line_real (char **line, int cont, int nested)
+ {
+ const char *prompt;
++#if QUIET_BOOT
++ static int displayed_intro;
++
++ if (! displayed_intro)
++ {
++ grub_normal_reader_init (nested);
++ displayed_intro = 1;
++ }
++#endif
+
+ if (cont)
+ /* TRANSLATORS: it's command line prompt. */
+@@ -459,7 +468,9 @@ grub_cmdline_run (int nested, int force_auth)
+ return;
+ }
+
++#if !QUIET_BOOT
+ grub_normal_reader_init (nested);
++#endif
+
+ while (1)
+ {
+diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
+index 8397886fa..e9d8444b5 100644
+--- a/grub-core/normal/menu.c
++++ b/grub-core/normal/menu.c
+@@ -807,12 +807,18 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
+
+ /* Callback invoked immediately before a menu entry is executed. */
+ static void
+-notify_booting (grub_menu_entry_t entry,
++notify_booting (grub_menu_entry_t entry
++#if QUIET_BOOT
++ __attribute__((unused))
++#endif
++ ,
+ void *userdata __attribute__((unused)))
+ {
++#if !QUIET_BOOT
+ grub_printf (" ");
+ grub_printf_ (N_("Booting `%s'"), entry->title);
+ grub_printf ("\n\n");
++#endif
+ }
+
+ /* Callback invoked when a default menu entry executed because of a timeout
+@@ -860,6 +866,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
+ int boot_entry;
+ grub_menu_entry_t e;
+ int auto_boot;
++#if QUIET_BOOT
++ int initial_timeout = grub_menu_get_timeout ();
++#endif
+
+ boot_entry = run_menu (menu, nested, &auto_boot);
+ if (boot_entry < 0)
+@@ -869,7 +878,11 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
+ if (! e)
+ continue; /* Menu is empty. */
+
+- grub_cls ();
++#if QUIET_BOOT
++ /* Only clear the screen if we drew the menu in the first place. */
++ if (initial_timeout != 0)
++#endif
++ grub_cls ();
+
+ if (auto_boot)
+ grub_menu_execute_with_fallback (menu, e, autobooted,
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 1b8c6e146..869a7eec5 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -21,6 +21,7 @@ prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ datarootdir="@datarootdir@"
+ ubuntu_recovery="@UBUNTU_RECOVERY@"
++quiet_boot="@QUIET_BOOT@"
+
+ . "$pkgdatadir/grub-mkconfig_lib"
+
+@@ -158,10 +159,12 @@ linux_entry ()
+ fi
+ printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
+ fi
+- message="$(gettext_printf "Loading Linux %s ..." ${version})"
+- sed "s/^/$submenu_indentation/" << EOF
++ if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
++ message="$(gettext_printf "Loading Linux %s ..." ${version})"
++ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
+ EOF
++ fi
+ if test -d /sys/firmware/efi && test -e "${linux}.efi.signed"; then
+ sed "s/^/$submenu_indentation/" << EOF
+ linux ${rel_dirname}/${basename}.efi.signed root=${linux_root_device_thisversion} ro ${args}
+@@ -173,13 +176,17 @@ EOF
+ fi
+ if test -n "${initrd}" ; then
+ # TRANSLATORS: ramdisk isn't identifier. Should be translated.
+- message="$(gettext_printf "Loading initial ramdisk ...")"
++ if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
++ message="$(gettext_printf "Loading initial ramdisk ...")"
++ sed "s/^/$submenu_indentation/" << EOF
++ echo '$(echo "$message" | grub_quote)'
++EOF
++ fi
+ initrd_path=
+ for i in ${initrd}; do
+ initrd_path="${initrd_path} ${rel_dirname}/${i}"
+ done
+ sed "s/^/$submenu_indentation/" << EOF
+- echo '$(echo "$message" | grub_quote)'
+ initrd $(echo $initrd_path)
+ EOF
+ fi
diff --git a/debian/patches/minilzo-2.10.patch b/debian/patches/minilzo-2.10.patch
new file mode 100644
index 0000000..9dfce7c
--- /dev/null
+++ b/debian/patches/minilzo-2.10.patch
@@ -0,0 +1,2539 @@
+From dbcbb3e5b9fac665b92d630eb24de7bd8c43652e Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sun, 28 Nov 2021 23:42:30 +0000
+Subject: minilzo: Update to minilzo-2.10
+
+minilzo fails to build on a number of Debian release architectures
+(armel, mips64el, mipsel, ppc64el) with errors such as:
+
+ ../../grub-core/lib/minilzo/minilzo.c: In function 'lzo_memops_get_le16':
+ ../../grub-core/lib/minilzo/minilzo.c:3479:11: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
+ 3479 | * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ../../grub-core/lib/minilzo/minilzo.c:3530:5: note: in expansion of macro 'LZO_MEMOPS_COPY2'
+ 3530 | LZO_MEMOPS_COPY2(&v, ss);
+ | ^~~~~~~~~~~~~~~~
+
+The latest upstream version is 2.10, so updating to it seems like a good
+idea on general principles, and it fixes builds on all the above
+architectures.
+
+The update procedure documented in the GRUB Developers Manual worked; I
+just updated the version numbers to make it clear that it's been
+executed recently.
+
+Signed-off-by: Colin Watson <cjwatson@debian.org>
+
+Forwarded: https://lists.gnu.org/archive/html/grub-devel/2021-11/msg00095.html
+Last-Update: 2021-11-29
+
+Patch-Name: minilzo-2.10.patch
+---
+ docs/grub-dev.texi | 10 +-
+ grub-core/lib/minilzo/lzoconf.h | 41 ++-
+ grub-core/lib/minilzo/lzodefs.h | 416 +++++++++++++++++++-----
+ grub-core/lib/minilzo/minilzo.c | 542 +++++++++++++++++++++++++-------
+ grub-core/lib/minilzo/minilzo.h | 22 +-
+ 5 files changed, 817 insertions(+), 214 deletions(-)
+
+diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
+index 6c629a23e..eb755d998 100644
+--- a/docs/grub-dev.texi
++++ b/docs/grub-dev.texi
+@@ -575,12 +575,12 @@ To upgrade to a new version of the miniLZO library, download the release
+ tarball and copy the files into the target directory:
+
+ @example
+-curl -L -O http://www.oberhumer.com/opensource/lzo/download/minilzo-2.08.tar.gz
+-tar -zxf minilzo-2.08.tar.gz
+-rm minilzo-2.08/testmini.c
++curl -L -O http://www.oberhumer.com/opensource/lzo/download/minilzo-2.10.tar.gz
++tar -zxf minilzo-2.10.tar.gz
++rm minilzo-2.10/testmini.c
+ rm -r grub-core/lib/minilzo/*
+-cp minilzo-2.08/*.[hc] grub-core/lib/minilzo
+-rm -r minilzo-2.08*
++cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
++rm -r minilzo-2.10*
+ @end example
+
+ @node Porting
+diff --git a/grub-core/lib/minilzo/lzoconf.h b/grub-core/lib/minilzo/lzoconf.h
+index 61be29c5d..f9a8bdbee 100644
+--- a/grub-core/lib/minilzo/lzoconf.h
++++ b/grub-core/lib/minilzo/lzoconf.h
+@@ -2,7 +2,7 @@
+
+ This file is part of the LZO real-time data compression library.
+
+- Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
++ Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library is free software; you can redistribute it and/or
+@@ -29,9 +29,9 @@
+ #ifndef __LZOCONF_H_INCLUDED
+ #define __LZOCONF_H_INCLUDED 1
+
+-#define LZO_VERSION 0x2080
+-#define LZO_VERSION_STRING "2.08"
+-#define LZO_VERSION_DATE "Jun 29 2014"
++#define LZO_VERSION 0x20a0 /* 2.10 */
++#define LZO_VERSION_STRING "2.10"
++#define LZO_VERSION_DATE "Mar 01 2017"
+
+ /* internal Autoconf configuration file - only used when building LZO */
+ #if defined(LZO_HAVE_CONFIG_H)
+@@ -57,7 +57,7 @@
+
+ /* get OS and architecture defines */
+ #ifndef __LZODEFS_H_INCLUDED
+-#include "lzodefs.h"
++#include <lzo/lzodefs.h>
+ #endif
+
+
+@@ -94,25 +94,29 @@ extern "C" {
+ # if (LZO_OS_WIN64)
+ typedef unsigned __int64 lzo_uint;
+ typedef __int64 lzo_int;
++# define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64
+ # else
+ typedef lzo_ullong_t lzo_uint;
+ typedef lzo_llong_t lzo_int;
++# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG
+ # endif
+-# define LZO_SIZEOF_LZO_UINT 8
++# define LZO_SIZEOF_LZO_INT 8
+ # define LZO_UINT_MAX 0xffffffffffffffffull
+ # define LZO_INT_MAX 9223372036854775807LL
+ # define LZO_INT_MIN (-1LL - LZO_INT_MAX)
+ # elif (LZO_ABI_IP32L64) /* MIPS R5900 */
+ typedef unsigned int lzo_uint;
+ typedef int lzo_int;
+-# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_INT
++# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT
+ # define LZO_UINT_MAX UINT_MAX
+ # define LZO_INT_MAX INT_MAX
+ # define LZO_INT_MIN INT_MIN
+ # elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint;
+ typedef long lzo_int;
+-# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LONG
++# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG
+ # define LZO_UINT_MAX ULONG_MAX
+ # define LZO_INT_MAX LONG_MAX
+ # define LZO_INT_MIN LONG_MIN
+@@ -122,7 +126,7 @@ extern "C" {
+ #endif
+
+ /* The larger type of lzo_uint and lzo_uint32_t. */
+-#if (LZO_SIZEOF_LZO_UINT >= 4)
++#if (LZO_SIZEOF_LZO_INT >= 4)
+ # define lzo_xint lzo_uint
+ #else
+ # define lzo_xint lzo_uint32_t
+@@ -131,7 +135,8 @@ extern "C" {
+ typedef int lzo_bool;
+
+ /* sanity checks */
+-LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_UINT)
++LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT)
++LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint))
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t))
+
+@@ -163,14 +168,14 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t))
+ #endif
+
+ /* Older LZO versions used to support ancient systems and memory models
+- * like 16-bit MSDOS with __huge pointers and Cray PVP, but these
++ * such as 16-bit MSDOS with __huge pointers or Cray PVP, but these
+ * obsolete configurations are not supported any longer.
+ */
+ #if defined(__LZO_MMODEL_HUGE)
+-#error "__LZO_MMODEL_HUGE is unsupported"
++#error "__LZO_MMODEL_HUGE memory model is unsupported"
+ #endif
+ #if (LZO_MM_PVP)
+-#error "LZO_MM_PVP is unsupported"
++#error "LZO_MM_PVP memory model is unsupported"
+ #endif
+ #if (LZO_SIZEOF_INT < 4)
+ #error "LZO_SIZEOF_INT < 4 is unsupported"
+@@ -221,13 +226,13 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep))
+
+ /* __cdecl calling convention for public C and assembly functions */
+ #if !defined(LZO_PUBLIC)
+-# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
++# define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL
+ #endif
+ #if !defined(LZO_EXTERN)
+-# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
++# define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r)
+ #endif
+ #if !defined(LZO_PRIVATE)
+-# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
++# define LZO_PRIVATE(r) static r __LZO_CDECL
+ #endif
+
+ /* function types */
+@@ -399,6 +404,10 @@ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
+ /* deprecated types */
+ typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u;
+ typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u;
++/* deprecated defines */
++#if !defined(LZO_SIZEOF_LZO_UINT)
++# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT
++#endif
+
+ #if defined(LZO_CFG_COMPAT)
+
+diff --git a/grub-core/lib/minilzo/lzodefs.h b/grub-core/lib/minilzo/lzodefs.h
+index f4ae9487e..c3e2bcf5d 100644
+--- a/grub-core/lib/minilzo/lzodefs.h
++++ b/grub-core/lib/minilzo/lzodefs.h
+@@ -2,7 +2,7 @@
+
+ This file is part of the LZO real-time data compression library.
+
+- Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
++ Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library is free software; you can redistribute it and/or
+@@ -40,6 +40,33 @@
+ # define __LONG_MAX__ 9223372036854775807L
+ # endif
+ #endif
++#if 0
++#elif !defined(__LZO_LANG_OVERRIDE)
++#if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__)
++# if (__ASSEMBLER__+0) <= 0
++# error "__ASSEMBLER__"
++# else
++# define LZO_LANG_ASSEMBLER 1
++# endif
++#elif defined(__cplusplus)
++# if (__cplusplus+0) <= 0
++# error "__cplusplus"
++# elif (__cplusplus < 199711L)
++# define LZO_LANG_CXX 1
++# elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1
++# define LZO_LANG_CXX _MSVC_LANG
++# else
++# define LZO_LANG_CXX __cplusplus
++# endif
++# define LZO_LANG_CPLUSPLUS LZO_LANG_CXX
++#else
++# if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L)
++# define LZO_LANG_C __STDC_VERSION__
++# else
++# define LZO_LANG_C 1
++# endif
++#endif
++#endif
+ #if !defined(LZO_CFG_NO_DISABLE_WUNDEF)
+ #if defined(__ARMCC_VERSION)
+ # pragma diag_suppress 193
+@@ -135,10 +162,12 @@
+ # endif
+ #endif
+ #endif
+-#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
++#if (UINT_MAX == LZO_0xffffL)
++#if defined(_MSC_VER) && defined(M_I86HM)
+ # define ptrdiff_t long
+ # define _PTRDIFF_T_DEFINED 1
+ #endif
++#endif
+ #if (UINT_MAX == LZO_0xffffL)
+ # undef __LZO_RENAME_A
+ # undef __LZO_RENAME_B
+@@ -287,7 +316,7 @@
+ #define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f)
+ #define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g)
+ #endif
+-#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b))
++#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0))
+ #if 1 && defined(__cplusplus)
+ # if !defined(__STDC_CONSTANT_MACROS)
+ # define __STDC_CONSTANT_MACROS 1
+@@ -398,7 +427,7 @@
+ #elif defined(__TOS__) || defined(__atarist__)
+ # define LZO_OS_TOS 1
+ # define LZO_INFO_OS "tos"
+-#elif defined(macintosh) && !defined(__ppc__)
++#elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__)
+ # define LZO_OS_MACCLASSIC 1
+ # define LZO_INFO_OS "macclassic"
+ #elif defined(__VMS)
+@@ -538,6 +567,12 @@
+ # define LZO_CC_ARMCC __ARMCC_VERSION
+ # define LZO_INFO_CC "ARM C Compiler"
+ # define LZO_INFO_CCVER __VERSION__
++#elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER)
++# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0))
++# define LZO_CC_CLANG_C2 _MSC_VER
++# define LZO_CC_CLANG_VENDOR_MICROSOFT 1
++# define LZO_INFO_CC "clang/c2"
++# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__)
+ #elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__)
+ # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+ # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0))
+@@ -549,8 +584,18 @@
+ # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+ # define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+ # endif
+-# define LZO_INFO_CC "clang"
+-# define LZO_INFO_CCVER __VERSION__
++# if defined(__APPLE_CC__)
++# define LZO_CC_CLANG_VENDOR_APPLE 1
++# define LZO_INFO_CC "clang/apple"
++# else
++# define LZO_CC_CLANG_VENDOR_LLVM 1
++# define LZO_INFO_CC "clang"
++# endif
++# if defined(__clang_version__)
++# define LZO_INFO_CCVER __clang_version__
++# else
++# define LZO_INFO_CCVER __VERSION__
++# endif
+ #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+ # if defined(__GNUC_PATCHLEVEL__)
+ # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+@@ -770,7 +815,7 @@
+ #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+ # define LZO_ARCH_I086 1
+ # define LZO_INFO_ARCH "i086"
+-#elif defined(__aarch64__)
++#elif defined(__aarch64__) || defined(_M_ARM64)
+ # define LZO_ARCH_ARM64 1
+ # define LZO_INFO_ARCH "arm64"
+ #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+@@ -782,22 +827,11 @@
+ #elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+ # define LZO_ARCH_AMD64 1
+ # define LZO_INFO_ARCH "amd64"
+-#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
++#elif defined(__arm__) || defined(_M_ARM)
+ # define LZO_ARCH_ARM 1
+-# define LZO_ARCH_ARM_THUMB 1
+-# define LZO_INFO_ARCH "arm_thumb"
++# define LZO_INFO_ARCH "arm"
+ #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+ # define LZO_ARCH_ARM 1
+-# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1)
+-# define LZO_ARCH_ARM_THUMB 1
+-# define LZO_INFO_ARCH "arm_thumb"
+-# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2)
+-# define LZO_INFO_ARCH "arm"
+-# else
+-# define LZO_INFO_ARCH "arm"
+-# endif
+-#elif defined(__arm__) || defined(_M_ARM)
+-# define LZO_ARCH_ARM 1
+ # define LZO_INFO_ARCH "arm"
+ #elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+ # define LZO_ARCH_AVR 1
+@@ -871,6 +905,15 @@
+ #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+ # define LZO_ARCH_POWERPC 1
+ # define LZO_INFO_ARCH "powerpc"
++#elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__)
++# define LZO_ARCH_POWERPC 1
++# define LZO_INFO_ARCH "powerpc"
++#elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__)
++# define LZO_ARCH_POWERPC 1
++# define LZO_INFO_ARCH "powerpc"
++#elif defined(__riscv)
++# define LZO_ARCH_RISCV 1
++# define LZO_INFO_ARCH "riscv"
+ #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+ # define LZO_ARCH_S390 1
+ # define LZO_INFO_ARCH "s390"
+@@ -905,6 +948,23 @@
+ # define LZO_INFO_ARCH "unknown"
+ #endif
+ #endif
++#if !defined(LZO_ARCH_ARM_THUMB2)
++#if (LZO_ARCH_ARM)
++# if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB)
++# if defined(__thumb2__)
++# define LZO_ARCH_ARM_THUMB2 1
++# elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4)
++# define LZO_ARCH_ARM_THUMB2 1
++# elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7)
++# define LZO_ARCH_ARM_THUMB2 1
++# endif
++# endif
++#endif
++#endif
++#if (LZO_ARCH_ARM_THUMB2)
++# undef LZO_INFO_ARCH
++# define LZO_INFO_ARCH "arm_thumb2"
++#endif
+ #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+ # error "FIXME - missing define for CPU architecture"
+ #endif
+@@ -947,13 +1007,10 @@
+ #if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86)
+ # error "unexpected configuration - check your compiler defines"
+ #endif
+-#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM)
+-# error "unexpected configuration - check your compiler defines"
+-#endif
+-#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB)
++#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM)
+ # error "unexpected configuration - check your compiler defines"
+ #endif
+-#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB)
++#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM)
+ # error "unexpected configuration - check your compiler defines"
+ #endif
+ #if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2)
+@@ -985,7 +1042,9 @@
+ # if !defined(LZO_TARGET_FEATURE_SSE2)
+ # if defined(__SSE2__)
+ # define LZO_TARGET_FEATURE_SSE2 1
+-# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64))
++# elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2))
++# define LZO_TARGET_FEATURE_SSE2 1
++# elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64)
+ # define LZO_TARGET_FEATURE_SSE2 1
+ # endif
+ # endif
+@@ -1034,7 +1093,11 @@
+ #endif
+ #if (LZO_ARCH_ARM)
+ # if !defined(LZO_TARGET_FEATURE_NEON)
+-# if defined(__ARM_NEON__)
++# if defined(__ARM_NEON) && ((__ARM_NEON)+0)
++# define LZO_TARGET_FEATURE_NEON 1
++# elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0)
++# define LZO_TARGET_FEATURE_NEON 1
++# elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0)
+ # define LZO_TARGET_FEATURE_NEON 1
+ # endif
+ # endif
+@@ -1105,7 +1168,7 @@
+ # error "unexpected configuration - check your compiler defines"
+ # endif
+ #endif
+-#ifdef __cplusplus
++#if defined(__cplusplus)
+ extern "C" {
+ #endif
+ #if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+@@ -1128,7 +1191,7 @@ extern "C" {
+ #else
+ # error "FIXME - implement LZO_MM_AHSHIFT"
+ #endif
+-#ifdef __cplusplus
++#if defined(__cplusplus)
+ }
+ #endif
+ #endif
+@@ -1214,12 +1277,53 @@ extern "C" {
+ # define __lzo_gnuc_extension__ __extension__
+ #elif (LZO_CC_IBMC >= 600)
+ # define __lzo_gnuc_extension__ __extension__
+-#else
+ #endif
+ #endif
+ #if !defined(__lzo_gnuc_extension__)
+ # define __lzo_gnuc_extension__ /*empty*/
+ #endif
++#if !defined(lzo_has_builtin)
++#if (LZO_CC_CLANG) && defined(__has_builtin)
++# define lzo_has_builtin __has_builtin
++#endif
++#endif
++#if !defined(lzo_has_builtin)
++# define lzo_has_builtin(x) 0
++#endif
++#if !defined(lzo_has_attribute)
++#if (LZO_CC_CLANG) && defined(__has_attribute)
++# define lzo_has_attribute __has_attribute
++#endif
++#endif
++#if !defined(lzo_has_attribute)
++# define lzo_has_attribute(x) 0
++#endif
++#if !defined(lzo_has_declspec_attribute)
++#if (LZO_CC_CLANG) && defined(__has_declspec_attribute)
++# define lzo_has_declspec_attribute __has_declspec_attribute
++#endif
++#endif
++#if !defined(lzo_has_declspec_attribute)
++# define lzo_has_declspec_attribute(x) 0
++#endif
++#if !defined(lzo_has_feature)
++#if (LZO_CC_CLANG) && defined(__has_feature)
++# define lzo_has_feature __has_feature
++#endif
++#endif
++#if !defined(lzo_has_feature)
++# define lzo_has_feature(x) 0
++#endif
++#if !defined(lzo_has_extension)
++#if (LZO_CC_CLANG) && defined(__has_extension)
++# define lzo_has_extension __has_extension
++#elif (LZO_CC_CLANG) && defined(__has_feature)
++# define lzo_has_extension __has_feature
++#endif
++#endif
++#if !defined(lzo_has_extension)
++# define lzo_has_extension(x) 0
++#endif
+ #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0
+ # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul))
+ # define LZO_CFG_USE_NEW_STYLE_CASTS 0
+@@ -1356,7 +1460,7 @@ extern "C" {
+ # elif (LZO_CC_MSC && (_MSC_VER < 900))
+ # define LZO_UNUSED(var) if (&var) ; else
+ # elif (LZO_CC_KEILC)
+-# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];}
++# define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;}
+ # elif (LZO_CC_PACIFICC)
+ # define LZO_UNUSED(var) ((void) sizeof(var))
+ # elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+@@ -1365,6 +1469,9 @@ extern "C" {
+ # define LZO_UNUSED(var) ((void) &var)
+ # endif
+ #endif
++#if !defined(LZO_UNUSED_RESULT)
++# define LZO_UNUSED_RESULT(var) LZO_UNUSED(var)
++#endif
+ #if !defined(LZO_UNUSED_FUNC)
+ # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+ # define LZO_UNUSED_FUNC(func) ((void) func)
+@@ -1377,7 +1484,7 @@ extern "C" {
+ # elif (LZO_CC_MSC)
+ # define LZO_UNUSED_FUNC(func) ((void) &func)
+ # elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+-# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];}
++# define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;}
+ # else
+ # define LZO_UNUSED_FUNC(func) ((void) func)
+ # endif
+@@ -1783,6 +1890,7 @@ extern "C" {
+ #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+ # define __lzo_likely(e) (__builtin_expect(!!(e),1))
+ # define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
++#elif (LZO_CC_CLANG && LZO_CC_CLANG_C2)
+ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+ # define __lzo_likely(e) (__builtin_expect(!!(e),1))
+ # define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+@@ -1793,21 +1901,28 @@ extern "C" {
+ # define __lzo_HAVE_likely 1
+ # endif
+ #else
+-# define __lzo_likely(e) (e)
++# define __lzo_likely(e) (e)
++#endif
++#if defined(__lzo_very_likely)
++# ifndef __lzo_HAVE_very_likely
++# define __lzo_HAVE_very_likely 1
++# endif
++#else
++# define __lzo_very_likely(e) __lzo_likely(e)
+ #endif
+ #if defined(__lzo_unlikely)
+ # ifndef __lzo_HAVE_unlikely
+ # define __lzo_HAVE_unlikely 1
+ # endif
+ #else
+-# define __lzo_unlikely(e) (e)
++# define __lzo_unlikely(e) (e)
+ #endif
+-#if !defined(__lzo_static_unused_void_func)
+-# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+-# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void)
+-# else
+-# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void)
++#if defined(__lzo_very_unlikely)
++# ifndef __lzo_HAVE_very_unlikely
++# define __lzo_HAVE_very_unlikely 1
+ # endif
++#else
++# define __lzo_very_unlikely(e) __lzo_unlikely(e)
+ #endif
+ #if !defined(__lzo_loop_forever)
+ # if (LZO_CC_IBMC)
+@@ -1817,7 +1932,7 @@ extern "C" {
+ # endif
+ #endif
+ #if !defined(__lzo_unreachable)
+-#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul))
++#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable)
+ # define __lzo_unreachable() __builtin_unreachable();
+ #elif (LZO_CC_GNUC >= 0x040500ul)
+ # define __lzo_unreachable() __builtin_unreachable();
+@@ -1836,6 +1951,15 @@ extern "C" {
+ # define __lzo_unreachable() __lzo_loop_forever();
+ # endif
+ #endif
++#if !defined(lzo_unused_funcs_impl)
++# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
++# define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f
++# elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC)
++# define lzo_unused_funcs_impl(r,f) static r f
++# else
++# define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f
++# endif
++#endif
+ #ifndef __LZO_CTA_NAME
+ #if (LZO_CFG_USE_COUNTER)
+ # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__)
+@@ -1861,6 +1985,8 @@ extern "C" {
+ #if !defined(LZO_COMPILE_TIME_ASSERT)
+ # if (LZO_CC_AZTECC)
+ # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];}
++# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul))
++# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));}
+ # elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+ # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+ # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__)
+@@ -1877,11 +2003,16 @@ extern "C" {
+ # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];}
+ # endif
+ #endif
++#if (LZO_LANG_ASSEMBLER)
++# undef LZO_COMPILE_TIME_ASSERT_HEADER
++# define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/
++#else
+ LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1)
+ #if defined(__cplusplus)
+ extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) }
+ #endif
+ LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
++#endif
+ #if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+ # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+ # elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+@@ -1948,7 +2079,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
+ #if !defined(LZO_HAVE_WINDOWS_H)
+ #if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+ # if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+-# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
++# elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)))
+ # elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+ # else
+ # define LZO_HAVE_WINDOWS_H 1
+@@ -1956,6 +2087,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
+ #endif
+ #endif
+ #endif
++#define LZO_SIZEOF_CHAR 1
+ #ifndef LZO_SIZEOF_SHORT
+ #if defined(SIZEOF_SHORT)
+ # define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+@@ -2154,12 +2286,12 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long))
+ # define LZO_WORDSIZE 8
+ #elif (LZO_ARCH_AMD64)
+ # define LZO_WORDSIZE 8
++#elif (LZO_ARCH_ARM64)
++# define LZO_WORDSIZE 8
+ #elif (LZO_ARCH_AVR)
+ # define LZO_WORDSIZE 1
+ #elif (LZO_ARCH_H8300)
+-# if defined(__NORMAL_MODE__)
+-# define LZO_WORDSIZE 4
+-# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
++# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+ # define LZO_WORDSIZE 4
+ # else
+ # define LZO_WORDSIZE 2
+@@ -2202,11 +2334,15 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8)
+ #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+ # define LZO_SIZEOF_VOID_P 2
+ #elif (LZO_ARCH_H8300)
+-# if defined(__NORMAL_MODE__)
+-# define LZO_SIZEOF_VOID_P 2
+-# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+-# define LZO_SIZEOF_VOID_P 4
++# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
++ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4)
++# if defined(__NORMAL_MODE__)
++# define LZO_SIZEOF_VOID_P 2
++# else
++# define LZO_SIZEOF_VOID_P 4
++# endif
+ # else
++ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2)
+ # define LZO_SIZEOF_VOID_P 2
+ # endif
+ # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+@@ -2296,7 +2432,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+ # define LZO_ABI_LITTLE_ENDIAN 1
+-#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
++#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV)
+ # define LZO_ABI_LITTLE_ENDIAN 1
+ #elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU)
+ # define LZO_ABI_BIG_ENDIAN 1
+@@ -2310,10 +2446,14 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0)
++# define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32)
++# define LZO_ABI_LITTLE_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC)
+ # if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+ # error "unexpected configuration - check your compiler defines"
+@@ -2323,10 +2463,14 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_LITTLE_ENDIAN 1
+ # endif
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0)
++# define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__)
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__)
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32)
++# define LZO_ABI_LITTLE_ENDIAN 1
+ #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+@@ -2368,6 +2512,12 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_IP32L64 1
+ # define LZO_INFO_ABI_PM "ip32l64"
+ #endif
++#if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8)
++# define LZO_ABI_IP32W64 1
++# ifndef LZO_INFO_ABI_PM
++# define LZO_INFO_ABI_PM "ip32w64"
++# endif
++#endif
+ #if 0
+ #elif !defined(__LZO_LIBC_OVERRIDE)
+ #if (LZO_LIBC_NAKED)
+@@ -2455,20 +2605,43 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # endif
+ #elif (LZO_ARCH_ARM)
+ # if defined(__ARM_FEATURE_UNALIGNED)
++# if ((__ARM_FEATURE_UNALIGNED)+0)
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# endif
++# elif 1 && (LZO_ARCH_ARM_THUMB2)
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7)
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+ # ifndef LZO_OPT_UNALIGNED32
+ # define LZO_OPT_UNALIGNED32 1
+ # endif
+-# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7)
++# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R))
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+ # ifndef LZO_OPT_UNALIGNED32
+ # define LZO_OPT_UNALIGNED32 1
+ # endif
+-# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M)
++# elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+@@ -2520,7 +2693,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ #elif (LZO_ARCH_POWERPC)
+ # define LZO_OPT_PREFER_PREINC 1
+ # define LZO_OPT_PREFER_PREDEC 1
+-# if (LZO_ABI_BIG_ENDIAN)
++# if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+@@ -2533,6 +2706,19 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # endif
+ # endif
+ # endif
++#elif (LZO_ARCH_RISCV)
++# define LZO_OPT_AVOID_UINT_INDEX 1
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# if (LZO_WORDSIZE == 8)
++# ifndef LZO_OPT_UNALIGNED64
++# define LZO_OPT_UNALIGNED64 1
++# endif
++# endif
+ #elif (LZO_ARCH_S390)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+@@ -2624,32 +2810,61 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ #if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0))
+ # error "missing defines for sizes"
+ #endif
++#define LZO_TYPEOF_CHAR 1u
++#define LZO_TYPEOF_SHORT 2u
++#define LZO_TYPEOF_INT 3u
++#define LZO_TYPEOF_LONG 4u
++#define LZO_TYPEOF_LONG_LONG 5u
++#define LZO_TYPEOF___INT8 17u
++#define LZO_TYPEOF___INT16 18u
++#define LZO_TYPEOF___INT32 19u
++#define LZO_TYPEOF___INT64 20u
++#define LZO_TYPEOF___INT128 21u
++#define LZO_TYPEOF___INT256 22u
++#define LZO_TYPEOF___MODE_QI 33u
++#define LZO_TYPEOF___MODE_HI 34u
++#define LZO_TYPEOF___MODE_SI 35u
++#define LZO_TYPEOF___MODE_DI 36u
++#define LZO_TYPEOF___MODE_TI 37u
++#define LZO_TYPEOF_CHAR_P 129u
+ #if !defined(lzo_llong_t)
+ #if (LZO_SIZEOF_LONG_LONG+0 > 0)
+-__lzo_gnuc_extension__ typedef long long lzo_llong_t__;
+-__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
++# if !(LZO_LANG_ASSEMBLER)
++ __lzo_gnuc_extension__ typedef long long lzo_llong_t__;
++ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
++# endif
+ # define lzo_llong_t lzo_llong_t__
+ # define lzo_ullong_t lzo_ullong_t__
+ #endif
+ #endif
+ #if !defined(lzo_int16e_t)
+-#if (LZO_SIZEOF_LONG == 2)
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T
++#endif
++#if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT)
+ # define lzo_int16e_t long
+ # define lzo_uint16e_t unsigned long
+-#elif (LZO_SIZEOF_INT == 2)
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG
++#elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT)
+ # define lzo_int16e_t int
+ # define lzo_uint16e_t unsigned int
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_SHORT == 2)
+ # define lzo_int16e_t short int
+ # define lzo_uint16e_t unsigned short int
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT
+ #elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM)
++# if !(LZO_LANG_ASSEMBLER)
+ typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__)));
+ typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__)));
++# endif
+ # define lzo_int16e_t lzo_int16e_hi_t__
+ # define lzo_uint16e_t lzo_uint16e_hi_t__
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI
+ #elif (LZO_SIZEOF___INT16 == 2)
+ # define lzo_int16e_t __int16
+ # define lzo_uint16e_t unsigned __int16
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16
+ #else
+ #endif
+ #endif
+@@ -2659,33 +2874,47 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T)
+ #endif
+ #if !defined(lzo_int32e_t)
+-#if (LZO_SIZEOF_LONG == 4)
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T
++#endif
++#if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT)
+ # define lzo_int32e_t long int
+ # define lzo_uint32e_t unsigned long int
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG
+ #elif (LZO_SIZEOF_INT == 4)
+ # define lzo_int32e_t int
+ # define lzo_uint32e_t unsigned int
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_SHORT == 4)
+ # define lzo_int32e_t short int
+ # define lzo_uint32e_t unsigned short int
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT
+ #elif (LZO_SIZEOF_LONG_LONG == 4)
+ # define lzo_int32e_t lzo_llong_t
+ # define lzo_uint32e_t lzo_ullong_t
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG
+ #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)
++# if !(LZO_LANG_ASSEMBLER)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
++# endif
+ # define lzo_int32e_t lzo_int32e_si_t__
+ # define lzo_uint32e_t lzo_uint32e_si_t__
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI
+ #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)
++# if !(LZO_LANG_ASSEMBLER)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
++# endif
+ # define lzo_int32e_t lzo_int32e_si_t__
+ # define lzo_uint32e_t lzo_uint32e_si_t__
+ # define LZO_INT32_C(c) (c##LL)
+ # define LZO_UINT32_C(c) (c##ULL)
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI
+ #elif (LZO_SIZEOF___INT32 == 4)
+ # define lzo_int32e_t __int32
+ # define lzo_uint32e_t unsigned __int32
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32
+ #else
+ #endif
+ #endif
+@@ -2696,21 +2925,28 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #endif
+ #if !defined(lzo_int64e_t)
+ #if (LZO_SIZEOF___INT64 == 8)
+-# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64)
+-# define LZO_CFG_TYPE_PREFER___INT64 1
++# if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T)
++# define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64
+ # endif
+ #endif
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T
++#endif
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T
++#endif
+ #if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+ # define lzo_int64e_t int
+ # define lzo_uint64e_t unsigned int
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT
+-#elif (LZO_SIZEOF_LONG == 8)
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT
++#elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64)
+ # define lzo_int64e_t long int
+ # define lzo_uint64e_t unsigned long int
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG
+-#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64)
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG
++#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64)
+ # define lzo_int64e_t lzo_llong_t
+ # define lzo_uint64e_t lzo_ullong_t
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG
+ # if (LZO_CC_BORLANDC)
+ # define LZO_INT64_C(c) ((c) + 0ll)
+ # define LZO_UINT64_C(c) ((c) + 0ull)
+@@ -2721,10 +2957,10 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define LZO_INT64_C(c) (c##LL)
+ # define LZO_UINT64_C(c) (c##ULL)
+ # endif
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG
+ #elif (LZO_SIZEOF___INT64 == 8)
+ # define lzo_int64e_t __int64
+ # define lzo_uint64e_t unsigned __int64
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64
+ # if (LZO_CC_BORLANDC)
+ # define LZO_INT64_C(c) ((c) + 0i64)
+ # define LZO_UINT64_C(c) ((c) + 0ui64)
+@@ -2732,11 +2968,11 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define LZO_INT64_C(c) (c##i64)
+ # define LZO_UINT64_C(c) (c##ui64)
+ # endif
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64
+ #else
+ #endif
+ #endif
+ #if defined(lzo_int64e_t)
++# define LZO_SIZEOF_LZO_INT64E_T 8
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T)
+ #endif
+@@ -2745,14 +2981,17 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int32l_t lzo_int32e_t
+ # define lzo_uint32l_t lzo_uint32e_t
+ # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T
++# define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T
+ #elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+ # define lzo_int32l_t int
+ # define lzo_uint32l_t unsigned int
+ # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT
+ #elif (LZO_SIZEOF_LONG >= 4)
+ # define lzo_int32l_t long int
+ # define lzo_uint32l_t unsigned long int
+ # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG
+ #else
+ # error "lzo_int32l_t"
+ #endif
+@@ -2766,6 +3005,7 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int64l_t lzo_int64e_t
+ # define lzo_uint64l_t lzo_uint64e_t
+ # define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T
++# define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T
+ #else
+ #endif
+ #endif
+@@ -2778,10 +3018,12 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int32f_t lzo_int64l_t
+ # define lzo_uint32f_t lzo_uint64l_t
+ # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T
+ #else
+ # define lzo_int32f_t lzo_int32l_t
+ # define lzo_uint32f_t lzo_uint32l_t
+ # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T
++# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T
+ #endif
+ #endif
+ #if 1
+@@ -2793,6 +3035,7 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int64f_t lzo_int64l_t
+ # define lzo_uint64f_t lzo_uint64l_t
+ # define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T
+ #else
+ #endif
+ #endif
+@@ -2803,33 +3046,43 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #if !defined(lzo_intptr_t)
+ #if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16))
+ # define __LZO_INTPTR_T_IS_POINTER 1
+- typedef char* lzo_intptr_t;
+- typedef char* lzo_uintptr_t;
++# if !(LZO_LANG_ASSEMBLER)
++ typedef char * lzo_intptr_t;
++ typedef char * lzo_uintptr_t;
++# endif
+ # define lzo_intptr_t lzo_intptr_t
+ # define lzo_uintptr_t lzo_uintptr_t
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P
+ #elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4))
++# if !(LZO_LANG_ASSEMBLER)
+ typedef __w64 int lzo_intptr_t;
+ typedef __w64 unsigned int lzo_uintptr_t;
++# endif
+ # define lzo_intptr_t lzo_intptr_t
+ # define lzo_uintptr_t lzo_uintptr_t
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P)
+ # define lzo_intptr_t short
+ # define lzo_uintptr_t unsigned short
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT
+ #elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+ # define lzo_intptr_t int
+ # define lzo_uintptr_t unsigned int
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P)
+ # define lzo_intptr_t long
+ # define lzo_uintptr_t unsigned long
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG
+ #elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P)
+ # define lzo_intptr_t lzo_int64l_t
+ # define lzo_uintptr_t lzo_uint64l_t
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T
+ #else
+ # error "lzo_intptr_t"
+ #endif
+@@ -2843,34 +3096,43 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER)
+ # define lzo_word_t lzo_uintptr_t
+ # define lzo_sword_t lzo_intptr_t
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_LONG)
+ # define lzo_word_t unsigned long
+ # define lzo_sword_t long
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_INT)
+ # define lzo_word_t unsigned int
+ # define lzo_sword_t int
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT)
+ # define lzo_word_t unsigned short
+ # define lzo_sword_t short
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT
+ #elif (LZO_WORDSIZE == 1)
+ # define lzo_word_t unsigned char
+ # define lzo_sword_t signed char
+-# define LZO_SIZEOF_LZO_WORD_T 1
++# define LZO_SIZEOF_LZO_WORD_T 1
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T)
+ # define lzo_word_t lzo_uint64l_t
+ # define lzo_sword_t lzo_int64l_t
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
+ #elif (LZO_ARCH_SPU) && (LZO_CC_GNUC)
+ #if 0
++# if !(LZO_LANG_ASSEMBLER)
+ typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__)));
+ typedef int lzo_sword_t __attribute__((__mode__(__V16QI__)));
++# endif
+ # define lzo_word_t lzo_word_t
+ # define lzo_sword_t lzo_sword_t
+ # define LZO_SIZEOF_LZO_WORD_T 16
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI
+ #endif
+ #else
+ # error "lzo_word_t"
+@@ -2885,6 +3147,7 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #define lzo_int8_t signed char
+ #define lzo_uint8_t unsigned char
+ #define LZO_SIZEOF_LZO_INT8_T 1
++#define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t))
+ #endif
+@@ -2892,6 +3155,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t))
+ #define lzo_int16_t lzo_int16e_t
+ #define lzo_uint16_t lzo_uint16e_t
+ #define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T
++#define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t))
+ #endif
+@@ -2899,6 +3163,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t))
+ #define lzo_int32_t lzo_int32e_t
+ #define lzo_uint32_t lzo_uint32e_t
+ #define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T
++#define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t))
+ #endif
+@@ -2906,6 +3171,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t))
+ #define lzo_int64_t lzo_int64e_t
+ #define lzo_uint64_t lzo_uint64e_t
+ #define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T
++#define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t))
+ #endif
+@@ -2913,6 +3179,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t))
+ #define lzo_int_least32_t lzo_int32l_t
+ #define lzo_uint_least32_t lzo_uint32l_t
+ #define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T
++#define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t))
+ #endif
+@@ -2920,6 +3187,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_leas
+ #define lzo_int_least64_t lzo_int64l_t
+ #define lzo_uint_least64_t lzo_uint64l_t
+ #define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T
++#define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t))
+ #endif
+@@ -2927,6 +3195,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_leas
+ #define lzo_int_fast32_t lzo_int32f_t
+ #define lzo_uint_fast32_t lzo_uint32f_t
+ #define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T
++#define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t))
+ #endif
+@@ -2934,6 +3203,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast3
+ #define lzo_int_fast64_t lzo_int64f_t
+ #define lzo_uint_fast64_t lzo_uint64f_t
+ #define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T
++#define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t))
+ #endif
+diff --git a/grub-core/lib/minilzo/minilzo.c b/grub-core/lib/minilzo/minilzo.c
+index ab2be5f4f..8fd866450 100644
+--- a/grub-core/lib/minilzo/minilzo.c
++++ b/grub-core/lib/minilzo/minilzo.c
+@@ -2,7 +2,7 @@
+
+ This file is part of the LZO real-time data compression library.
+
+- Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
++ Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library is free software; you can redistribute it and/or
+@@ -60,6 +60,33 @@
+ # define __LONG_MAX__ 9223372036854775807L
+ # endif
+ #endif
++#if 0
++#elif !defined(__LZO_LANG_OVERRIDE)
++#if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__)
++# if (__ASSEMBLER__+0) <= 0
++# error "__ASSEMBLER__"
++# else
++# define LZO_LANG_ASSEMBLER 1
++# endif
++#elif defined(__cplusplus)
++# if (__cplusplus+0) <= 0
++# error "__cplusplus"
++# elif (__cplusplus < 199711L)
++# define LZO_LANG_CXX 1
++# elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1
++# define LZO_LANG_CXX _MSVC_LANG
++# else
++# define LZO_LANG_CXX __cplusplus
++# endif
++# define LZO_LANG_CPLUSPLUS LZO_LANG_CXX
++#else
++# if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L)
++# define LZO_LANG_C __STDC_VERSION__
++# else
++# define LZO_LANG_C 1
++# endif
++#endif
++#endif
+ #if !defined(LZO_CFG_NO_DISABLE_WUNDEF)
+ #if defined(__ARMCC_VERSION)
+ # pragma diag_suppress 193
+@@ -155,10 +182,12 @@
+ # endif
+ #endif
+ #endif
+-#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
++#if (UINT_MAX == LZO_0xffffL)
++#if defined(_MSC_VER) && defined(M_I86HM)
+ # define ptrdiff_t long
+ # define _PTRDIFF_T_DEFINED 1
+ #endif
++#endif
+ #if (UINT_MAX == LZO_0xffffL)
+ # undef __LZO_RENAME_A
+ # undef __LZO_RENAME_B
+@@ -307,7 +336,7 @@
+ #define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f)
+ #define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g)
+ #endif
+-#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b))
++#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0))
+ #if 1 && defined(__cplusplus)
+ # if !defined(__STDC_CONSTANT_MACROS)
+ # define __STDC_CONSTANT_MACROS 1
+@@ -418,7 +447,7 @@
+ #elif defined(__TOS__) || defined(__atarist__)
+ # define LZO_OS_TOS 1
+ # define LZO_INFO_OS "tos"
+-#elif defined(macintosh) && !defined(__ppc__)
++#elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__)
+ # define LZO_OS_MACCLASSIC 1
+ # define LZO_INFO_OS "macclassic"
+ #elif defined(__VMS)
+@@ -558,6 +587,12 @@
+ # define LZO_CC_ARMCC __ARMCC_VERSION
+ # define LZO_INFO_CC "ARM C Compiler"
+ # define LZO_INFO_CCVER __VERSION__
++#elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER)
++# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0))
++# define LZO_CC_CLANG_C2 _MSC_VER
++# define LZO_CC_CLANG_VENDOR_MICROSOFT 1
++# define LZO_INFO_CC "clang/c2"
++# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__)
+ #elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__)
+ # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+ # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0))
+@@ -569,8 +604,18 @@
+ # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+ # define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+ # endif
+-# define LZO_INFO_CC "clang"
+-# define LZO_INFO_CCVER __VERSION__
++# if defined(__APPLE_CC__)
++# define LZO_CC_CLANG_VENDOR_APPLE 1
++# define LZO_INFO_CC "clang/apple"
++# else
++# define LZO_CC_CLANG_VENDOR_LLVM 1
++# define LZO_INFO_CC "clang"
++# endif
++# if defined(__clang_version__)
++# define LZO_INFO_CCVER __clang_version__
++# else
++# define LZO_INFO_CCVER __VERSION__
++# endif
+ #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+ # if defined(__GNUC_PATCHLEVEL__)
+ # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0))
+@@ -790,7 +835,7 @@
+ #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
+ # define LZO_ARCH_I086 1
+ # define LZO_INFO_ARCH "i086"
+-#elif defined(__aarch64__)
++#elif defined(__aarch64__) || defined(_M_ARM64)
+ # define LZO_ARCH_ARM64 1
+ # define LZO_INFO_ARCH "arm64"
+ #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
+@@ -802,22 +847,11 @@
+ #elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
+ # define LZO_ARCH_AMD64 1
+ # define LZO_INFO_ARCH "amd64"
+-#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB))
++#elif defined(__arm__) || defined(_M_ARM)
+ # define LZO_ARCH_ARM 1
+-# define LZO_ARCH_ARM_THUMB 1
+-# define LZO_INFO_ARCH "arm_thumb"
++# define LZO_INFO_ARCH "arm"
+ #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
+ # define LZO_ARCH_ARM 1
+-# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1)
+-# define LZO_ARCH_ARM_THUMB 1
+-# define LZO_INFO_ARCH "arm_thumb"
+-# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2)
+-# define LZO_INFO_ARCH "arm"
+-# else
+-# define LZO_INFO_ARCH "arm"
+-# endif
+-#elif defined(__arm__) || defined(_M_ARM)
+-# define LZO_ARCH_ARM 1
+ # define LZO_INFO_ARCH "arm"
+ #elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
+ # define LZO_ARCH_AVR 1
+@@ -891,6 +925,15 @@
+ #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
+ # define LZO_ARCH_POWERPC 1
+ # define LZO_INFO_ARCH "powerpc"
++#elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__)
++# define LZO_ARCH_POWERPC 1
++# define LZO_INFO_ARCH "powerpc"
++#elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__)
++# define LZO_ARCH_POWERPC 1
++# define LZO_INFO_ARCH "powerpc"
++#elif defined(__riscv)
++# define LZO_ARCH_RISCV 1
++# define LZO_INFO_ARCH "riscv"
+ #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
+ # define LZO_ARCH_S390 1
+ # define LZO_INFO_ARCH "s390"
+@@ -925,6 +968,23 @@
+ # define LZO_INFO_ARCH "unknown"
+ #endif
+ #endif
++#if !defined(LZO_ARCH_ARM_THUMB2)
++#if (LZO_ARCH_ARM)
++# if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB)
++# if defined(__thumb2__)
++# define LZO_ARCH_ARM_THUMB2 1
++# elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4)
++# define LZO_ARCH_ARM_THUMB2 1
++# elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7)
++# define LZO_ARCH_ARM_THUMB2 1
++# endif
++# endif
++#endif
++#endif
++#if (LZO_ARCH_ARM_THUMB2)
++# undef LZO_INFO_ARCH
++# define LZO_INFO_ARCH "arm_thumb2"
++#endif
+ #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2)
+ # error "FIXME - missing define for CPU architecture"
+ #endif
+@@ -967,13 +1027,10 @@
+ #if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86)
+ # error "unexpected configuration - check your compiler defines"
+ #endif
+-#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM)
+-# error "unexpected configuration - check your compiler defines"
+-#endif
+-#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB)
++#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM)
+ # error "unexpected configuration - check your compiler defines"
+ #endif
+-#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB)
++#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM)
+ # error "unexpected configuration - check your compiler defines"
+ #endif
+ #if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2)
+@@ -1005,7 +1062,9 @@
+ # if !defined(LZO_TARGET_FEATURE_SSE2)
+ # if defined(__SSE2__)
+ # define LZO_TARGET_FEATURE_SSE2 1
+-# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64))
++# elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2))
++# define LZO_TARGET_FEATURE_SSE2 1
++# elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64)
+ # define LZO_TARGET_FEATURE_SSE2 1
+ # endif
+ # endif
+@@ -1054,7 +1113,11 @@
+ #endif
+ #if (LZO_ARCH_ARM)
+ # if !defined(LZO_TARGET_FEATURE_NEON)
+-# if defined(__ARM_NEON__)
++# if defined(__ARM_NEON) && ((__ARM_NEON)+0)
++# define LZO_TARGET_FEATURE_NEON 1
++# elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0)
++# define LZO_TARGET_FEATURE_NEON 1
++# elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0)
+ # define LZO_TARGET_FEATURE_NEON 1
+ # endif
+ # endif
+@@ -1125,7 +1188,7 @@
+ # error "unexpected configuration - check your compiler defines"
+ # endif
+ #endif
+-#ifdef __cplusplus
++#if defined(__cplusplus)
+ extern "C" {
+ #endif
+ #if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200))
+@@ -1148,7 +1211,7 @@ extern "C" {
+ #else
+ # error "FIXME - implement LZO_MM_AHSHIFT"
+ #endif
+-#ifdef __cplusplus
++#if defined(__cplusplus)
+ }
+ #endif
+ #endif
+@@ -1234,12 +1297,53 @@ extern "C" {
+ # define __lzo_gnuc_extension__ __extension__
+ #elif (LZO_CC_IBMC >= 600)
+ # define __lzo_gnuc_extension__ __extension__
+-#else
+ #endif
+ #endif
+ #if !defined(__lzo_gnuc_extension__)
+ # define __lzo_gnuc_extension__ /*empty*/
+ #endif
++#if !defined(lzo_has_builtin)
++#if (LZO_CC_CLANG) && defined(__has_builtin)
++# define lzo_has_builtin __has_builtin
++#endif
++#endif
++#if !defined(lzo_has_builtin)
++# define lzo_has_builtin(x) 0
++#endif
++#if !defined(lzo_has_attribute)
++#if (LZO_CC_CLANG) && defined(__has_attribute)
++# define lzo_has_attribute __has_attribute
++#endif
++#endif
++#if !defined(lzo_has_attribute)
++# define lzo_has_attribute(x) 0
++#endif
++#if !defined(lzo_has_declspec_attribute)
++#if (LZO_CC_CLANG) && defined(__has_declspec_attribute)
++# define lzo_has_declspec_attribute __has_declspec_attribute
++#endif
++#endif
++#if !defined(lzo_has_declspec_attribute)
++# define lzo_has_declspec_attribute(x) 0
++#endif
++#if !defined(lzo_has_feature)
++#if (LZO_CC_CLANG) && defined(__has_feature)
++# define lzo_has_feature __has_feature
++#endif
++#endif
++#if !defined(lzo_has_feature)
++# define lzo_has_feature(x) 0
++#endif
++#if !defined(lzo_has_extension)
++#if (LZO_CC_CLANG) && defined(__has_extension)
++# define lzo_has_extension __has_extension
++#elif (LZO_CC_CLANG) && defined(__has_feature)
++# define lzo_has_extension __has_feature
++#endif
++#endif
++#if !defined(lzo_has_extension)
++# define lzo_has_extension(x) 0
++#endif
+ #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0
+ # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul))
+ # define LZO_CFG_USE_NEW_STYLE_CASTS 0
+@@ -1376,7 +1480,7 @@ extern "C" {
+ # elif (LZO_CC_MSC && (_MSC_VER < 900))
+ # define LZO_UNUSED(var) if (&var) ; else
+ # elif (LZO_CC_KEILC)
+-# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];}
++# define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;}
+ # elif (LZO_CC_PACIFICC)
+ # define LZO_UNUSED(var) ((void) sizeof(var))
+ # elif (LZO_CC_WATCOMC) && defined(__cplusplus)
+@@ -1385,6 +1489,9 @@ extern "C" {
+ # define LZO_UNUSED(var) ((void) &var)
+ # endif
+ #endif
++#if !defined(LZO_UNUSED_RESULT)
++# define LZO_UNUSED_RESULT(var) LZO_UNUSED(var)
++#endif
+ #if !defined(LZO_UNUSED_FUNC)
+ # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600))
+ # define LZO_UNUSED_FUNC(func) ((void) func)
+@@ -1397,7 +1504,7 @@ extern "C" {
+ # elif (LZO_CC_MSC)
+ # define LZO_UNUSED_FUNC(func) ((void) &func)
+ # elif (LZO_CC_KEILC || LZO_CC_PELLESC)
+-# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];}
++# define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;}
+ # else
+ # define LZO_UNUSED_FUNC(func) ((void) func)
+ # endif
+@@ -1803,6 +1910,7 @@ extern "C" {
+ #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800))
+ # define __lzo_likely(e) (__builtin_expect(!!(e),1))
+ # define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
++#elif (LZO_CC_CLANG && LZO_CC_CLANG_C2)
+ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+ # define __lzo_likely(e) (__builtin_expect(!!(e),1))
+ # define __lzo_unlikely(e) (__builtin_expect(!!(e),0))
+@@ -1813,21 +1921,28 @@ extern "C" {
+ # define __lzo_HAVE_likely 1
+ # endif
+ #else
+-# define __lzo_likely(e) (e)
++# define __lzo_likely(e) (e)
++#endif
++#if defined(__lzo_very_likely)
++# ifndef __lzo_HAVE_very_likely
++# define __lzo_HAVE_very_likely 1
++# endif
++#else
++# define __lzo_very_likely(e) __lzo_likely(e)
+ #endif
+ #if defined(__lzo_unlikely)
+ # ifndef __lzo_HAVE_unlikely
+ # define __lzo_HAVE_unlikely 1
+ # endif
+ #else
+-# define __lzo_unlikely(e) (e)
++# define __lzo_unlikely(e) (e)
+ #endif
+-#if !defined(__lzo_static_unused_void_func)
+-# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+-# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void)
+-# else
+-# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void)
++#if defined(__lzo_very_unlikely)
++# ifndef __lzo_HAVE_very_unlikely
++# define __lzo_HAVE_very_unlikely 1
+ # endif
++#else
++# define __lzo_very_unlikely(e) __lzo_unlikely(e)
+ #endif
+ #if !defined(__lzo_loop_forever)
+ # if (LZO_CC_IBMC)
+@@ -1837,7 +1952,7 @@ extern "C" {
+ # endif
+ #endif
+ #if !defined(__lzo_unreachable)
+-#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul))
++#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable)
+ # define __lzo_unreachable() __builtin_unreachable();
+ #elif (LZO_CC_GNUC >= 0x040500ul)
+ # define __lzo_unreachable() __builtin_unreachable();
+@@ -1856,6 +1971,15 @@ extern "C" {
+ # define __lzo_unreachable() __lzo_loop_forever();
+ # endif
+ #endif
++#if !defined(lzo_unused_funcs_impl)
++# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
++# define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f
++# elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC)
++# define lzo_unused_funcs_impl(r,f) static r f
++# else
++# define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f
++# endif
++#endif
+ #ifndef __LZO_CTA_NAME
+ #if (LZO_CFG_USE_COUNTER)
+ # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__)
+@@ -1881,6 +2005,8 @@ extern "C" {
+ #if !defined(LZO_COMPILE_TIME_ASSERT)
+ # if (LZO_CC_AZTECC)
+ # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];}
++# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul))
++# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));}
+ # elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+ # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break;
+ # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__)
+@@ -1897,11 +2023,16 @@ extern "C" {
+ # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];}
+ # endif
+ #endif
++#if (LZO_LANG_ASSEMBLER)
++# undef LZO_COMPILE_TIME_ASSERT_HEADER
++# define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/
++#else
+ LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1)
+ #if defined(__cplusplus)
+ extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) }
+ #endif
+ LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
++#endif
+ #if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64)
+ # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC)
+ # elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC)
+@@ -1968,7 +2099,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
+ #if !defined(LZO_HAVE_WINDOWS_H)
+ #if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64)
+ # if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000))
+-# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__)
++# elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)))
+ # elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul)))
+ # else
+ # define LZO_HAVE_WINDOWS_H 1
+@@ -1976,6 +2107,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3)
+ #endif
+ #endif
+ #endif
++#define LZO_SIZEOF_CHAR 1
+ #ifndef LZO_SIZEOF_SHORT
+ #if defined(SIZEOF_SHORT)
+ # define LZO_SIZEOF_SHORT (SIZEOF_SHORT)
+@@ -2174,12 +2306,12 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long))
+ # define LZO_WORDSIZE 8
+ #elif (LZO_ARCH_AMD64)
+ # define LZO_WORDSIZE 8
++#elif (LZO_ARCH_ARM64)
++# define LZO_WORDSIZE 8
+ #elif (LZO_ARCH_AVR)
+ # define LZO_WORDSIZE 1
+ #elif (LZO_ARCH_H8300)
+-# if defined(__NORMAL_MODE__)
+-# define LZO_WORDSIZE 4
+-# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
++# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+ # define LZO_WORDSIZE 4
+ # else
+ # define LZO_WORDSIZE 2
+@@ -2222,11 +2354,15 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8)
+ #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430)
+ # define LZO_SIZEOF_VOID_P 2
+ #elif (LZO_ARCH_H8300)
+-# if defined(__NORMAL_MODE__)
+-# define LZO_SIZEOF_VOID_P 2
+-# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
+-# define LZO_SIZEOF_VOID_P 4
++# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__)
++ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4)
++# if defined(__NORMAL_MODE__)
++# define LZO_SIZEOF_VOID_P 2
++# else
++# define LZO_SIZEOF_VOID_P 4
++# endif
+ # else
++ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2)
+ # define LZO_SIZEOF_VOID_P 2
+ # endif
+ # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4)
+@@ -2316,7 +2452,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+ # define LZO_ABI_LITTLE_ENDIAN 1
+-#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430)
++#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV)
+ # define LZO_ABI_LITTLE_ENDIAN 1
+ #elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU)
+ # define LZO_ABI_BIG_ENDIAN 1
+@@ -2330,10 +2466,14 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0)
++# define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__)
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__)
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32)
++# define LZO_ABI_LITTLE_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC)
+ # if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+ # error "unexpected configuration - check your compiler defines"
+@@ -2343,10 +2483,14 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_LITTLE_ENDIAN 1
+ # endif
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0)
++# define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__)
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__)
+ # define LZO_ABI_LITTLE_ENDIAN 1
++#elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32)
++# define LZO_ABI_LITTLE_ENDIAN 1
+ #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__)
+ # define LZO_ABI_BIG_ENDIAN 1
+ #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__)
+@@ -2388,6 +2532,12 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # define LZO_ABI_IP32L64 1
+ # define LZO_INFO_ABI_PM "ip32l64"
+ #endif
++#if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8)
++# define LZO_ABI_IP32W64 1
++# ifndef LZO_INFO_ABI_PM
++# define LZO_INFO_ABI_PM "ip32w64"
++# endif
++#endif
+ #if 0
+ #elif !defined(__LZO_LIBC_OVERRIDE)
+ #if (LZO_LIBC_NAKED)
+@@ -2475,20 +2625,43 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # endif
+ #elif (LZO_ARCH_ARM)
+ # if defined(__ARM_FEATURE_UNALIGNED)
++# if ((__ARM_FEATURE_UNALIGNED)+0)
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# endif
++# elif 1 && (LZO_ARCH_ARM_THUMB2)
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+ # ifndef LZO_OPT_UNALIGNED32
+ # define LZO_OPT_UNALIGNED32 1
+ # endif
+-# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7)
++# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+ # ifndef LZO_OPT_UNALIGNED32
+ # define LZO_OPT_UNALIGNED32 1
+ # endif
+-# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M)
++# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R))
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+@@ -2540,7 +2713,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ #elif (LZO_ARCH_POWERPC)
+ # define LZO_OPT_PREFER_PREINC 1
+ # define LZO_OPT_PREFER_PREDEC 1
+-# if (LZO_ABI_BIG_ENDIAN)
++# if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+ # endif
+@@ -2553,6 +2726,19 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ # endif
+ # endif
+ # endif
++#elif (LZO_ARCH_RISCV)
++# define LZO_OPT_AVOID_UINT_INDEX 1
++# ifndef LZO_OPT_UNALIGNED16
++# define LZO_OPT_UNALIGNED16 1
++# endif
++# ifndef LZO_OPT_UNALIGNED32
++# define LZO_OPT_UNALIGNED32 1
++# endif
++# if (LZO_WORDSIZE == 8)
++# ifndef LZO_OPT_UNALIGNED64
++# define LZO_OPT_UNALIGNED64 1
++# endif
++# endif
+ #elif (LZO_ARCH_S390)
+ # ifndef LZO_OPT_UNALIGNED16
+ # define LZO_OPT_UNALIGNED16 1
+@@ -2644,32 +2830,61 @@ LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t))
+ #if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0))
+ # error "missing defines for sizes"
+ #endif
++#define LZO_TYPEOF_CHAR 1u
++#define LZO_TYPEOF_SHORT 2u
++#define LZO_TYPEOF_INT 3u
++#define LZO_TYPEOF_LONG 4u
++#define LZO_TYPEOF_LONG_LONG 5u
++#define LZO_TYPEOF___INT8 17u
++#define LZO_TYPEOF___INT16 18u
++#define LZO_TYPEOF___INT32 19u
++#define LZO_TYPEOF___INT64 20u
++#define LZO_TYPEOF___INT128 21u
++#define LZO_TYPEOF___INT256 22u
++#define LZO_TYPEOF___MODE_QI 33u
++#define LZO_TYPEOF___MODE_HI 34u
++#define LZO_TYPEOF___MODE_SI 35u
++#define LZO_TYPEOF___MODE_DI 36u
++#define LZO_TYPEOF___MODE_TI 37u
++#define LZO_TYPEOF_CHAR_P 129u
+ #if !defined(lzo_llong_t)
+ #if (LZO_SIZEOF_LONG_LONG+0 > 0)
+-__lzo_gnuc_extension__ typedef long long lzo_llong_t__;
+-__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
++# if !(LZO_LANG_ASSEMBLER)
++ __lzo_gnuc_extension__ typedef long long lzo_llong_t__;
++ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
++# endif
+ # define lzo_llong_t lzo_llong_t__
+ # define lzo_ullong_t lzo_ullong_t__
+ #endif
+ #endif
+ #if !defined(lzo_int16e_t)
+-#if (LZO_SIZEOF_LONG == 2)
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T
++#endif
++#if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT)
+ # define lzo_int16e_t long
+ # define lzo_uint16e_t unsigned long
+-#elif (LZO_SIZEOF_INT == 2)
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG
++#elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT)
+ # define lzo_int16e_t int
+ # define lzo_uint16e_t unsigned int
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_SHORT == 2)
+ # define lzo_int16e_t short int
+ # define lzo_uint16e_t unsigned short int
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT
+ #elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM)
++# if !(LZO_LANG_ASSEMBLER)
+ typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__)));
+ typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__)));
++# endif
+ # define lzo_int16e_t lzo_int16e_hi_t__
+ # define lzo_uint16e_t lzo_uint16e_hi_t__
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI
+ #elif (LZO_SIZEOF___INT16 == 2)
+ # define lzo_int16e_t __int16
+ # define lzo_uint16e_t unsigned __int16
++# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16
+ #else
+ #endif
+ #endif
+@@ -2679,33 +2894,47 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T)
+ #endif
+ #if !defined(lzo_int32e_t)
+-#if (LZO_SIZEOF_LONG == 4)
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T
++#endif
++#if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT)
+ # define lzo_int32e_t long int
+ # define lzo_uint32e_t unsigned long int
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG
+ #elif (LZO_SIZEOF_INT == 4)
+ # define lzo_int32e_t int
+ # define lzo_uint32e_t unsigned int
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_SHORT == 4)
+ # define lzo_int32e_t short int
+ # define lzo_uint32e_t unsigned short int
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT
+ #elif (LZO_SIZEOF_LONG_LONG == 4)
+ # define lzo_int32e_t lzo_llong_t
+ # define lzo_uint32e_t lzo_ullong_t
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG
+ #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L)
++# if !(LZO_LANG_ASSEMBLER)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
++# endif
+ # define lzo_int32e_t lzo_int32e_si_t__
+ # define lzo_uint32e_t lzo_uint32e_si_t__
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI
+ #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L)
++# if !(LZO_LANG_ASSEMBLER)
+ typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__)));
+ typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__)));
++# endif
+ # define lzo_int32e_t lzo_int32e_si_t__
+ # define lzo_uint32e_t lzo_uint32e_si_t__
+ # define LZO_INT32_C(c) (c##LL)
+ # define LZO_UINT32_C(c) (c##ULL)
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI
+ #elif (LZO_SIZEOF___INT32 == 4)
+ # define lzo_int32e_t __int32
+ # define lzo_uint32e_t unsigned __int32
++# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32
+ #else
+ #endif
+ #endif
+@@ -2716,21 +2945,28 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #endif
+ #if !defined(lzo_int64e_t)
+ #if (LZO_SIZEOF___INT64 == 8)
+-# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64)
+-# define LZO_CFG_TYPE_PREFER___INT64 1
++# if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T)
++# define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64
+ # endif
+ #endif
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T
++#endif
++#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8)
++# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T
++#endif
+ #if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+ # define lzo_int64e_t int
+ # define lzo_uint64e_t unsigned int
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT
+-#elif (LZO_SIZEOF_LONG == 8)
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT
++#elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64)
+ # define lzo_int64e_t long int
+ # define lzo_uint64e_t unsigned long int
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG
+-#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64)
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG
++#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64)
+ # define lzo_int64e_t lzo_llong_t
+ # define lzo_uint64e_t lzo_ullong_t
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG
+ # if (LZO_CC_BORLANDC)
+ # define LZO_INT64_C(c) ((c) + 0ll)
+ # define LZO_UINT64_C(c) ((c) + 0ull)
+@@ -2741,10 +2977,10 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define LZO_INT64_C(c) (c##LL)
+ # define LZO_UINT64_C(c) (c##ULL)
+ # endif
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG
+ #elif (LZO_SIZEOF___INT64 == 8)
+ # define lzo_int64e_t __int64
+ # define lzo_uint64e_t unsigned __int64
++# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64
+ # if (LZO_CC_BORLANDC)
+ # define LZO_INT64_C(c) ((c) + 0i64)
+ # define LZO_UINT64_C(c) ((c) + 0ui64)
+@@ -2752,11 +2988,11 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define LZO_INT64_C(c) (c##i64)
+ # define LZO_UINT64_C(c) (c##ui64)
+ # endif
+-# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64
+ #else
+ #endif
+ #endif
+ #if defined(lzo_int64e_t)
++# define LZO_SIZEOF_LZO_INT64E_T 8
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T)
+ #endif
+@@ -2765,14 +3001,17 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int32l_t lzo_int32e_t
+ # define lzo_uint32l_t lzo_uint32e_t
+ # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T
++# define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T
+ #elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+ # define lzo_int32l_t int
+ # define lzo_uint32l_t unsigned int
+ # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT
+ #elif (LZO_SIZEOF_LONG >= 4)
+ # define lzo_int32l_t long int
+ # define lzo_uint32l_t unsigned long int
+ # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG
+ #else
+ # error "lzo_int32l_t"
+ #endif
+@@ -2786,6 +3025,7 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int64l_t lzo_int64e_t
+ # define lzo_uint64l_t lzo_uint64e_t
+ # define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T
++# define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T
+ #else
+ #endif
+ #endif
+@@ -2798,10 +3038,12 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int32f_t lzo_int64l_t
+ # define lzo_uint32f_t lzo_uint64l_t
+ # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T
+ #else
+ # define lzo_int32f_t lzo_int32l_t
+ # define lzo_uint32f_t lzo_uint32l_t
+ # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T
++# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T
+ #endif
+ #endif
+ #if 1
+@@ -2813,6 +3055,7 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ # define lzo_int64f_t lzo_int64l_t
+ # define lzo_uint64f_t lzo_uint64l_t
+ # define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T
+ #else
+ #endif
+ #endif
+@@ -2823,33 +3066,43 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #if !defined(lzo_intptr_t)
+ #if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16))
+ # define __LZO_INTPTR_T_IS_POINTER 1
+- typedef char* lzo_intptr_t;
+- typedef char* lzo_uintptr_t;
++# if !(LZO_LANG_ASSEMBLER)
++ typedef char * lzo_intptr_t;
++ typedef char * lzo_uintptr_t;
++# endif
+ # define lzo_intptr_t lzo_intptr_t
+ # define lzo_uintptr_t lzo_uintptr_t
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P
+ #elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4))
++# if !(LZO_LANG_ASSEMBLER)
+ typedef __w64 int lzo_intptr_t;
+ typedef __w64 unsigned int lzo_uintptr_t;
++# endif
+ # define lzo_intptr_t lzo_intptr_t
+ # define lzo_uintptr_t lzo_uintptr_t
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P)
+ # define lzo_intptr_t short
+ # define lzo_uintptr_t unsigned short
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT
+ #elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG)
+ # define lzo_intptr_t int
+ # define lzo_uintptr_t unsigned int
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT
+ #elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P)
+ # define lzo_intptr_t long
+ # define lzo_uintptr_t unsigned long
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG
+ #elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P)
+ # define lzo_intptr_t lzo_int64l_t
+ # define lzo_uintptr_t lzo_uint64l_t
+ # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T
+ #else
+ # error "lzo_intptr_t"
+ #endif
+@@ -2863,34 +3116,43 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER)
+ # define lzo_word_t lzo_uintptr_t
+ # define lzo_sword_t lzo_intptr_t
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_LONG)
+ # define lzo_word_t unsigned long
+ # define lzo_sword_t long
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_INT)
+ # define lzo_word_t unsigned int
+ # define lzo_sword_t int
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT)
+ # define lzo_word_t unsigned short
+ # define lzo_sword_t short
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT
+ #elif (LZO_WORDSIZE == 1)
+ # define lzo_word_t unsigned char
+ # define lzo_sword_t signed char
+-# define LZO_SIZEOF_LZO_WORD_T 1
++# define LZO_SIZEOF_LZO_WORD_T 1
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR
+ #elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T)
+ # define lzo_word_t lzo_uint64l_t
+ # define lzo_sword_t lzo_int64l_t
+-# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
++# define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T
+ #elif (LZO_ARCH_SPU) && (LZO_CC_GNUC)
+ #if 0
++# if !(LZO_LANG_ASSEMBLER)
+ typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__)));
+ typedef int lzo_sword_t __attribute__((__mode__(__V16QI__)));
++# endif
+ # define lzo_word_t lzo_word_t
+ # define lzo_sword_t lzo_sword_t
+ # define LZO_SIZEOF_LZO_WORD_T 16
++# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI
+ #endif
+ #else
+ # error "lzo_word_t"
+@@ -2905,6 +3167,7 @@ __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__;
+ #define lzo_int8_t signed char
+ #define lzo_uint8_t unsigned char
+ #define LZO_SIZEOF_LZO_INT8_T 1
++#define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t))
+ #endif
+@@ -2912,6 +3175,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t))
+ #define lzo_int16_t lzo_int16e_t
+ #define lzo_uint16_t lzo_uint16e_t
+ #define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T
++#define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t))
+ #endif
+@@ -2919,6 +3183,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t))
+ #define lzo_int32_t lzo_int32e_t
+ #define lzo_uint32_t lzo_uint32e_t
+ #define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T
++#define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t))
+ #endif
+@@ -2926,6 +3191,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t))
+ #define lzo_int64_t lzo_int64e_t
+ #define lzo_uint64_t lzo_uint64e_t
+ #define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T
++#define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t))
+ #endif
+@@ -2933,6 +3199,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t))
+ #define lzo_int_least32_t lzo_int32l_t
+ #define lzo_uint_least32_t lzo_uint32l_t
+ #define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T
++#define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t))
+ #endif
+@@ -2940,6 +3207,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_leas
+ #define lzo_int_least64_t lzo_int64l_t
+ #define lzo_uint_least64_t lzo_uint64l_t
+ #define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T
++#define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t))
+ #endif
+@@ -2947,6 +3215,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_leas
+ #define lzo_int_fast32_t lzo_int32f_t
+ #define lzo_uint_fast32_t lzo_uint32f_t
+ #define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T
++#define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t))
+ #endif
+@@ -2954,6 +3223,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast3
+ #define lzo_int_fast64_t lzo_int64f_t
+ #define lzo_uint_fast64_t lzo_uint64f_t
+ #define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T
++#define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t))
+ #endif
+@@ -3020,7 +3290,7 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast6
+ #undef LZO_HAVE_CONFIG_H
+ #include "minilzo.h"
+
+-#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2080)
++#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x20a0)
+ # error "version mismatch in miniLZO source files"
+ #endif
+
+@@ -3042,13 +3312,23 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast6
+ #if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED)
+ # error "include this file first"
+ #endif
+-#include "lzo/lzoconf.h"
++#if defined(LZO_CFG_BUILD_DLL) && (LZO_CFG_BUILD_DLL+0) && !defined(__LZO_EXPORT1) && !defined(__LZO_EXPORT2) && 0
++#ifndef __LZODEFS_H_INCLUDED
++#if defined(LZO_HAVE_CONFIG_H)
++# include <config.h>
++#endif
++#include <limits.h>
++#include <stddef.h>
++#include <lzo/lzodefs.h>
++#endif
++#endif
++#include <lzo/lzoconf.h>
+ #if defined(LZO_CFG_EXTRA_CONFIG_HEADER2)
+ # include LZO_CFG_EXTRA_CONFIG_HEADER2
+ #endif
+ #endif
+
+-#if (LZO_VERSION < 0x2080) || !defined(__LZOCONF_H_INCLUDED)
++#if !defined(__LZOCONF_H_INCLUDED) || (LZO_VERSION+0 != 0x20a0)
+ # error "version mismatch"
+ #endif
+
+@@ -3065,6 +3345,9 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast6
+ #if (LZO_CC_MSC && (_MSC_VER >= 1800))
+ # pragma warning(disable: 4746)
+ #endif
++#if (LZO_CC_INTELC && (__INTEL_COMPILER >= 900))
++# pragma warning(disable: 1684)
++#endif
+
+ #if (LZO_CC_SUNPROC)
+ #if !defined(__cplusplus)
+@@ -3074,6 +3357,32 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast6
+ #endif
+ #endif
+
++#if !defined(__LZO_NOEXPORT1)
++# define __LZO_NOEXPORT1 /*empty*/
++#endif
++#if !defined(__LZO_NOEXPORT2)
++# define __LZO_NOEXPORT2 /*empty*/
++#endif
++
++#if 1
++# define LZO_PUBLIC_DECL(r) LZO_EXTERN(r)
++#endif
++#if 1
++# define LZO_PUBLIC_IMPL(r) LZO_PUBLIC(r)
++#endif
++#if !defined(LZO_LOCAL_DECL)
++# define LZO_LOCAL_DECL(r) __LZO_EXTERN_C LZO_LOCAL_IMPL(r)
++#endif
++#if !defined(LZO_LOCAL_IMPL)
++# define LZO_LOCAL_IMPL(r) __LZO_NOEXPORT1 r __LZO_NOEXPORT2 __LZO_CDECL
++#endif
++#if 1
++# define LZO_STATIC_DECL(r) LZO_PRIVATE(r)
++#endif
++#if 1
++# define LZO_STATIC_IMPL(r) LZO_PRIVATE(r)
++#endif
++
+ #if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING)
+ #elif 1
+ # include <string.h>
+@@ -3269,6 +3578,9 @@ __lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v)
+ #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4)
+ unsigned r; r = (unsigned) __builtin_clz(v); return r;
+ #define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v))
++#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8)
++ unsigned r; r = (unsigned) __builtin_clzl(v); return r ^ 32;
++#define lzo_bitops_ctlz32(v) (((unsigned) __builtin_clzl(v)) ^ 32)
+ #else
+ LZO_UNUSED(v); return 0;
+ #endif
+@@ -3338,25 +3650,20 @@ __lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v)
+ }
+ #endif
+
+-#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+-static void __attribute__((__unused__))
+-#else
+-__lzo_static_forceinline void
+-#endif
+-lzo_bitops_unused_funcs(void)
++lzo_unused_funcs_impl(void, lzo_bitops_unused_funcs)(void)
+ {
++ LZO_UNUSED_FUNC(lzo_bitops_unused_funcs);
+ LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func);
+ LZO_UNUSED_FUNC(lzo_bitops_cttz32_func);
+ #if defined(lzo_uint64_t)
+ LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func);
+ LZO_UNUSED_FUNC(lzo_bitops_cttz64_func);
+ #endif
+- LZO_UNUSED_FUNC(lzo_bitops_unused_funcs);
+ }
+
+ #if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED)
+-#ifndef __lzo_memops_tcheck
+-#define __lzo_memops_tcheck(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b))
++#if !defined(lzo_memops_tcheck__) && 0
++#define lzo_memops_tcheck__(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b))
+ #endif
+ #endif
+ #ifndef lzo_memops_TU0p
+@@ -3473,9 +3780,9 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2)
+ #define LZO_MEMOPS_COPY2(dd,ss) \
+ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)
+-#elif defined(__lzo_memops_tcheck)
++#elif defined(lzo_memops_tcheck__)
+ #define LZO_MEMOPS_COPY2(dd,ss) \
+- LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU2,2,1)) { \
++ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU2,2,1)) { \
+ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \
+ } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END
+ #else
+@@ -3485,9 +3792,9 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2)
+ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4)
+ #define LZO_MEMOPS_COPY4(dd,ss) \
+ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)
+-#elif defined(__lzo_memops_tcheck)
++#elif defined(lzo_memops_tcheck__)
+ #define LZO_MEMOPS_COPY4(dd,ss) \
+- LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU4,4,1)) { \
++ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU4,4,1)) { \
+ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \
+ } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END
+ #else
+@@ -3504,9 +3811,9 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8)
+ #elif (LZO_OPT_UNALIGNED32)
+ #define LZO_MEMOPS_COPY8(dd,ss) \
+ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END
+-#elif defined(__lzo_memops_tcheck)
++#elif defined(lzo_memops_tcheck__)
+ #define LZO_MEMOPS_COPY8(dd,ss) \
+- LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU8,8,1)) { \
++ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU8,8,1)) { \
+ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \
+ } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END
+ #else
+@@ -3540,7 +3847,7 @@ __lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss)
+ return v;
+ }
+ #if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
+-#define LZO_MEMOPS_GET_LE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)
++#define LZO_MEMOPS_GET_LE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss))
+ #else
+ #define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss)
+ #endif
+@@ -3562,13 +3869,13 @@ __lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss)
+ return v;
+ }
+ #if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN)
+-#define LZO_MEMOPS_GET_LE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)
++#define LZO_MEMOPS_GET_LE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss))
+ #else
+ #define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss)
+ #endif
+
+ #if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN)
+-#define LZO_MEMOPS_GET_LE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)
++#define LZO_MEMOPS_GET_LE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss))
+ #endif
+
+ __lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss)
+@@ -3578,7 +3885,8 @@ __lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss)
+ return v;
+ }
+ #if (LZO_OPT_UNALIGNED16)
+-#define LZO_MEMOPS_GET_NE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)
++LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2)
++#define LZO_MEMOPS_GET_NE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss))
+ #else
+ #define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss)
+ #endif
+@@ -3590,13 +3898,15 @@ __lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss)
+ return v;
+ }
+ #if (LZO_OPT_UNALIGNED32)
+-#define LZO_MEMOPS_GET_NE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)
++LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4)
++#define LZO_MEMOPS_GET_NE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss))
+ #else
+ #define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss)
+ #endif
+
+ #if (LZO_OPT_UNALIGNED64)
+-#define LZO_MEMOPS_GET_NE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)
++LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8)
++#define LZO_MEMOPS_GET_NE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss))
+ #endif
+
+ __lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv)
+@@ -3661,13 +3971,9 @@ __lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv)
+ #define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv)
+ #endif
+
+-#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+-static void __attribute__((__unused__))
+-#else
+-__lzo_static_forceinline void
+-#endif
+-lzo_memops_unused_funcs(void)
++lzo_unused_funcs_impl(void, lzo_memops_unused_funcs)(void)
+ {
++ LZO_UNUSED_FUNC(lzo_memops_unused_funcs);
+ LZO_UNUSED_FUNC(lzo_memops_get_le16);
+ LZO_UNUSED_FUNC(lzo_memops_get_le32);
+ LZO_UNUSED_FUNC(lzo_memops_get_ne16);
+@@ -3676,7 +3982,6 @@ lzo_memops_unused_funcs(void)
+ LZO_UNUSED_FUNC(lzo_memops_put_le32);
+ LZO_UNUSED_FUNC(lzo_memops_put_ne16);
+ LZO_UNUSED_FUNC(lzo_memops_put_ne32);
+- LZO_UNUSED_FUNC(lzo_memops_unused_funcs);
+ }
+
+ #endif
+@@ -3889,11 +4194,16 @@ __lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+ #error "__LZO_UINTPTR_T_IS_POINTER is unsupported"
+ #else
+ lzo_uintptr_t p, n;
++ if (size < 2) return 0;
+ p = __lzo_ptr_linear(ptr);
++#if 0
+ n = (((p + size - 1) / size) * size) - p;
++#else
++ if ((size & (size - 1)) != 0)
++ return 0;
++ n = size; n = ((p + n - 1) & ~(n - 1)) - p;
++#endif
+ #endif
+-
+- assert(size > 0);
+ assert((long)n >= 0);
+ assert(n <= size);
+ return (unsigned)n;
+@@ -3906,23 +4216,25 @@ __lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+ * keep this copyright string in the executable of your product.
+ */
+
+-static const char __lzo_copyright[] =
++static const char lzo_copyright_[] =
+ #if !defined(__LZO_IN_MINLZO)
+ LZO_VERSION_STRING;
+ #else
+ "\r\n\n"
+ "LZO data compression library.\n"
+- "$Copyright: LZO Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer\n"
++ "$Copyright: LZO Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\n"
+ "<markus@oberhumer.com>\n"
+ "http://www.oberhumer.com $\n\n"
+ "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n"
+ "$Info: " LZO_INFO_STRING " $\n";
+ #endif
++static const char lzo_version_string_[] = LZO_VERSION_STRING;
++static const char lzo_version_date_[] = LZO_VERSION_DATE;
+
+ LZO_PUBLIC(const lzo_bytep)
+ lzo_copyright(void)
+ {
+- return (const lzo_bytep) __lzo_copyright;
++ return (const lzo_bytep) lzo_copyright_;
+ }
+
+ LZO_PUBLIC(unsigned)
+@@ -3934,25 +4246,25 @@ lzo_version(void)
+ LZO_PUBLIC(const char *)
+ lzo_version_string(void)
+ {
+- return LZO_VERSION_STRING;
++ return lzo_version_string_;
+ }
+
+ LZO_PUBLIC(const char *)
+ lzo_version_date(void)
+ {
+- return LZO_VERSION_DATE;
++ return lzo_version_date_;
+ }
+
+ LZO_PUBLIC(const lzo_charp)
+ _lzo_version_string(void)
+ {
+- return LZO_VERSION_STRING;
++ return lzo_version_string_;
+ }
+
+ LZO_PUBLIC(const lzo_charp)
+ _lzo_version_date(void)
+ {
+- return LZO_VERSION_DATE;
++ return lzo_version_date_;
+ }
+
+ #define LZO_BASE 65521u
+@@ -4324,7 +4636,7 @@ int __far __pascal LibMain ( int a, short b, short c, long d )
+ #endif
+
+ #if !defined(__LZO_IN_MINILZO)
+-#include "lzo/lzo1x.h"
++#include <lzo/lzo1x.h>
+ #endif
+
+ #ifndef LZO_EOF_CODE
+@@ -4516,7 +4828,7 @@ extern "C" {
+
+ #if !defined(DVAL_ASSERT)
+ #if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG)
+-#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM)
++#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+ static void __attribute__((__unused__))
+ #else
+ static void
+diff --git a/grub-core/lib/minilzo/minilzo.h b/grub-core/lib/minilzo/minilzo.h
+index 793745467..c1c229757 100644
+--- a/grub-core/lib/minilzo/minilzo.h
++++ b/grub-core/lib/minilzo/minilzo.h
+@@ -2,7 +2,7 @@
+
+ This file is part of the LZO real-time data compression library.
+
+- Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
++ Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library is free software; you can redistribute it and/or
+@@ -32,15 +32,25 @@
+ */
+
+
+-#ifndef __MINILZO_H
+-#define __MINILZO_H 1
++#ifndef __MINILZO_H_INCLUDED
++#define __MINILZO_H_INCLUDED 1
+
+-#define MINILZO_VERSION 0x2080
++#define MINILZO_VERSION 0x20a0 /* 2.10 */
+
+-#ifdef __LZOCONF_H
++#if defined(__LZOCONF_H_INCLUDED)
+ # error "you cannot use both LZO and miniLZO"
+ #endif
+
++/* internal Autoconf configuration file - only used when building miniLZO */
++#ifdef MINILZO_HAVE_CONFIG_H
++# include <config.h>
++#endif
++#include <limits.h>
++#include <stddef.h>
++
++#ifndef __LZODEFS_H_INCLUDED
++#include "lzodefs.h"
++#endif
+ #undef LZO_HAVE_CONFIG_H
+ #include "lzoconf.h"
+
+@@ -92,3 +102,5 @@ lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
+
+ #endif /* already included */
+
++
++/* vim:set ts=4 sw=4 et: */
diff --git a/debian/patches/mkconfig-loopback.patch b/debian/patches/mkconfig-loopback.patch
new file mode 100644
index 0000000..686117f
--- /dev/null
+++ b/debian/patches/mkconfig-loopback.patch
@@ -0,0 +1,96 @@
+From 3f0c88e2ffa15cfb34641397cc9bdbe39085f1ba Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:13:00 +0000
+Subject: Handle filesystems loop-mounted on file images
+
+Improve prepare_grub_to_access_device to emit appropriate commands for
+such filesystems, and ignore them in Linux grub.d scripts.
+
+This is needed for Ubuntu's Wubi installation method.
+
+This patch isn't inherently Debian/Ubuntu-specific. losetup and
+/proc/mounts are Linux-specific, though, so we might need to refine this
+before sending it upstream. The changes to the Linux grub.d scripts
+might be better handled by integrating 10_lupin properly instead.
+
+Patch-Name: mkconfig-loopback.patch
+---
+ util/grub-mkconfig_lib.in | 24 ++++++++++++++++++++++++
+ util/grub.d/10_linux.in | 5 +++++
+ util/grub.d/20_linux_xen.in | 5 +++++
+ 3 files changed, 34 insertions(+)
+
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index 17f9b3e58..e62cfc22b 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -133,6 +133,22 @@ prepare_grub_to_access_device ()
+ esac
+ done
+
++ loop_file=
++ case $1 in
++ /dev/loop/*|/dev/loop[0-9])
++ grub_loop_device="${1#/dev/}"
++ loop_file=`losetup "$1" | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
++ case $loop_file in
++ /dev/*) ;;
++ *)
++ loop_device="$1"
++ shift
++ set -- `"${grub_probe}" --target=device "${loop_file}"` "$@"
++ ;;
++ esac
++ ;;
++ esac
++
+ # Abstraction modules aren't auto-loaded.
+ abstraction="`"${grub_probe}" --device $@ --target=abstraction`"
+ for module in ${abstraction} ; do
+@@ -169,6 +185,14 @@ prepare_grub_to_access_device ()
+ fi
+ fi
+ IFS="$old_ifs"
++
++ if [ "x${loop_file}" != x ]; then
++ loop_mountpoint="$(awk '"'${loop_file}'" ~ "^"$2 && $2 != "/" { print $2 }' /proc/mounts | tail -n1)"
++ if [ "x${loop_mountpoint}" != x ]; then
++ echo "loopback ${grub_loop_device} ${loop_file#$loop_mountpoint}"
++ echo "set root=(${grub_loop_device})"
++ fi
++ fi
+ }
+
+ grub_get_device_id ()
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 9446d6833..46696dd66 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -40,6 +40,11 @@ fi
+ case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
++ # We can't cope with devices loop-mounted from files here.
++ case ${GRUB_DEVICE} in
++ /dev/*) ;;
++ *) exit 0 ;;
++ esac
+ ;;
+ esac
+
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index 3b1f47049..7620a14fa 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -40,6 +40,11 @@ fi
+ case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
++ # We can't cope with devices loop-mounted from files here.
++ case ${GRUB_DEVICE} in
++ /dev/*) ;;
++ *) exit 0 ;;
++ esac
+ ;;
+ esac
+
diff --git a/debian/patches/mkconfig-nonexistent-loopback.patch b/debian/patches/mkconfig-nonexistent-loopback.patch
new file mode 100644
index 0000000..9c55c1d
--- /dev/null
+++ b/debian/patches/mkconfig-nonexistent-loopback.patch
@@ -0,0 +1,55 @@
+From 989f83d664999deeb28d03a847e8f00a28639d7d Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:08 +0000
+Subject: Avoid getting confused by inaccessible loop device backing paths
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/938724
+Forwarded: no
+Last-Update: 2021-09-24
+
+Patch-Name: mkconfig-nonexistent-loopback.patch
+---
+ util/grub-mkconfig_lib.in | 2 +-
+ util/grub.d/30_os-prober.in | 9 +++++----
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index e62cfc22b..b6a1d7dec 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -143,7 +143,7 @@ prepare_grub_to_access_device ()
+ *)
+ loop_device="$1"
+ shift
+- set -- `"${grub_probe}" --target=device "${loop_file}"` "$@"
++ set -- `"${grub_probe}" --target=device "${loop_file}"` "$@" || return 0
+ ;;
+ esac
+ ;;
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 37d5f05b5..e2ec80eb9 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -222,6 +222,11 @@ EOF
+ LINITRD="${LINITRD#/boot}"
+ fi
+
++ if [ -z "${prepare_boot_cache}" ]; then
++ prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"
++ [ "${prepare_boot_cache}" ] || continue
++ fi
++
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true
+ counter=1
+@@ -233,10 +238,6 @@ EOF
+ fi
+ used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'"
+
+- if [ -z "${prepare_boot_cache}" ]; then
+- prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"
+- fi
+-
+ # The GRUB_DISABLE_SUBMENU option used to be different than others since it was
+ # mentioned in the documentation that has to be set to 'y' instead of 'true' to
+ # enable it. This caused a lot of confusion to users that set the option to 'y',
diff --git a/debian/patches/mkconfig-other-inits.patch b/debian/patches/mkconfig-other-inits.patch
new file mode 100644
index 0000000..75bf4e4
--- /dev/null
+++ b/debian/patches/mkconfig-other-inits.patch
@@ -0,0 +1,90 @@
+From f8382052a32839fbc3715d1c5076f1b6bbcbcb63 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sat, 3 Jan 2015 12:04:59 +0000
+Subject: Generate alternative init entries in advanced menu
+
+Add fallback boot entries for alternative installed init systems. Based
+on patches from Michael Biebl and Didier Roche.
+
+Bug-Debian: https://bugs.debian.org/757298
+Bug-Debian: https://bugs.debian.org/773173
+Forwarded: no
+Last-Update: 2017-06-23
+
+Patch-Name: mkconfig-other-inits.patch
+---
+ util/grub.d/10_linux.in | 10 ++++++++++
+ util/grub.d/20_linux_xen.in | 11 +++++++++++
+ 2 files changed, 21 insertions(+)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 635c609d6..4e09797f8 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -32,6 +32,7 @@ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+
+ CLASS="--class gnu-linux --class gnu --class os"
++SUPPORTED_INITS="sysvinit:/lib/sysvinit/init systemd:/lib/systemd/systemd upstart:/sbin/upstart"
+
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS=GNU/Linux
+@@ -127,6 +128,8 @@ linux_entry ()
+ case $type in
+ recovery)
+ title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")" ;;
++ init-*)
++ title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "${type#init-}")" ;;
+ *)
+ title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
+ esac
+@@ -389,6 +392,13 @@ while [ "x$list" != "x" ] ; do
+
+ linux_entry "${OS}" "${version}" advanced \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
++ for supported_init in ${SUPPORTED_INITS}; do
++ init_path="${supported_init#*:}"
++ if [ -x "${init_path}" ] && [ "$(readlink -f /sbin/init)" != "$(readlink -f "${init_path}")" ]; then
++ linux_entry "${OS}" "${version}" "init-${supported_init%%:*}" \
++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} init=${init_path}"
++ fi
++ done
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" recovery \
+ "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index 64e26e4b4..d99751a94 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -27,6 +27,7 @@ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+
+ CLASS="--class gnu-linux --class gnu --class os --class xen"
++SUPPORTED_INITS="sysvinit:/lib/sysvinit/init systemd:/lib/systemd/systemd upstart:/sbin/upstart"
+
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS=GNU/Linux
+@@ -123,6 +124,8 @@ linux_entry_xsm ()
+ if [ x$type != xsimple ] ; then
+ if [ x$type = xrecovery ] ; then
+ title="$(gettext_printf "%s, with Xen %s and Linux %s (%s)" "${os}" "${xen_version}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
++ elif [ "${type#init-}" != "$type" ] ; then
++ title="$(gettext_printf "%s, with Xen %s and Linux %s (%s)" "${os}" "${xen_version}" "${version}" "${type#init-}")"
+ else
+ title="$(gettext_printf "%s, with Xen %s and Linux %s" "${os}" "${xen_version}" "${version}")"
+ fi
+@@ -346,6 +349,14 @@ while [ "x${xen_list}" != "x" ] ; do
+
+ linux_entry "${OS}" "${version}" "${xen_version}" advanced \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}"
++ for supported_init in ${SUPPORTED_INITS}; do
++ init_path="${supported_init#*:}"
++ if [ -x "${init_path}" ] && [ "$(readlink -f /sbin/init)" != "$(readlink -f "${init_path}")" ]; then
++ linux_entry "${OS}" "${version}" "${xen_version}" "init-${supported_init%%:*}" \
++ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} init=${init_path}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}"
++
++ fi
++ done
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" "${xen_version}" recovery \
+ "single ${GRUB_CMDLINE_LINUX}" "${GRUB_CMDLINE_XEN}"
diff --git a/debian/patches/mkconfig-recovery-title.patch b/debian/patches/mkconfig-recovery-title.patch
new file mode 100644
index 0000000..74c8b9e
--- /dev/null
+++ b/debian/patches/mkconfig-recovery-title.patch
@@ -0,0 +1,130 @@
+From fd81fffa2d498d66dce65b50da2532690c806ea4 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:33 +0000
+Subject: Add GRUB_RECOVERY_TITLE option
+
+This allows the controversial "recovery mode" text to be customised.
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1240360
+Forwarded: no
+Last-Update: 2013-12-25
+
+Patch-Name: mkconfig-recovery-title.patch
+---
+ docs/grub.texi | 5 +++++
+ util/grub-mkconfig.in | 7 ++++++-
+ util/grub.d/10_hurd.in | 4 ++--
+ util/grub.d/10_kfreebsd.in | 2 +-
+ util/grub.d/10_linux.in | 2 +-
+ util/grub.d/10_netbsd.in | 2 +-
+ util/grub.d/20_linux_xen.in | 2 +-
+ 7 files changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 0b58dafb2..86e46f33b 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -1577,6 +1577,11 @@ a console is restricted or limited.
+ This option is only effective when GRUB was configured with the
+ @option{--enable-quick-boot} option.
+
++@item GRUB_RECOVERY_TITLE
++This option sets the English text of the string that will be displayed in
++parentheses to indicate that a boot option is provided to help users recover
++a broken system. The default is "recovery mode".
++
+ @end table
+
+ The following options are still accepted for compatibility with existing
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index fa9c53a92..0d39c8f05 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -201,6 +201,10 @@ GRUB_ACTUAL_DEFAULT="$GRUB_DEFAULT"
+
+ if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub_editenv}" - list | sed -n '/^saved_entry=/ s,^saved_entry=,,p'`" ; fi
+
++if [ "x${GRUB_RECOVERY_TITLE}" = "x" ]; then
++ GRUB_RECOVERY_TITLE="recovery mode"
++fi
++
+
+ # These are defined in this script, export them here so that user can
+ # override them.
+@@ -257,7 +261,8 @@ export GRUB_DEFAULT \
+ GRUB_BADRAM \
+ GRUB_OS_PROBER_SKIP_LIST \
+ GRUB_DISABLE_SUBMENU \
+- GRUB_RECORDFAIL_TIMEOUT
++ GRUB_RECORDFAIL_TIMEOUT \
++ GRUB_RECOVERY_TITLE
+
+ if test "x${grub_cfg}" != "x"; then
+ rm -f "${grub_cfg}.new"
+diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
+index 3663d360e..8f6041894 100644
+--- a/util/grub.d/10_hurd.in
++++ b/util/grub.d/10_hurd.in
+@@ -88,8 +88,8 @@ hurd_entry () {
+
+ if [ x$type != xsimple ] ; then
+ if [ x$type = xrecovery ] ; then
+- title="$(gettext_printf "%s, with Hurd %s (recovery mode)" "${OS}" "${kernel_base}")"
+- oldtitle="$OS using $kernel_base (recovery mode)"
++ title="$(gettext_printf "%s, with Hurd %s (%s)" "${OS}" "${kernel_base}" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
++ oldtitle="$OS using $kernel_base ($GRUB_RECOVERY_TITLE)"
+ else
+ title="$(gettext_printf "%s, with Hurd %s" "${OS}" "${kernel_base}")"
+ oldtitle="$OS using $kernel_base"
+diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in
+index 199b20e16..bbd63cf74 100644
+--- a/util/grub.d/10_kfreebsd.in
++++ b/util/grub.d/10_kfreebsd.in
+@@ -76,7 +76,7 @@ kfreebsd_entry ()
+ fi
+ if [ x$type != xsimple ] ; then
+ if [ x$type = xrecovery ] ; then
+- title="$(gettext_printf "%s, with kFreeBSD %s (recovery mode)" "${os}" "${version}")"
++ title="$(gettext_printf "%s, with kFreeBSD %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+ else
+ title="$(gettext_printf "%s, with kFreeBSD %s" "${os}" "${version}")"
+ fi
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 64204c216..f88a2de10 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -126,7 +126,7 @@ linux_entry ()
+ if [ x$type != xsimple ] ; then
+ case $type in
+ recovery)
+- title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;;
++ title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")" ;;
+ *)
+ title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
+ esac
+diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
+index dc0cd1b17..336895012 100644
+--- a/util/grub.d/10_netbsd.in
++++ b/util/grub.d/10_netbsd.in
+@@ -102,7 +102,7 @@ netbsd_entry ()
+
+ if [ x$type != xsimple ] ; then
+ if [ x$type = xrecovery ] ; then
+- title="$(gettext_printf "%s, with kernel %s (via %s, recovery mode)" "${OS}" "$(echo ${kernel} | sed -e 's,^.*/,,')" "${loader}")"
++ title="$(gettext_printf "%s, with kernel %s (via %s, %s)" "${OS}" "$(echo ${kernel} | sed -e 's,^.*/,,')" "${loader}" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+ else
+ title="$(gettext_printf "%s, with kernel %s (via %s)" "${OS}" "$(echo ${kernel} | sed -e 's,^.*/,,')" "${loader}")"
+ fi
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index 7620a14fa..64e26e4b4 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -122,7 +122,7 @@ linux_entry_xsm ()
+ fi
+ if [ x$type != xsimple ] ; then
+ if [ x$type = xrecovery ] ; then
+- title="$(gettext_printf "%s, with Xen %s and Linux %s (recovery mode)" "${os}" "${xen_version}" "${version}")"
++ title="$(gettext_printf "%s, with Xen %s and Linux %s (%s)" "${os}" "${xen_version}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+ else
+ title="$(gettext_printf "%s, with Xen %s and Linux %s" "${os}" "${xen_version}" "${version}")"
+ fi
diff --git a/debian/patches/mkconfig-signed-kernel.patch b/debian/patches/mkconfig-signed-kernel.patch
new file mode 100644
index 0000000..aa93fad
--- /dev/null
+++ b/debian/patches/mkconfig-signed-kernel.patch
@@ -0,0 +1,48 @@
+From 9eefe03f4b52e65cb4f372e0ff12a2b68cada425 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:21 +0000
+Subject: Generate configuration for signed UEFI kernels if available
+
+Forwarded: no
+Last-Update: 2013-12-25
+
+Patch-Name: mkconfig-signed-kernel.patch
+---
+ util/grub.d/10_linux.in | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 1603a75a7..1b8c6e146 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -161,8 +161,16 @@ linux_entry ()
+ message="$(gettext_printf "Loading Linux %s ..." ${version})"
+ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
++EOF
++ if test -d /sys/firmware/efi && test -e "${linux}.efi.signed"; then
++ sed "s/^/$submenu_indentation/" << EOF
++ linux ${rel_dirname}/${basename}.efi.signed root=${linux_root_device_thisversion} ro ${args}
++EOF
++ else
++ sed "s/^/$submenu_indentation/" << EOF
+ linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
++ fi
+ if test -n "${initrd}" ; then
+ # TRANSLATORS: ramdisk isn't identifier. Should be translated.
+ message="$(gettext_printf "Loading initial ramdisk ...")"
+@@ -214,6 +222,13 @@ submenu_indentation=""
+ is_top_level=true
+ while [ "x$list" != "x" ] ; do
+ linux=`version_find_latest $list`
++ case $linux in
++ *.efi.signed)
++ # We handle these in linux_entry.
++ list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
++ continue
++ ;;
++ esac
+ gettext_printf "Found linux image: %s\n" "$linux" >&2
+ basename=`basename $linux`
+ dirname=`dirname $linux`
diff --git a/debian/patches/mkconfig-ubuntu-distributor.patch b/debian/patches/mkconfig-ubuntu-distributor.patch
new file mode 100644
index 0000000..8ec05e0
--- /dev/null
+++ b/debian/patches/mkconfig-ubuntu-distributor.patch
@@ -0,0 +1,37 @@
+From 84938bc37ee1cfabf84915ad4b6c8904b4770ef6 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <Mario_Limonciello@dell.com>
+Date: Mon, 13 Jan 2014 12:13:14 +0000
+Subject: Remove GNU/Linux from default distributor string for Ubuntu
+
+Ubuntu is called "Ubuntu", not "Ubuntu GNU/Linux".
+
+Author: Colin Watson <cjwatson@debian.org>
+Author: Harald Sitter <apachelogger@kubuntu.org>
+Forwarded: not-needed
+Last-Update: 2013-12-25
+
+Patch-Name: mkconfig-ubuntu-distributor.patch
+---
+ util/grub.d/10_linux.in | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index f215e3213..1603a75a7 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -32,7 +32,14 @@ CLASS="--class gnu-linux --class gnu --class os"
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS=GNU/Linux
+ else
+- OS="${GRUB_DISTRIBUTOR} GNU/Linux"
++ case ${GRUB_DISTRIBUTOR} in
++ Ubuntu|Kubuntu)
++ OS="${GRUB_DISTRIBUTOR}"
++ ;;
++ *)
++ OS="${GRUB_DISTRIBUTOR} GNU/Linux"
++ ;;
++ esac
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+ fi
+
diff --git a/debian/patches/mkconfig-ubuntu-recovery.patch b/debian/patches/mkconfig-ubuntu-recovery.patch
new file mode 100644
index 0000000..1fa5bde
--- /dev/null
+++ b/debian/patches/mkconfig-ubuntu-recovery.patch
@@ -0,0 +1,107 @@
+From 13c9a7101d2611bbc02b464ef4e32b02cfc7860b Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:06 +0000
+Subject: "single" -> "recovery" when friendly-recovery is installed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If configured with --enable-ubuntu-recovery, also set nomodeset for
+recovery mode, and disable 'set gfxpayload=keep' even if the system
+normally supports it. See
+https://launchpad.net/ubuntu/+spec/desktop-o-xorg-tools-and-processes.
+
+Author: Stéphane Graber <stgraber@ubuntu.com>
+Forwarded: no
+Last-Update: 2013-12-25
+
+Patch-Name: mkconfig-ubuntu-recovery.patch
+---
+ configure.ac | 11 +++++++++++
+ util/grub.d/10_linux.in | 16 ++++++++++++++--
+ util/grub.d/30_os-prober.in | 2 +-
+ 3 files changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 7517fc49d..74778a6f8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1904,6 +1904,17 @@ fi
+ AC_SUBST([LIBZFS])
+ AC_SUBST([LIBNVPAIR])
+
++AC_ARG_ENABLE([ubuntu-recovery],
++ [AS_HELP_STRING([--enable-ubuntu-recovery],
++ [adjust boot options for the Ubuntu recovery mode (default=no)])],
++ [], [enable_ubuntu_recovery=no])
++if test x"$enable_ubuntu_recovery" = xyes ; then
++ UBUNTU_RECOVERY=1
++else
++ UBUNTU_RECOVERY=0
++fi
++AC_SUBST([UBUNTU_RECOVERY])
++
+ LIBS=""
+
+ AC_SUBST([FONT_SOURCE])
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 46696dd66..f215e3213 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -20,6 +20,7 @@ set -e
+ prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ datarootdir="@datarootdir@"
++ubuntu_recovery="@UBUNTU_RECOVERY@"
+
+ . "$pkgdatadir/grub-mkconfig_lib"
+
+@@ -84,6 +85,15 @@ esac
+
+ title_correction_code=
+
++if [ -x /lib/recovery-mode/recovery-menu ]; then
++ GRUB_CMDLINE_LINUX_RECOVERY=recovery
++else
++ GRUB_CMDLINE_LINUX_RECOVERY=single
++fi
++if [ "$ubuntu_recovery" = 1 ]; then
++ GRUB_CMDLINE_LINUX_RECOVERY="$GRUB_CMDLINE_LINUX_RECOVERY nomodeset"
++fi
++
+ linux_entry ()
+ {
+ os="$1"
+@@ -123,7 +133,9 @@ linux_entry ()
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+ fi
+- echo " set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
++ if [ "$ubuntu_recovery" = 0 ] || [ x$type != xrecovery ]; then
++ echo " set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
++ fi
+ fi
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
+@@ -288,7 +300,7 @@ while [ "x$list" != "x" ] ; do
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" recovery \
+- "single ${GRUB_CMDLINE_LINUX}"
++ "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
+ fi
+
+ list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 5984e92d2..37d5f05b5 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -223,7 +223,7 @@ EOF
+ fi
+
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+- recovery_params="$(echo "${LPARAMS}" | grep single)" || true
++ recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true
+ counter=1
+ while echo "$used_osprober_linux_ids" | grep 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id' > /dev/null; do
+ counter=$((counter+1));
diff --git a/debian/patches/mkimage-fix-section-sizes.patch b/debian/patches/mkimage-fix-section-sizes.patch
new file mode 100644
index 0000000..107bd0e
--- /dev/null
+++ b/debian/patches/mkimage-fix-section-sizes.patch
@@ -0,0 +1,109 @@
+From e5be30174c7ed596ca2fd28d636a4fbc26a0199a Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Fri, 16 Apr 2021 21:37:23 +0200
+Subject: util/mkimage: Some fixes to PE binaries section size calculation
+
+Commit f60ba9e5945 (util/mkimage: Refactor section setup to use a helper)
+added a helper function to setup PE sections, but it caused regressions
+in some arches where the natural alignment lead to wrong section sizes.
+
+This patch fixes a few things that were caused the section sizes to be
+calculated wrongly. These fixes are:
+
+ * Only align the virtual memory addresses but not the raw data offsets.
+ * Use aligned sizes for virtual memory sizes but not for raw data sizes.
+ * Always align the sizes to set the virtual memory sizes.
+
+These seems to not cause problems for x64 and aa64 EFI platforms but was
+a problem for ia64. Because the size of the ".data" and "mods" sections
+were wrong and didn't have the correct content. Which lead to GRUB not
+being able to load any built-in module.
+
+Reported-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+
+Bug-Debian: https://bugs.debian.org/987103
+
+Patch-Name: mkimage-fix-section-sizes.patch
+---
+ util/mkimage.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/util/mkimage.c b/util/mkimage.c
+index a26cf76f7..b84311f1f 100644
+--- a/util/mkimage.c
++++ b/util/mkimage.c
+@@ -841,7 +841,7 @@ init_pe_section(const struct grub_install_image_target_desc *image_target,
+
+ section->raw_data_offset = grub_host_to_target32 (*rda);
+ section->raw_data_size = grub_host_to_target32 (rsz);
+- (*rda) = ALIGN_UP (*rda + rsz, GRUB_PE32_FILE_ALIGNMENT);
++ (*rda) = *rda + rsz;
+
+ section->characteristics = grub_host_to_target32 (characteristics);
+
+@@ -1309,7 +1309,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ char *pe_img, *pe_sbat, *header;
+ struct grub_pe32_section_table *section;
+ size_t n_sections = 4;
+- size_t scn_size;
++ size_t scn_size, raw_size;
+ grub_uint32_t vma, raw_data;
+ size_t pe_size, header_size;
+ struct grub_pe32_coff_header *c;
+@@ -1410,7 +1410,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ GRUB_PE32_SCN_MEM_EXECUTE |
+ GRUB_PE32_SCN_MEM_READ);
+
+- scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
++ raw_size = layout.kernel_size - layout.exec_size;
++ scn_size = ALIGN_UP (raw_size, GRUB_PE32_FILE_ALIGNMENT);
+ /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size +
+ ALIGN_UP (total_module_size,
+@@ -1418,15 +1419,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
+
+ section = init_pe_section (image_target, section, ".data",
+ &vma, scn_size, image_target->section_align,
+- &raw_data, scn_size,
++ &raw_data, raw_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ |
+ GRUB_PE32_SCN_MEM_WRITE);
+
+- scn_size = pe_size - layout.reloc_size - sbat_size - raw_data;
++ raw_size = pe_size - layout.reloc_size - sbat_size - raw_data;
++ scn_size = ALIGN_UP (raw_size, GRUB_PE32_FILE_ALIGNMENT);
+ section = init_pe_section (image_target, section, "mods",
+ &vma, scn_size, image_target->section_align,
+- &raw_data, scn_size,
++ &raw_data, raw_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ |
+ GRUB_PE32_SCN_MEM_WRITE);
+@@ -1436,21 +1438,22 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ pe_sbat = pe_img + raw_data;
+ grub_util_load_image (sbat_path, pe_sbat);
+
++ scn_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT);
+ section = init_pe_section (image_target, section, ".sbat",
+- &vma, sbat_size,
++ &vma, scn_size,
+ image_target->section_align,
+ &raw_data, sbat_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ);
+ }
+
+- scn_size = layout.reloc_size;
++ scn_size = ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
+ PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
+ PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
+ memcpy (pe_img + raw_data, layout.reloc_section, scn_size);
+ init_pe_section (image_target, section, ".reloc",
+ &vma, scn_size, image_target->section_align,
+- &raw_data, scn_size,
++ &raw_data, layout.reloc_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_DISCARDABLE |
+ GRUB_PE32_SCN_MEM_READ);
diff --git a/debian/patches/mkrescue-efi-modules.patch b/debian/patches/mkrescue-efi-modules.patch
new file mode 100644
index 0000000..8b6df4f
--- /dev/null
+++ b/debian/patches/mkrescue-efi-modules.patch
@@ -0,0 +1,35 @@
+From 41f0edb8bebe40b7d9302418100034dead84dfe9 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <Mario_Limonciello@dell.com>
+Date: Mon, 13 Jan 2014 12:12:59 +0000
+Subject: Build vfat into EFI boot images
+
+Author: Colin Watson <cjwatson@ubuntu.com>
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/677758
+Forwarded: http://lists.gnu.org/archive/html/grub-devel/2011-01/msg00028.html
+Last-Update: 2016-09-18
+
+Patch-Name: mkrescue-efi-modules.patch
+---
+ util/grub-mkrescue.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
+index fb4dcc6d5..fcb35726c 100644
+--- a/util/grub-mkrescue.c
++++ b/util/grub-mkrescue.c
+@@ -753,6 +753,7 @@ main (int argc, char *argv[])
+
+ grub_install_push_module ("part_gpt");
+ grub_install_push_module ("part_msdos");
++ grub_install_push_module ("fat");
+
+ imgname = grub_util_path_concat (2, efidir_efi_boot, "bootia64.efi");
+ make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname);
+@@ -830,6 +831,7 @@ main (int argc, char *argv[])
+ free (efidir);
+ grub_install_pop_module ();
+ grub_install_pop_module ();
++ grub_install_pop_module ();
+ }
+
+ grub_install_push_module ("part_apple");
diff --git a/debian/patches/net-read-bracketed-ipv6-addr.patch b/debian/patches/net-read-bracketed-ipv6-addr.patch
new file mode 100644
index 0000000..93ee7d7
--- /dev/null
+++ b/debian/patches/net-read-bracketed-ipv6-addr.patch
@@ -0,0 +1,255 @@
+From c7e2338904e5e1e2546f1097cad1a020615463cf Mon Sep 17 00:00:00 2001
+From: Aaron Miller <aaronmiller@fb.com>
+Date: Thu, 27 Oct 2016 17:39:49 -0400
+Subject: net: read bracketed ipv6 addrs and port numbers
+
+Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses
+to be recognized with brackets around them, which is required to specify a port
+number
+
+Last-Update: 2021-09-24
+
+Patch-Name: net-read-bracketed-ipv6-addr.patch
+---
+ grub-core/net/http.c | 21 ++++++++--
+ grub-core/net/net.c | 93 +++++++++++++++++++++++++++++++++++++++++---
+ grub-core/net/tftp.c | 6 ++-
+ include/grub/net.h | 1 +
+ 4 files changed, 110 insertions(+), 11 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index b616cf40b..3fe155f1b 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -312,12 +312,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ int i;
+ struct grub_net_buff *nb;
+ grub_err_t err;
++ char* server = file->device->net->server;
++ int port = file->device->net->port;
+
+ nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
+ + sizeof ("GET ") - 1
+ + grub_strlen (data->filename)
+ + sizeof (" HTTP/1.1\r\nHost: ") - 1
+- + grub_strlen (file->device->net->server)
++ + grub_strlen (server) + sizeof (":XXXXXXXXXX")
+ + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
+ "\r\n") - 1
+ + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
+@@ -356,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ sizeof (" HTTP/1.1\r\nHost: ") - 1);
+
+ ptr = nb->tail;
+- err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
++ err = grub_netbuff_put (nb, grub_strlen (server));
+ if (err)
+ {
+ grub_netbuff_free (nb);
+@@ -365,6 +367,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ grub_memcpy (ptr, file->device->net->server,
+ grub_strlen (file->device->net->server));
+
++ if (port)
++ {
++ ptr = nb->tail;
++ grub_snprintf ((char *) ptr,
++ sizeof (":XXXXXXXXXX"),
++ ":%d",
++ port);
++ }
++
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb,
+ sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
+@@ -390,8 +401,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ grub_netbuff_put (nb, 2);
+ grub_memcpy (ptr, "\r\n", 2);
+
+- data->sock = grub_net_tcp_open (file->device->net->server,
+- HTTP_PORT, http_receive,
++ grub_dprintf ("http", "opening path %s on host %s TCP port %d\n",
++ data->filename, server, port ? port : HTTP_PORT);
++ data->sock = grub_net_tcp_open (server,
++ port ? port : HTTP_PORT, http_receive,
+ http_err, NULL,
+ file);
+ if (!data->sock)
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 4d3eb5c1a..15a2f29a9 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -442,6 +442,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
+ grub_uint16_t newip[8];
+ const char *ptr = val;
+ int word, quaddot = -1;
++ int bracketed = 0;
++
++ if (ptr[0] == '[') {
++ bracketed = 1;
++ ptr++;
++ }
+
+ if (ptr[0] == ':' && ptr[1] != ':')
+ return 0;
+@@ -480,6 +486,9 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
+ grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
+ }
+ grub_memcpy (ip, newip, 16);
++ if (bracketed && *ptr == ']') {
++ ptr++;
++ }
+ if (rest)
+ *rest = ptr;
+ return 1;
+@@ -1265,8 +1274,10 @@ grub_net_open_real (const char *name)
+ {
+ grub_net_app_level_t proto;
+ const char *protname, *server;
++ char *host;
+ grub_size_t protnamelen;
+ int try;
++ int port = 0;
+
+ if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
+ {
+@@ -1304,6 +1315,72 @@ grub_net_open_real (const char *name)
+ return NULL;
+ }
+
++ char* port_start;
++ /* ipv6 or port specified? */
++ if ((port_start = grub_strchr (server, ':')))
++ {
++ char* ipv6_begin;
++ if((ipv6_begin = grub_strchr (server, '[')))
++ {
++ char* ipv6_end = grub_strchr (server, ']');
++ if(!ipv6_end)
++ {
++ grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++ N_("mismatched [ in address"));
++ return NULL;
++ }
++ /* port number after bracketed ipv6 addr */
++ if(ipv6_end[1] == ':')
++ {
++ port = grub_strtoul (ipv6_end + 2, NULL, 10);
++ if(port > 65535)
++ {
++ grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++ N_("bad port number"));
++ return NULL;
++ }
++ }
++ host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1);
++ }
++ else
++ {
++ if (grub_strchr (port_start + 1, ':'))
++ {
++ int iplen = grub_strlen (server);
++ /* bracket bare ipv6 addrs */
++ host = grub_malloc (iplen + 3);
++ if(!host)
++ {
++ return NULL;
++ }
++ host[0] = '[';
++ grub_memcpy (host + 1, server, iplen);
++ host[iplen + 1] = ']';
++ host[iplen + 2] = '\0';
++ }
++ else
++ {
++ /* hostname:port or ipv4:port */
++ port = grub_strtol (port_start + 1, NULL, 10);
++ if(port > 65535)
++ {
++ grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++ N_("bad port number"));
++ return NULL;
++ }
++ host = grub_strndup (server, port_start - server);
++ }
++ }
++ }
++ else
++ {
++ host = grub_strdup (server);
++ }
++ if (!host)
++ {
++ return NULL;
++ }
++
+ for (try = 0; try < 2; try++)
+ {
+ FOR_NET_APP_LEVEL (proto)
+@@ -1313,15 +1390,19 @@ grub_net_open_real (const char *name)
+ {
+ grub_net_t ret = grub_zalloc (sizeof (*ret));
+ if (!ret)
+- return NULL;
+- ret->protocol = proto;
+- ret->server = grub_strdup (server);
+- if (!ret->server)
++ grub_free (host);
++ if (host)
+ {
+- grub_free (ret);
+- return NULL;
++ ret->server = grub_strdup (host);
++ if (!ret->server)
++ {
++ grub_free (ret);
++ return NULL;
++ }
+ }
+ ret->fs = &grub_net_fs;
++ ret->protocol = proto;
++ ret->port = port;
+ return ret;
+ }
+ }
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 7f44b30f5..f3e787938 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -295,6 +295,7 @@ tftp_open (struct grub_file *file, const char *filename)
+ grub_err_t err;
+ grub_uint8_t *nbd;
+ grub_net_network_level_address_t addr;
++ int port = file->device->net->port;
+
+ data = grub_zalloc (sizeof (*data));
+ if (!data)
+@@ -361,12 +362,15 @@ tftp_open (struct grub_file *file, const char *filename)
+ err = grub_net_resolve_address (file->device->net->server, &addr);
+ if (err)
+ {
++ grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
++ (unsigned long long)data->file_size,
++ (unsigned long long)data->block_size);
+ grub_free (data);
+ return err;
+ }
+
+ data->sock = grub_net_udp_open (addr,
+- TFTP_SERVER_PORT, tftp_receive,
++ port ? port : TFTP_SERVER_PORT, tftp_receive,
+ file);
+ if (!data->sock)
+ {
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 7ae4b6bd8..69bfe0947 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -270,6 +270,7 @@ typedef struct grub_net
+ {
+ char *server;
+ char *name;
++ int port;
+ grub_net_app_level_t protocol;
+ grub_net_packets_t packs;
+ grub_off_t offset;
diff --git a/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
new file mode 100644
index 0000000..24601f7
--- /dev/null
+++ b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
@@ -0,0 +1,57 @@
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:38:19 +0300
+Subject: fs/ntfs: Fix an OOB read when parsing a volume label
+
+This fix introduces checks to ensure that an NTFS volume label is always
+read from the corresponding file record segment.
+
+The current NTFS code allows the volume label string to be read from an
+arbitrary, attacker-chosen memory location. However, the bytes read are
+always treated as UTF-16LE. So, the final string displayed is mostly
+unreadable and it can't be easily converted back to raw bytes.
+
+The lack of this check is a minor issue, likely not causing a significant
+data leak.
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index bb70c89..ff5e374 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -1213,13 +1213,29 @@ grub_ntfs_label (grub_device_t device, char **label)
+
+ init_attr (&mft->attr, mft);
+ pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
++
++ if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++ {
++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
++ goto fail;
++ }
++
++ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa < 0x16)
++ {
++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
++ goto fail;
++ }
++
+ if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
+ {
+ int len;
+
+ len = u32at (pa, 0x10) / 2;
+ pa += u16at (pa, 0x14);
+- *label = get_utf8 (pa, len);
++ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
++ *label = get_utf8 (pa, len);
++ else
++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
+ }
+
+ fail:
diff --git a/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-index-at.patch b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-index-at.patch
new file mode 100644
index 0000000..29b9dd5
--- /dev/null
+++ b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-index-at.patch
@@ -0,0 +1,46 @@
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:33:44 +0300
+Subject: fs/ntfs: Fix an OOB read when parsing bitmaps for index attributes
+
+This fix introduces checks to ensure that bitmaps for directory indices
+are never read beyond their actual sizes.
+
+The lack of this check is a minor issue, likely not exploitable in any way.
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index 2d78b96..bb70c89 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -843,6 +843,25 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+
+ if (is_resident)
+ {
++ if (bitmap_len > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++ {
++ grub_error (GRUB_ERR_BAD_FS, "resident bitmap too large");
++ goto done;
++ }
++
++ if (cur_pos >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++ {
++ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
++ goto done;
++ }
++
++ if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) >
++ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
++ {
++ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
++ goto done;
++ }
++
+ grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
+ bitmap_len);
+ }
diff --git a/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entries-fr.patch b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entries-fr.patch
new file mode 100644
index 0000000..bbc90c3
--- /dev/null
+++ b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entries-fr.patch
@@ -0,0 +1,69 @@
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:33:17 +0300
+Subject: fs/ntfs: Fix an OOB read when parsing directory entries from
+ resident and non-resident index attributes
+
+This fix introduces checks to ensure that index entries are never read
+beyond the corresponding directory index.
+
+The lack of this check is a minor issue, likely not exploitable in any way.
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index a68e173..2d78b96 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -599,7 +599,7 @@ get_utf8 (grub_uint8_t *in, grub_size_t len)
+ }
+
+ static int
+-list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
++list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos,
+ grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
+ {
+ grub_uint8_t *np;
+@@ -610,6 +610,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
+ grub_uint8_t namespace;
+ char *ustr;
+
++ if ((pos >= end_pos) || (end_pos - pos < 0x52))
++ break;
++
+ if (pos[0xC] & 2) /* end signature */
+ break;
+
+@@ -617,6 +620,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
+ ns = *(np++);
+ namespace = *(np++);
+
++ if (2 * ns > end_pos - pos - 0x52)
++ break;
++
+ /*
+ * Ignore files in DOS namespace, as they will reappear as Win32
+ * names.
+@@ -806,7 +812,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ }
+
+ cur_pos += 0x10; /* Skip index root */
+- ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data);
++ ret = list_file (mft, cur_pos + u16at (cur_pos, 0),
++ at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
++ hook, hook_data);
+ if (ret)
+ goto done;
+
+@@ -893,6 +901,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ (const grub_uint8_t *) "INDX")))
+ goto done;
+ ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
++ indx + (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
+ hook, hook_data);
+ if (ret)
+ goto done;
diff --git a/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-reside.patch b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-reside.patch
new file mode 100644
index 0000000..d762c06
--- /dev/null
+++ b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-reside.patch
@@ -0,0 +1,54 @@
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:32:33 +0300
+Subject: fs/ntfs: Fix an OOB read when reading data from the resident $DATA
+ attribute
+
+When reading a file containing resident data, i.e., the file data is stored in
+the $DATA attribute within the NTFS file record, not in external clusters,
+there are no checks that this resident data actually fits the corresponding
+file record segment.
+
+When parsing a specially-crafted file system image, the current NTFS code will
+read the file data from an arbitrary, attacker-chosen memory offset and of
+arbitrary, attacker-chosen length.
+
+This allows an attacker to display arbitrary chunks of memory, which could
+contain sensitive information like password hashes or even plain-text,
+obfuscated passwords from BS EFI variables.
+
+This fix implements a check to ensure that resident data is read from the
+corresponding file record segment only.
+
+Fixes: CVE-2023-4693
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index c3c4db1..a68e173 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -401,7 +401,18 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
+ {
+ if (ofs + len > u32at (pa, 0x10))
+ return grub_error (GRUB_ERR_BAD_FS, "read out of range");
+- grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
++
++ if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++ return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
++
++ if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
++
++ if (u16at (pa, 0x14) + u32at (pa, 0x10) >
++ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
++ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
++
++ grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
+ return 0;
+ }
+
diff --git a/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_LIST-.patch b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_LIST-.patch
new file mode 100644
index 0000000..06279b8
--- /dev/null
+++ b/debian/patches/ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_LIST-.patch
@@ -0,0 +1,89 @@
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:31:57 +0300
+Subject: fs/ntfs: Fix an OOB write when parsing the $ATTRIBUTE_LIST attribute
+ for the $MFT file
+
+When parsing an extremely fragmented $MFT file, i.e., the file described
+using the $ATTRIBUTE_LIST attribute, current NTFS code will reuse a buffer
+containing bytes read from the underlying drive to store sector numbers,
+which are consumed later to read data from these sectors into another buffer.
+
+These sectors numbers, two 32-bit integers, are always stored at predefined
+offsets, 0x10 and 0x14, relative to first byte of the selected entry within
+the $ATTRIBUTE_LIST attribute. Usually, this won't cause any problem.
+
+However, when parsing a specially-crafted file system image, this may cause
+the NTFS code to write these integers beyond the buffer boundary, likely
+causing the GRUB memory allocator to misbehave or fail. These integers contain
+values which are controlled by on-disk structures of the NTFS file system.
+
+Such modification and resulting misbehavior may touch a memory range not
+assigned to the GRUB and owned by firmware or another EFI application/driver.
+
+This fix introduces checks to ensure that these sector numbers are never
+written beyond the boundary.
+
+Fixes: CVE-2023-4692
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index bbdbe24..c3c4db1 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -184,7 +184,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ }
+ if (at->attr_end)
+ {
+- grub_uint8_t *pa;
++ grub_uint8_t *pa, *pa_end;
+
+ at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+ if (at->emft_buf == NULL)
+@@ -209,11 +209,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ }
+ at->attr_nxt = at->edat_buf;
+ at->attr_end = at->edat_buf + u32at (pa, 0x30);
++ pa_end = at->edat_buf + n;
+ }
+ else
+ {
+ at->attr_nxt = at->attr_end + u16at (pa, 0x14);
+ at->attr_end = at->attr_end + u32at (pa, 4);
++ pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+ }
+ at->flags |= GRUB_NTFS_AF_ALST;
+ while (at->attr_nxt < at->attr_end)
+@@ -230,6 +232,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ at->flags |= GRUB_NTFS_AF_GPOS;
+ at->attr_cur = at->attr_nxt;
+ pa = at->attr_cur;
++
++ if ((pa >= pa_end) || (pa_end - pa < 0x18))
++ {
++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
++ return NULL;
++ }
++
+ grub_set_unaligned32 ((char *) pa + 0x10,
+ grub_cpu_to_le32 (at->mft->data->mft_start));
+ grub_set_unaligned32 ((char *) pa + 0x14,
+@@ -240,6 +249,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ {
+ if (*pa != attr)
+ break;
++
++ if ((pa >= pa_end) || (pa_end - pa < 0x18))
++ {
++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
++ return NULL;
++ }
++
+ if (read_attr
+ (at, pa + 0x10,
+ u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
diff --git a/debian/patches/ntfs-cve-fixes/fs-ntfs-Make-code-more-readable.patch b/debian/patches/ntfs-cve-fixes/fs-ntfs-Make-code-more-readable.patch
new file mode 100644
index 0000000..bc3bfd7
--- /dev/null
+++ b/debian/patches/ntfs-cve-fixes/fs-ntfs-Make-code-more-readable.patch
@@ -0,0 +1,155 @@
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:40:07 +0300
+Subject: fs/ntfs: Make code more readable
+
+Move some calls used to access NTFS attribute header fields into
+functions with human-readable names.
+
+Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 48 +++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index ff5e374..de435aa 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -52,6 +52,24 @@ u64at (void *ptr, grub_size_t ofs)
+ return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs));
+ }
+
++static grub_uint16_t
++first_attr_off (void *mft_buf_ptr)
++{
++ return u16at (mft_buf_ptr, 0x14);
++}
++
++static grub_uint16_t
++res_attr_data_off (void *res_attr_ptr)
++{
++ return u16at (res_attr_ptr, 0x14);
++}
++
++static grub_uint32_t
++res_attr_data_len (void *res_attr_ptr)
++{
++ return u32at (res_attr_ptr, 0x10);
++}
++
+ grub_ntfscomp_func_t grub_ntfscomp_func;
+
+ static grub_err_t
+@@ -106,7 +124,7 @@ init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
+ {
+ at->mft = mft;
+ at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
+- at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
++ at->attr_nxt = mft->buf + first_attr_off (mft->buf);
+ at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
+ }
+
+@@ -154,7 +172,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ return NULL;
+ }
+
+- new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)];
++ new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
+ while (*new_pos != 0xFF)
+ {
+ if ((*new_pos == *at->attr_cur)
+@@ -213,7 +231,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ }
+ else
+ {
+- at->attr_nxt = at->attr_end + u16at (pa, 0x14);
++ at->attr_nxt = at->attr_end + res_attr_data_off (pa);
+ at->attr_end = at->attr_end + u32at (pa, 4);
+ pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+ }
+@@ -399,20 +417,20 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
+
+ if (pa[8] == 0)
+ {
+- if (ofs + len > u32at (pa, 0x10))
++ if (ofs + len > res_attr_data_len (pa))
+ return grub_error (GRUB_ERR_BAD_FS, "read out of range");
+
+- if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++ if (res_attr_data_len (pa) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
+
+ if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
+
+- if (u16at (pa, 0x14) + u32at (pa, 0x10) >
++ if (res_attr_data_off (pa) + res_attr_data_len (pa) >
+ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
+
+- grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
++ grub_memcpy (dest, pa + res_attr_data_off (pa) + ofs, len);
+ return 0;
+ }
+
+@@ -556,7 +574,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
+ (unsigned long long) mftno);
+
+ if (!pa[8])
+- mft->size = u32at (pa, 0x10);
++ mft->size = res_attr_data_len (pa);
+ else
+ mft->size = u64at (pa, 0x30);
+
+@@ -805,7 +823,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ (u32at (cur_pos, 0x18) != 0x490024) ||
+ (u32at (cur_pos, 0x1C) != 0x300033))
+ continue;
+- cur_pos += u16at (cur_pos, 0x14);
++ cur_pos += res_attr_data_off (cur_pos);
+ if (*cur_pos != 0x30) /* Not filename index */
+ continue;
+ break;
+@@ -834,7 +852,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ {
+ int is_resident = (cur_pos[8] == 0);
+
+- bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) :
++ bitmap_len = ((is_resident) ? res_attr_data_len (cur_pos) :
+ u32at (cur_pos, 0x28));
+
+ bmp = grub_malloc (bitmap_len);
+@@ -855,14 +873,14 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ goto done;
+ }
+
+- if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) >
++ if (res_attr_data_off (cur_pos) + res_attr_data_len (cur_pos) >
+ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
+ goto done;
+ }
+
+- grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
++ grub_memcpy (bmp, cur_pos + res_attr_data_off (cur_pos),
+ bitmap_len);
+ }
+ else
+@@ -1226,12 +1244,12 @@ grub_ntfs_label (grub_device_t device, char **label)
+ goto fail;
+ }
+
+- if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
++ if ((pa) && (pa[8] == 0) && (res_attr_data_len (pa)))
+ {
+ int len;
+
+- len = u32at (pa, 0x10) / 2;
+- pa += u16at (pa, 0x14);
++ len = res_attr_data_len (pa) / 2;
++ pa += res_attr_data_off (pa);
+ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
+ *label = get_utf8 (pa, len);
+ else
diff --git a/debian/patches/olpc-prefix-hack.patch b/debian/patches/olpc-prefix-hack.patch
new file mode 100644
index 0000000..6ba9b1e
--- /dev/null
+++ b/debian/patches/olpc-prefix-hack.patch
@@ -0,0 +1,51 @@
+From 39e079ec50c46fa2fc2f43a1a2e01172ef7dd7c6 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:12:50 +0000
+Subject: Hack prefix for OLPC
+
+This sucks, but it's better than what OFW was giving us.
+
+Patch-Name: olpc-prefix-hack.patch
+---
+ grub-core/kern/ieee1275/init.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index d483e35ee..8b089b48d 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -76,6 +76,7 @@ grub_exit (void)
+ grub_ieee1275_exit ();
+ }
+
++#ifndef __i386__
+ /* Translate an OF filesystem path (separated by backslashes), into a GRUB
+ path (separated by forward slashes). */
+ static void
+@@ -90,9 +91,18 @@ grub_translate_ieee1275_path (char *filepath)
+ backslash = grub_strchr (filepath, '\\');
+ }
+ }
++#endif
+
+ void (*grub_ieee1275_net_config) (const char *dev, char **device, char **path,
+ char *bootpath);
++#ifdef __i386__
++void
++grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
++ char **path __attribute__ ((unused)))
++{
++ grub_env_set ("prefix", "(sd,1)/");
++}
++#else
+ void
+ grub_machine_get_bootlocation (char **device, char **path)
+ {
+@@ -146,6 +156,7 @@ grub_machine_get_bootlocation (char **device, char **path)
+ }
+ grub_free (bootpath);
+ }
++#endif
+
+ /* Claim some available memory in the first /memory node. */
+ #ifdef __sparc__
diff --git a/debian/patches/os-prober-Allow-initrd-to-contain-spaces.patch b/debian/patches/os-prober-Allow-initrd-to-contain-spaces.patch
new file mode 100644
index 0000000..eb6c452
--- /dev/null
+++ b/debian/patches/os-prober-Allow-initrd-to-contain-spaces.patch
@@ -0,0 +1,50 @@
+From 1f982e2a7c35e14d5a92c76db998afafd1bd9e87 Mon Sep 17 00:00:00 2001
+From: General Chaos <debianbugs@toeai.com>
+Date: Tue, 12 Apr 2016 22:28:52 +0000
+Subject: [PATCH] os-prober: Allow initrd to contain spaces
+
+linux-boot-prober produces structured output with newline-terminated rows
+representing kernels, each with colon-delimited columns. We translate
+this into a sequence of space-separated words representing kernels,
+each containing colon-delimited fields where spaces are represented by
+carets.
+
+When we parse each of those words into colon-delimited fields, if the
+field could conceivably contain spaces then we need to translate
+carets back into spaces. We did this for label and parameters, but not
+for the initrd.
+
+In particular, when CPU microcode is installed on Arch Linux or its
+derivatives, they write CPU microcode into one initrd archive and the
+rest of early user-space into another, instead of concatenating the
+archives into a single file like Debian derivatives do. To boot Arch
+successfully from the grub menu, we need to add all of their initrds
+to the grub menu entry (detecting this situation requires an os-prober
+patch, for which see <https://bugs.debian.org/820838>).
+
+[Commit message added by Simon McVittie <smcv@collabora.com>]
+
+Bug: https://savannah.gnu.org/bugs/index.php?47681
+Bug-Debian: https://bugs.debian.org/838177
+Forwarded: https://savannah.gnu.org/bugs/index.php?47681
+Closes: #838177
+---
+ util/grub.d/30_os-prober.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index da5f28876..d0609d9a4 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -243,7 +243,7 @@ EOF
+ LBOOT="`echo ${LINUX} | cut -d ':' -f 2`"
+ LLABEL="`echo ${LINUX} | cut -d ':' -f 3 | tr '^' ' '`"
+ LKERNEL="`echo ${LINUX} | cut -d ':' -f 4`"
+- LINITRD="`echo ${LINUX} | cut -d ':' -f 5`"
++ LINITRD="`echo ${LINUX} | cut -d ':' -f 5 | tr '^' ' '`"
+ LPARAMS="`echo ${LINUX} | cut -d ':' -f 6- | tr '^' ' '`"
+
+ if [ -z "${LLABEL}" ] ; then
+--
+2.32.0
+
diff --git a/debian/patches/osdep-devmapper-getroot-have-devmapper-recognize-luks2.patch b/debian/patches/osdep-devmapper-getroot-have-devmapper-recognize-luks2.patch
new file mode 100644
index 0000000..667a5a1
--- /dev/null
+++ b/debian/patches/osdep-devmapper-getroot-have-devmapper-recognize-luks2.patch
@@ -0,0 +1,54 @@
+From: Josselin Poiret <dev@jpoiret.xyz>
+Date: Thu, 12 Jan 2023 17:05:08 -0600
+Subject: osdep/devmapper/getroot: Have devmapper recognize LUKS2
+Origin: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=9022a48dd9984fc3e90a5b42c3b5483d6061ccfb
+Bug-Debian: https://bugs.debian.org/1028301
+
+Changes UUID comparisons so that LUKS1 and LUKS2 are both recognized
+as being LUKS cryptodisks.
+
+Signed-off-by: Josselin Poiret <dev@jpoiret.xyz>
+Tested-by: Glenn Washburn <development@efficientek.com>
+Reviewed-by: Patrick Steinhardt <ps@pks.im>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/osdep/devmapper/getroot.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/grub-core/osdep/devmapper/getroot.c
++++ b/grub-core/osdep/devmapper/getroot.c
+@@ -143,7 +143,8 @@ grub_util_get_dm_abstraction (const char
+ grub_free (uuid);
+ return GRUB_DEV_ABSTRACTION_LVM;
+ }
+- if (strncmp (uuid, "CRYPT-LUKS1-", 12) == 0)
++ if (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
++ || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0)
+ {
+ grub_free (uuid);
+ return GRUB_DEV_ABSTRACTION_LUKS;
+@@ -184,7 +185,9 @@ grub_util_pull_devmapper (const char *os
+ grub_util_pull_device (subdev);
+ }
+ }
+- if (uuid && strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
++ if (uuid
++ && (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
++ || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0)
+ && lastsubdev)
+ {
+ char *grdev = grub_util_get_grub_dev (lastsubdev);
+@@ -258,11 +261,11 @@ grub_util_get_devmapper_grub_dev (const
+ {
+ char *dash;
+
+- dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-');
++ dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS*-") - 1, '-');
+ if (dash)
+ *dash = 0;
+ grub_dev = grub_xasprintf ("cryptouuid/%s",
+- uuid + sizeof ("CRYPT-LUKS1-") - 1);
++ uuid + sizeof ("CRYPT-LUKS*-") - 1);
+ grub_free (uuid);
+ return grub_dev;
+ }
diff --git a/debian/patches/osdep-devmapper-getroot-set-up-cheated-luks2-cryptodisk-mount-from-dm-parameters.patch b/debian/patches/osdep-devmapper-getroot-set-up-cheated-luks2-cryptodisk-mount-from-dm-parameters.patch
new file mode 100644
index 0000000..a23d0f7
--- /dev/null
+++ b/debian/patches/osdep-devmapper-getroot-set-up-cheated-luks2-cryptodisk-mount-from-dm-parameters.patch
@@ -0,0 +1,154 @@
+From: Josselin Poiret <dev@jpoiret.xyz>
+Date: Thu, 12 Jan 2023 17:05:09 -0600
+Subject: osdep/devmapper/getroot: Set up cheated LUKS2 cryptodisk mount from
+ DM parameters
+Origin: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=aa5172a55cfabdd0bed3161ad44fc228b9d019f7
+Bug-Debian: https://bugs.debian.org/1028301
+
+This lets a LUKS2 cryptodisk have its cipher and hash filled out,
+otherwise they wouldn't be initialized if cheat mounted.
+
+Signed-off-by: Josselin Poiret <dev@jpoiret.xyz>
+Tested-by: Glenn Washburn <development@efficientek.com>
+Reviewed-by: Patrick Steinhardt <ps@pks.im>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/osdep/devmapper/getroot.c | 107 +++++++++++++++++++++++++++++++++++-
+ 1 file changed, 106 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c
+index 2bf4264..cc3f7da 100644
+--- a/grub-core/osdep/devmapper/getroot.c
++++ b/grub-core/osdep/devmapper/getroot.c
+@@ -51,6 +51,8 @@
+ #include <grub/emu/misc.h>
+ #include <grub/emu/hostdisk.h>
+
++#include <grub/cryptodisk.h>
++
+ static int
+ grub_util_open_dm (const char *os_dev, struct dm_tree **tree,
+ struct dm_tree_node **node)
+@@ -186,7 +188,6 @@ grub_util_pull_devmapper (const char *os_dev)
+ && lastsubdev)
+ {
+ char *grdev = grub_util_get_grub_dev (lastsubdev);
+- dm_tree_free (tree);
+ if (grdev)
+ {
+ grub_err_t err;
+@@ -194,7 +195,111 @@ grub_util_pull_devmapper (const char *os_dev)
+ if (err)
+ grub_util_error (_("can't mount encrypted volume `%s': %s"),
+ lastsubdev, grub_errmsg);
++ if (strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0)
++ {
++ /*
++ * Set LUKS2 cipher from dm parameters, since it is not
++ * possible to determine the correct one without
++ * unlocking, as there might be multiple segments.
++ */
++ grub_disk_t source;
++ grub_cryptodisk_t cryptodisk;
++ grub_uint64_t start, length;
++ char *target_type;
++ char *params;
++ const char *name;
++ char *cipher, *cipher_mode;
++ struct dm_task *dmt;
++ char *seek_head, *c;
++ unsigned int remaining;
++
++ source = grub_disk_open (grdev);
++ if (! source)
++ grub_util_error (_("cannot open grub disk `%s'"), grdev);
++ cryptodisk = grub_cryptodisk_get_by_source_disk (source);
++ if (! cryptodisk)
++ grub_util_error (_("cannot get cryptodisk from source disk `%s'"), grdev);
++ grub_disk_close (source);
++
++ /*
++ * The following function always returns a non-NULL pointer,
++ * but the string may be empty if the relevant info is not present.
++ */
++ name = dm_tree_node_get_name (node);
++ if (*name == '\0')
++ grub_util_error (_("cannot get dm node name for grub dev `%s'"), grdev);
++
++ grub_util_info ("populating parameters of cryptomount `%s' from DM device `%s'",
++ uuid, name);
++
++ dmt = dm_task_create (DM_DEVICE_TABLE);
++ if (dmt == NULL)
++ grub_util_error (_("can't create dm task DM_DEVICE_TABLE"));
++ if (dm_task_set_name (dmt, name) == 0)
++ grub_util_error (_("can't set dm task name to `%s'"), name);
++ if (dm_task_run (dmt) == 0)
++ grub_util_error (_("can't run dm task for `%s'"), name);
++ /*
++ * dm_get_next_target() doesn't have any error modes, everything has
++ * been handled by dm_task_run().
++ */
++ dm_get_next_target (dmt, NULL, &start, &length,
++ &target_type, &params);
++ if (strncmp (target_type, "crypt", sizeof ("crypt")) != 0)
++ grub_util_error (_("dm target of type `%s' is not `crypt'"), target_type);
++
++ /*
++ * The dm target parameters for dm-crypt are
++ * <cipher> <key> <iv_offset> <device path> <offset> [<#opt_params> <opt_param1> ...]
++ */
++ c = params;
++ remaining = grub_strlen (c);
++
++ /* First, get the cipher name from the cipher. */
++ seek_head = grub_memchr (c, '-', remaining);
++ if (seek_head == NULL)
++ grub_util_error (_("can't get cipher from dm-crypt parameters `%s'"),
++ params);
++ cipher = grub_strndup (c, seek_head - c);
++ if (cipher == NULL)
++ grub_util_error (_("could not strndup cipher of length `%lu'"), (unsigned long)(seek_head - c));
++ remaining -= seek_head - c + 1;
++ c = seek_head + 1;
++
++ /* Now, the cipher mode. */
++ seek_head = grub_memchr (c, ' ', remaining);
++ if (seek_head == NULL)
++ grub_util_error (_("can't get cipher mode from dm-crypt parameters `%s'"),
++ params);
++ cipher_mode = grub_strndup (c, seek_head - c);
++ if (cipher_mode == NULL)
++ grub_util_error (_("could not strndup cipher_mode of length `%lu'"), (unsigned long)(seek_head - c));
++
++ remaining -= seek_head - c + 1;
++ c = seek_head + 1;
++
++ err = grub_cryptodisk_setcipher (cryptodisk, cipher, cipher_mode);
++ if (err)
++ grub_util_error (_("can't set cipher of cryptodisk `%s' to `%s' with mode `%s'"),
++ uuid, cipher, cipher_mode);
++
++ grub_free (cipher);
++ grub_free (cipher_mode);
++
++ /*
++ * This is the only hash usable by PBKDF2, and we don't
++ * have Argon2 support yet, so set it by default,
++ * otherwise grub-probe would miss the required
++ * abstraction.
++ */
++ cryptodisk->hash = grub_crypto_lookup_md_by_name ("sha256");
++ if (cryptodisk->hash == NULL)
++ grub_util_error (_("can't lookup hash sha256 by name"));
++
++ dm_task_destroy (dmt);
++ }
+ }
++ dm_tree_free (tree);
+ grub_free (grdev);
+ }
+ else
+--
+cgit v1.1
+
diff --git a/debian/patches/pc-verifiers-module.patch b/debian/patches/pc-verifiers-module.patch
new file mode 100644
index 0000000..a3c1303
--- /dev/null
+++ b/debian/patches/pc-verifiers-module.patch
@@ -0,0 +1,167 @@
+From 4a6abe501f39c4c8afe4ed7405ff99aff8559a13 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 18 Mar 2021 19:30:26 +0800
+Subject: i386-pc: build verifiers API as module
+
+Given no core functions on i386-pc would require verifiers to work and
+the only consumer of the verifier API is the pgp module, it looks good
+to me that we can move the verifiers out of the kernel image and let
+moddep.lst to auto-load it when pgp is loaded on i386-pc platform.
+
+This helps to reduce the size of core image and thus can relax the
+tension of exploding on some i386-pc system with very short MBR gap
+size. See also a very comprehensive summary from Colin [1] about the
+details.
+
+[1] https://lists.gnu.org/archive/html/grub-devel/2021-03/msg00240.html
+
+V2:
+Drop COND_NOT_i386_pc and use !COND_i386_pc.
+Add comment in kern/verifiers.c to help understanding what's going on
+without digging into the commit history.
+
+Reported-by: Colin Watson <cjwatson@debian.org>
+Reviewed-by: Colin Watson <cjwatson@debian.org>
+Signed-off-by: Michael Chang <mchang@suse.com>
+
+Origin: other, https://lists.gnu.org/archive/html/grub-devel/2021-03/msg00251.html
+Bug-Debian: https://bugs.debian.org/984488
+Bug-Debian: https://bugs.debian.org/985374
+Last-Update: 2021-09-24
+
+Patch-Name: pc-verifiers-module.patch
+---
+ grub-core/Makefile.am | 2 ++
+ grub-core/Makefile.core.def | 8 +++++++-
+ grub-core/kern/main.c | 4 ++++
+ grub-core/kern/verifiers.c | 17 +++++++++++++++++
+ include/grub/verify.h | 9 +++++++++
+ 5 files changed, 39 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index ee88e44e9..b6872d20f 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -93,7 +93,9 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
++if !COND_i386_pc
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h
++endif
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 2ff266806..da3269899 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -141,7 +141,7 @@ kernel = {
+ common = kern/rescue_parser.c;
+ common = kern/rescue_reader.c;
+ common = kern/term.c;
+- common = kern/verifiers.c;
++ nopc = kern/verifiers.c;
+
+ noemu = kern/compiler-rt.c;
+ noemu = kern/mm.c;
+@@ -946,6 +946,12 @@ module = {
+ cppflags = '-I$(srcdir)/lib/posix_wrap';
+ };
+
++module = {
++ name = verifiers;
++ common = kern/verifiers.c;
++ enable = i386_pc;
++};
++
+ module = {
+ name = hdparm;
+ common = commands/hdparm.c;
+diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
+index 2879d644a..c6fb66853 100644
+--- a/grub-core/kern/main.c
++++ b/grub-core/kern/main.c
+@@ -29,7 +29,9 @@
+ #include <grub/command.h>
+ #include <grub/reader.h>
+ #include <grub/parser.h>
++#ifndef GRUB_MACHINE_PCBIOS
+ #include <grub/verify.h>
++#endif
+
+ #ifdef GRUB_MACHINE_PCBIOS
+ #include <grub/machine/memory.h>
+@@ -285,8 +287,10 @@ grub_main (void)
+ grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+ #endif
+
++#ifndef GRUB_MACHINE_PCBIOS
+ /* Init verifiers API. */
+ grub_verifiers_init ();
++#endif
+
+ grub_load_config ();
+
+diff --git a/grub-core/kern/verifiers.c b/grub-core/kern/verifiers.c
+index 75d7994cf..1245d0d9e 100644
+--- a/grub-core/kern/verifiers.c
++++ b/grub-core/kern/verifiers.c
+@@ -221,8 +221,25 @@ grub_verify_string (char *str, enum grub_verify_string_type type)
+ return GRUB_ERR_NONE;
+ }
+
++/*
++ * It is intended to build verifiers as module on i386-pc platform to minimize
++ * the impact of growing core image size could blow up the 63 sectors limit of
++ * some MBR gap one day. It is also adequate to do so, given no core function
++ * on i386-pc would require the verifiers API to work.
++ */
++#ifdef GRUB_MACHINE_PCBIOS
++GRUB_MOD_INIT(verifiers)
++#else
+ void
+ grub_verifiers_init (void)
++#endif
+ {
+ grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
+ }
++
++#ifdef GRUB_MACHINE_PCBIOS
++GRUB_MOD_FINI(verifiers)
++{
++ grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY);
++}
++#endif
+diff --git a/include/grub/verify.h b/include/grub/verify.h
+index cd129c398..6fde244fc 100644
+--- a/include/grub/verify.h
++++ b/include/grub/verify.h
+@@ -64,10 +64,14 @@ struct grub_file_verifier
+ grub_err_t (*verify_string) (char *str, enum grub_verify_string_type type);
+ };
+
++#ifdef GRUB_MACHINE_PCBIOS
++extern struct grub_file_verifier *grub_file_verifiers;
++#else
+ extern struct grub_file_verifier *EXPORT_VAR (grub_file_verifiers);
+
+ extern void
+ grub_verifiers_init (void);
++#endif
+
+ static inline void
+ grub_verifier_register (struct grub_file_verifier *ver)
+@@ -81,7 +85,12 @@ grub_verifier_unregister (struct grub_file_verifier *ver)
+ grub_list_remove (GRUB_AS_LIST (ver));
+ }
+
++#ifdef GRUB_MACHINE_PCBIOS
++grub_err_t
++grub_verify_string (char *str, enum grub_verify_string_type type);
++#else
+ extern grub_err_t
+ EXPORT_FUNC (grub_verify_string) (char *str, enum grub_verify_string_type type);
++#endif
+
+ #endif /* ! GRUB_VERIFY_HEADER */
diff --git a/debian/patches/ppc64el-disable-vsx.patch b/debian/patches/ppc64el-disable-vsx.patch
new file mode 100644
index 0000000..bd29ae8
--- /dev/null
+++ b/debian/patches/ppc64el-disable-vsx.patch
@@ -0,0 +1,52 @@
+From c1c72eb757d40208128fb1da02199b0210a206ab Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
+Date: Thu, 25 Sep 2014 19:33:39 -0300
+Subject: Disable VSX instruction
+
+VSX bit is enabled by default for Power7 and Power8 CPU models,
+so we need to disable them in order to avoid instruction exceptions.
+Kernel will activate it when necessary.
+
+* grub-core/kern/powerpc/ieee1275/startup.S: Disable VSX.
+
+Also-By: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
+Also-By: Colin Watson <cjwatson@debian.org>
+
+Origin: other, https://lists.gnu.org/archive/html/grub-devel/2014-09/msg00078.html
+Last-Update: 2015-01-27
+
+Patch-Name: ppc64el-disable-vsx.patch
+---
+ grub-core/kern/powerpc/ieee1275/startup.S | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/grub-core/kern/powerpc/ieee1275/startup.S b/grub-core/kern/powerpc/ieee1275/startup.S
+index 21c884b43..de9a9601a 100644
+--- a/grub-core/kern/powerpc/ieee1275/startup.S
++++ b/grub-core/kern/powerpc/ieee1275/startup.S
+@@ -20,6 +20,8 @@
+ #include <grub/symbol.h>
+ #include <grub/offsets.h>
+
++#define MSR_VSX 0x80
++
+ .extern __bss_start
+ .extern _end
+
+@@ -28,6 +30,16 @@
+ .globl start, _start
+ start:
+ _start:
++ _start:
++
++ /* Disable VSX instruction */
++ mfmsr 0
++ oris 0,0,MSR_VSX
++ /* The "VSX Available" bit is in the lower half of the MSR, so we
++ don't need mtmsrd, which in any case won't work in 32-bit mode. */
++ mtmsr 0
++ isync
++
+ li 2, 0
+ li 13, 0
+
diff --git a/debian/patches/probe-fusionio.patch b/debian/patches/probe-fusionio.patch
new file mode 100644
index 0000000..d0d5efa
--- /dev/null
+++ b/debian/patches/probe-fusionio.patch
@@ -0,0 +1,76 @@
+From 611974f8c3231d87ca572feda72eb6d1a5a6b309 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:31 +0000
+Subject: Probe FusionIO devices
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1237519
+Forwarded: no
+Last-Update: 2016-09-18
+
+Patch-Name: probe-fusionio.patch
+---
+ grub-core/osdep/linux/getroot.c | 13 +++++++++++++
+ util/deviceiter.c | 19 +++++++++++++++++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
+index 001b818fe..c506f4cb5 100644
+--- a/grub-core/osdep/linux/getroot.c
++++ b/grub-core/osdep/linux/getroot.c
+@@ -963,6 +963,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
+ *pp = '\0';
+ return path;
+ }
++
++ /* If this is a FusionIO disk. */
++ if ((strncmp ("fio", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z')
++ {
++ char *pp = p + 3;
++ while (*pp >= 'a' && *pp <= 'z')
++ pp++;
++ if (*pp)
++ *is_part = 1;
++ /* /dev/fio[a-z]+[0-9]* */
++ *pp = '\0';
++ return path;
++ }
+ }
+
+ return path;
+diff --git a/util/deviceiter.c b/util/deviceiter.c
+index b5b9ac6ab..3a8f2770e 100644
+--- a/util/deviceiter.c
++++ b/util/deviceiter.c
+@@ -384,6 +384,12 @@ get_nvme_disk_name (char *name, int controller, int namespace)
+ {
+ sprintf (name, "/dev/nvme%dn%d", controller, namespace);
+ }
++
++static void
++get_fio_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/fio%c", unit + 'a');
++}
+ #endif
+
+ static struct seen_device
+@@ -929,6 +935,19 @@ grub_util_iterate_devices (int (*hook) (const char *, int, void *), void *hook_d
+ }
+ }
+
++ /* FusionIO. */
++ for (i = 0; i < 26; i++)
++ {
++ char name[16];
++
++ get_fio_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
+ # ifdef HAVE_DEVICE_MAPPER
+ # define dmraid_check(cond, ...) \
+ if (! (cond)) \
diff --git a/debian/patches/quick-boot-lvm.patch b/debian/patches/quick-boot-lvm.patch
new file mode 100644
index 0000000..6f3ac2d
--- /dev/null
+++ b/debian/patches/quick-boot-lvm.patch
@@ -0,0 +1,77 @@
+From 4f5e080c61055b04db3cdf8067cf180f193cf89f Mon Sep 17 00:00:00 2001
+From: Steve Langasek <steve.langasek@ubuntu.com>
+Date: Tue, 30 Oct 2018 15:04:16 -0700
+Subject: If we don't have writable grubenv and we're on EFI, always show the
+ menu
+
+If we don't have writable grubenv, recordfail doesn't work, which means our
+quickboot behavior - with a timeout of 0 - leaves the user without a
+reliable way to access the boot menu if they're on UEFI, because unlike
+BIOS, UEFI does not support checking the state of modifier keys (i.e.
+holding down shift at boot is not detectable).
+
+Handle this corner case by always using a non-zero timeout on EFI when
+save_env doesn't work.
+
+Reuse GRUB_RECORDFAIL_TIMEOUT to avoid introducing another variable.
+
+Signed-off-by: Steve Langasek <steve.langasek@canonical.com>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1800722
+Last-Update: 2019-06-24
+
+Patch-Name: quick-boot-lvm.patch
+---
+ util/grub.d/00_header.in | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
+index 674a76140..b7135b655 100644
+--- a/util/grub.d/00_header.in
++++ b/util/grub.d/00_header.in
+@@ -115,7 +115,7 @@ EOF
+ cat <<EOF
+ # GRUB lacks write support for $abstraction, so recordfail support is disabled.
+ EOF
+- return
++ return 1
+ ;;
+ esac
+ done
+@@ -126,7 +126,7 @@ EOF
+ cat <<EOF
+ # GRUB lacks write support for $FS, so recordfail support is disabled.
+ EOF
+- return
++ return 1
+ ;;
+ esac
+
+@@ -135,7 +135,9 @@ EOF
+ EOF
+ }
+
+- check_writable
++ if ! check_writable; then
++ recordfail_broken=1
++ fi
+
+ cat <<EOF
+ }
+@@ -379,6 +381,16 @@ EOF
+ fi
+ fi
+ EOF
++if [ "$recordfail_broken" = 1 ]; then
++ cat << EOF
++if [ \$grub_platform = efi ]; then
++ set timeout=${GRUB_RECORDFAIL_TIMEOUT:-30}
++ if [ x\$feature_timeout_style = xy ] ; then
++ set timeout_style=menu
++ fi
++fi
++EOF
++fi
+ }
+
+ if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then
diff --git a/debian/patches/quick-boot.patch b/debian/patches/quick-boot.patch
new file mode 100644
index 0000000..73860af
--- /dev/null
+++ b/debian/patches/quick-boot.patch
@@ -0,0 +1,358 @@
+From e760841d961fc46c5f7a82830d2e0eb6d4b53e8d Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:28 +0000
+Subject: Add configure option to bypass boot menu if possible
+
+If other operating systems are installed, then automatically unhide the
+menu. Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus if
+available to check whether Shift is pressed. If it is, show the menu,
+otherwise boot immediately. If keystatus is not available, then fall
+back to a short delay interruptible with Escape.
+
+This may or may not remain Ubuntu-specific, although it's not obviously
+wanted upstream. It implements a requirement of
+https://wiki.ubuntu.com/DesktopExperienceTeam/KarmicBootExperienceDesignSpec#Bootloader.
+
+If the previous boot failed (defined as failing to get to the end of one
+of the normal runlevels), then show the boot menu regardless.
+
+Author: Richard Laager <rlaager@wiktel.com>
+Author: Robie Basak <robie.basak@ubuntu.com>
+Forwarded: no
+Last-Update: 2015-09-04
+
+Patch-Name: quick-boot.patch
+---
+ configure.ac | 11 ++++++
+ docs/grub.texi | 14 +++++++
+ grub-core/normal/menu.c | 24 ++++++++++++
+ util/grub-mkconfig.in | 3 +-
+ util/grub.d/00_header.in | 77 +++++++++++++++++++++++++++++++------
+ util/grub.d/10_linux.in | 4 ++
+ util/grub.d/30_os-prober.in | 21 ++++++++++
+ 7 files changed, 141 insertions(+), 13 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 256fc44ef..c42e4c784 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1926,6 +1926,17 @@ else
+ fi
+ AC_SUBST([QUIET_BOOT])
+
++AC_ARG_ENABLE([quick-boot],
++ [AS_HELP_STRING([--enable-quick-boot],
++ [bypass boot menu if possible (default=no)])],
++ [], [enable_quick_boot=no])
++if test x"$enable_quick_boot" = xyes ; then
++ QUICK_BOOT=1
++else
++ QUICK_BOOT=0
++fi
++AC_SUBST([QUICK_BOOT])
++
+ LIBS=""
+
+ AC_SUBST([FONT_SOURCE])
+diff --git a/docs/grub.texi b/docs/grub.texi
+index f8b4b3b21..0b58dafb2 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -1563,6 +1563,20 @@ This option may be set to a list of GRUB module names separated by spaces.
+ Each module will be loaded as early as possible, at the start of
+ @file{grub.cfg}.
+
++@item GRUB_RECORDFAIL_TIMEOUT
++If this option is set, it overrides the default recordfail setting. A
++setting of -1 causes GRUB to wait for user input indefinitely. However, a
++false positive in the recordfail mechanism may occur if power is lost during
++boot before boot success is recorded in userspace. The default setting is
++30, which causes GRUB to wait for user input for thirty seconds before
++continuing. This default allows interactive users the opportunity to switch
++to a different, working kernel, while avoiding a false positive causing the
++boot to block indefinitely on headless and appliance systems where access to
++a console is restricted or limited.
++
++This option is only effective when GRUB was configured with the
++@option{--enable-quick-boot} option.
++
+ @end table
+
+ The following options are still accepted for compatibility with existing
+diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
+index e9d8444b5..0440340b8 100644
+--- a/grub-core/normal/menu.c
++++ b/grub-core/normal/menu.c
+@@ -603,6 +603,30 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
+ static struct grub_term_coordinate *pos;
+ int entry = -1;
+
++ if (timeout == 0)
++ {
++ /* If modifier key statuses can't be detected without a delay,
++ then a hidden timeout of zero cannot be interrupted in any way,
++ which is not very helpful. Bump it to three seconds in this
++ case to give the user a fighting chance. */
++ grub_term_input_t term;
++ int nterms = 0;
++ int mods_detectable = 1;
++
++ FOR_ACTIVE_TERM_INPUTS(term)
++ {
++ if (!term->getkeystatus)
++ {
++ mods_detectable = 0;
++ break;
++ }
++ else
++ nterms++;
++ }
++ if (!mods_detectable || !nterms)
++ timeout = 3;
++ }
++
+ if (timeout_style == TIMEOUT_STYLE_COUNTDOWN && timeout)
+ {
+ pos = grub_term_save_pos ();
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index 0265a5a66..fa9c53a92 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -256,7 +256,8 @@ export GRUB_DEFAULT \
+ GRUB_ENABLE_CRYPTODISK \
+ GRUB_BADRAM \
+ GRUB_OS_PROBER_SKIP_LIST \
+- GRUB_DISABLE_SUBMENU
++ GRUB_DISABLE_SUBMENU \
++ GRUB_RECORDFAIL_TIMEOUT
+
+ if test "x${grub_cfg}" != "x"; then
+ rm -f "${grub_cfg}.new"
+diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
+index 93a90233e..674a76140 100644
+--- a/util/grub.d/00_header.in
++++ b/util/grub.d/00_header.in
+@@ -21,6 +21,8 @@ prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ datarootdir="@datarootdir@"
+ grub_lang=`echo $LANG | cut -d . -f 1`
++grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`"
++quick_boot="@QUICK_BOOT@"
+
+ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+@@ -44,6 +46,7 @@ if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT
+
+ cat << EOF
+ if [ -s \$prefix/grubenv ]; then
++ set have_grubenv=true
+ load_env
+ fi
+ EOF
+@@ -96,7 +99,50 @@ function savedefault {
+ save_env saved_entry
+ fi
+ }
++EOF
++
++if [ "$quick_boot" = 1 ]; then
++ cat <<EOF
++function recordfail {
++ set recordfail=1
++EOF
++
++ check_writable () {
++ abstractions="$(grub-probe --target=abstraction "${grubdir}")"
++ for abstraction in $abstractions; do
++ case "$abstraction" in
++ diskfilter | lvm)
++ cat <<EOF
++ # GRUB lacks write support for $abstraction, so recordfail support is disabled.
++EOF
++ return
++ ;;
++ esac
++ done
++
++ FS="$(grub-probe --target=fs "${grubdir}")"
++ case "$FS" in
++ btrfs | cpiofs | newc | odc | romfs | squash4 | tarfs | zfs)
++ cat <<EOF
++ # GRUB lacks write support for $FS, so recordfail support is disabled.
++EOF
++ return
++ ;;
++ esac
++
++ cat <<EOF
++ if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
++EOF
++ }
++
++ check_writable
+
++ cat <<EOF
++}
++EOF
++fi
++
++cat <<EOF
+ function load_video {
+ EOF
+ if [ -n "${GRUB_VIDEO_BACKEND}" ]; then
+@@ -282,10 +328,16 @@ fi
+
+ make_timeout ()
+ {
++ cat << EOF
++if [ "\${recordfail}" = 1 ] ; then
++ set timeout=${GRUB_RECORDFAIL_TIMEOUT:-30}
++else
++EOF
+ if [ "x${3}" != "x" ] ; then
+ timeout="${2}"
+ style="${3}"
+- elif [ "x${1}" != "x" ] && [ "x${1}" != "x0" ] ; then
++ elif [ "x${1}" != "x" ] && \
++ ([ "$quick_boot" = 1 ] || [ "x${1}" != "x0" ]) ; then
+ # Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme.
+ timeout="${1}"
+ if [ "x${2}" != "x0" ] ; then
+@@ -304,26 +356,27 @@ make_timeout ()
+ style="menu"
+ fi
+ cat << EOF
+-if [ x\$feature_timeout_style = xy ] ; then
+- set timeout_style=${style}
+- set timeout=${timeout}
++ if [ x\$feature_timeout_style = xy ] ; then
++ set timeout_style=${style}
++ set timeout=${timeout}
+ EOF
+ if [ "x${style}" = "xmenu" ] ; then
+ cat << EOF
+-# Fallback normal timeout code in case the timeout_style feature is
+-# unavailable.
+-else
+- set timeout=${timeout}
++ # Fallback normal timeout code in case the timeout_style feature is
++ # unavailable.
++ else
++ set timeout=${timeout}
+ EOF
+ else
+ cat << EOF
+-# Fallback hidden-timeout code in case the timeout_style feature is
+-# unavailable.
+-elif sleep${verbose} --interruptible ${timeout} ; then
+- set timeout=0
++ # Fallback hidden-timeout code in case the timeout_style feature is
++ # unavailable.
++ elif sleep${verbose} --interruptible ${timeout} ; then
++ set timeout=0
+ EOF
+ fi
+ cat << EOF
++ fi
+ fi
+ EOF
+ }
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 869a7eec5..80315a31b 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -22,6 +22,7 @@ exec_prefix="@exec_prefix@"
+ datarootdir="@datarootdir@"
+ ubuntu_recovery="@UBUNTU_RECOVERY@"
+ quiet_boot="@QUIET_BOOT@"
++quick_boot="@QUICK_BOOT@"
+
+ . "$pkgdatadir/grub-mkconfig_lib"
+
+@@ -129,6 +130,9 @@ linux_entry ()
+ else
+ echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ fi
++ if [ "$quick_boot" = 1 ]; then
++ echo " recordfail" | sed "s/^/$submenu_indentation/"
++ fi
+ if [ x$type != xrecovery ] ; then
+ save_default_entry | grub_add_tab
+ fi
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 98aee403e..225a3baf7 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -20,12 +20,26 @@ set -e
+ prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ datarootdir="@datarootdir@"
++quick_boot="@QUICK_BOOT@"
+
+ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+
+ . "$pkgdatadir/grub-mkconfig_lib"
+
++found_other_os=
++
++adjust_timeout () {
++ if [ "$quick_boot" = 1 ] && [ "x${found_other_os}" != "x" ]; then
++ cat << EOF
++set timeout_style=menu
++if [ "\${timeout}" = 0 ]; then
++ set timeout=10
++fi
++EOF
++ fi
++}
++
+ if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
+ grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.")"
+ exit 0
+@@ -45,6 +59,7 @@ if [ -z "${OSPROBED}" ] ; then
+ fi
+
+ osx_entry() {
++ found_other_os=1
+ if [ x$2 = x32 ]; then
+ # TRANSLATORS: it refers to kernel architecture (32-bit)
+ bitstr="$(gettext "(32-bit)")"
+@@ -168,6 +183,7 @@ for OS in ${OSPROBED} ; do
+ ;;
+ esac
+
++ found_other_os=1
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ cat << EOF
+ menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' $CLASS --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' {
+@@ -198,6 +214,7 @@ EOF
+ ;;
+ efi)
+
++ found_other_os=1
+ EFIPATH=${DEVICE#*@}
+ DEVICE=${DEVICE%@*}
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+@@ -246,6 +263,7 @@ EOF
+ [ "${prepare_boot_cache}" ] || continue
+ fi
+
++ found_other_os=1
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true
+ counter=1
+@@ -322,6 +340,7 @@ EOF
+ fi
+ ;;
+ hurd)
++ found_other_os=1
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ cat << EOF
+ menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' {
+@@ -364,3 +383,5 @@ EOF
+ ;;
+ esac
+ done
++
++adjust_timeout
diff --git a/debian/patches/restore-mkdevicemap.patch b/debian/patches/restore-mkdevicemap.patch
new file mode 100644
index 0000000..3822430
--- /dev/null
+++ b/debian/patches/restore-mkdevicemap.patch
@@ -0,0 +1,1326 @@
+From a7b960126fbc0d4541babe5553546e5f9530ac48 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 13 Jan 2014 12:13:01 +0000
+Subject: Restore grub-mkdevicemap
+
+This is kind of a mess, requiring lots of OS-specific code to iterate
+over all possible devices. However, we use it in a number of scripts to
+discover devices and reimplementing those in terms of something else
+would be very complicated.
+
+Author: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
+Forwarded: no
+Last-Update: 2021-09-24
+
+Patch-Name: restore-mkdevicemap.patch
+---
+ Makefile.util.def | 17 +
+ docs/man/grub-mkdevicemap.h2m | 4 +
+ include/grub/util/deviceiter.h | 14 +
+ util/deviceiter.c | 1027 ++++++++++++++++++++++++++++++++
+ util/devicemap.c | 13 +
+ util/grub-mkdevicemap.c | 181 ++++++
+ 6 files changed, 1256 insertions(+)
+ create mode 100644 docs/man/grub-mkdevicemap.h2m
+ create mode 100644 include/grub/util/deviceiter.h
+ create mode 100644 util/deviceiter.c
+ create mode 100644 util/devicemap.c
+ create mode 100644 util/grub-mkdevicemap.c
+
+diff --git a/Makefile.util.def b/Makefile.util.def
+index f8b356cc1..27f948291 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -336,6 +336,23 @@ program = {
+ condition = COND_GRUB_MKFONT;
+ };
+
++program = {
++ name = grub-mkdevicemap;
++ installdir = sbin;
++ mansection = 8;
++
++ common = util/grub-mkdevicemap.c;
++ common = util/deviceiter.c;
++ common = util/devicemap.c;
++ common = grub-core/osdep/init.c;
++
++ ldadd = libgrubmods.a;
++ ldadd = libgrubgcry.a;
++ ldadd = libgrubkern.a;
++ ldadd = grub-core/lib/gnulib/libgnu.a;
++ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
++};
++
+ program = {
+ name = grub-probe;
+ installdir = sbin;
+diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m
+new file mode 100644
+index 000000000..96cd6ee72
+--- /dev/null
++++ b/docs/man/grub-mkdevicemap.h2m
+@@ -0,0 +1,4 @@
++[NAME]
++grub-mkdevicemap \- make a device map file automatically
++[SEE ALSO]
++.BR grub-probe (8)
+diff --git a/include/grub/util/deviceiter.h b/include/grub/util/deviceiter.h
+new file mode 100644
+index 000000000..85374978c
+--- /dev/null
++++ b/include/grub/util/deviceiter.h
+@@ -0,0 +1,14 @@
++#ifndef GRUB_DEVICEITER_MACHINE_UTIL_HEADER
++#define GRUB_DEVICEITER_MACHINE_UTIL_HEADER 1
++
++#include <config.h>
++
++typedef int (*grub_util_iterate_devices_hook_t) (const char *name,
++ int is_floppy, void *data);
++
++void grub_util_iterate_devices (grub_util_iterate_devices_hook_t hook,
++ void *hook_data, int floppy_disks);
++void grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy,
++ int *num_fd, int *num_hd);
++
++#endif /* ! GRUB_DEVICEITER_MACHINE_UTIL_HEADER */
+diff --git a/util/deviceiter.c b/util/deviceiter.c
+new file mode 100644
+index 000000000..b5b9ac6ab
+--- /dev/null
++++ b/util/deviceiter.c
+@@ -0,0 +1,1027 @@
++/* deviceiter.c - iterate over system devices */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2011 Free Software Foundation, Inc.
++ *
++ * GRUB is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GRUB is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <dirent.h>
++
++#include <grub/util/misc.h>
++#include <grub/util/deviceiter.h>
++#include <grub/list.h>
++#include <grub/misc.h>
++#include <grub/emu/misc.h>
++#include <grub/safemath.h>
++
++#ifdef __linux__
++# if !defined(__GLIBC__) || \
++ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
++/* Maybe libc doesn't have large file support. */
++# include <linux/unistd.h> /* _llseek */
++# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
++# include <sys/ioctl.h> /* ioctl */
++# ifndef HDIO_GETGEO
++# define HDIO_GETGEO 0x0301 /* get device geometry */
++/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
++ defined. */
++struct hd_geometry
++{
++ unsigned char heads;
++ unsigned char sectors;
++ unsigned short cylinders;
++ unsigned long start;
++};
++# endif /* ! HDIO_GETGEO */
++# ifndef FLOPPY_MAJOR
++# define FLOPPY_MAJOR 2 /* the major number for floppy */
++# endif /* ! FLOPPY_MAJOR */
++# ifndef MAJOR
++# define MAJOR(dev) \
++ ({ \
++ unsigned long long __dev = (dev); \
++ (unsigned) ((__dev >> 8) & 0xfff) \
++ | ((unsigned int) (__dev >> 32) & ~0xfff); \
++ })
++# endif /* ! MAJOR */
++# ifndef MINOR
++# define MINOR(dev) \
++ ({ \
++ unsigned long long __dev = (dev); \
++ (unsigned) (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); \
++ })
++# endif /* ! MINOR */
++# ifndef CDROM_GET_CAPABILITY
++# define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
++# endif /* ! CDROM_GET_CAPABILITY */
++# ifndef BLKGETSIZE
++# define BLKGETSIZE _IO(0x12,96) /* return device size */
++# endif /* ! BLKGETSIZE */
++
++#ifdef HAVE_DEVICE_MAPPER
++# include <libdevmapper.h>
++# pragma GCC diagnostic ignored "-Wcast-align"
++#endif
++#endif /* __linux__ */
++
++/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
++ kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
++#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
++# define __FreeBSD_kernel__
++#endif
++#ifdef __FreeBSD_kernel__
++ /* Obtain version of kFreeBSD headers */
++# include <osreldate.h>
++# ifndef __FreeBSD_kernel_version
++# define __FreeBSD_kernel_version __FreeBSD_version
++# endif
++
++ /* Runtime detection of kernel */
++# include <sys/utsname.h>
++static int
++get_kfreebsd_version (void)
++{
++ struct utsname uts;
++ int major;
++ int minor;
++ int v[2];
++
++ uname (&uts);
++ sscanf (uts.release, "%d.%d", &major, &minor);
++
++ if (major >= 9)
++ major = 9;
++ if (major >= 5)
++ {
++ v[0] = minor/10; v[1] = minor%10;
++ }
++ else
++ {
++ v[0] = minor%10; v[1] = minor/10;
++ }
++ return major*100000+v[0]*10000+v[1]*1000;
++}
++#endif /* __FreeBSD_kernel__ */
++
++#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
++# include <sys/ioctl.h> /* ioctl */
++# include <sys/disklabel.h>
++# include <sys/cdio.h> /* CDIOCCLRDEBUG */
++# if defined(__FreeBSD_kernel__)
++# include <sys/param.h>
++# if __FreeBSD_kernel_version >= 500040
++# include <sys/disk.h>
++# endif
++# endif /* __FreeBSD_kernel__ */
++#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
++
++#ifdef HAVE_OPENDISK
++# include <util.h>
++#endif /* HAVE_OPENDISK */
++
++#ifdef __linux__
++/* Check if we have devfs support. */
++static int
++have_devfs (void)
++{
++ struct stat st;
++ return stat ("/dev/.devfsd", &st) == 0;
++}
++#endif /* __linux__ */
++
++/* These three functions are quite different among OSes. */
++static void
++get_floppy_disk_name (char *name, int unit)
++{
++#if defined(__linux__)
++ /* GNU/Linux */
++ if (have_devfs ())
++ sprintf (name, "/dev/floppy/%d", unit);
++ else
++ sprintf (name, "/dev/fd%d", unit);
++#elif defined(__GNU__)
++ /* GNU/Hurd */
++ sprintf (name, "/dev/fd%d", unit);
++#elif defined(__FreeBSD_kernel__)
++ /* kFreeBSD */
++ if (get_kfreebsd_version () >= 400000)
++ sprintf (name, "/dev/fd%d", unit);
++ else
++ sprintf (name, "/dev/rfd%d", unit);
++#elif defined(__NetBSD__)
++ /* NetBSD */
++ /* opendisk() doesn't work for floppies. */
++ sprintf (name, "/dev/rfd%da", unit);
++#elif defined(__OpenBSD__)
++ /* OpenBSD */
++ sprintf (name, "/dev/rfd%dc", unit);
++#elif defined(__QNXNTO__)
++ /* QNX RTP */
++ sprintf (name, "/dev/fd%d", unit);
++#elif defined(__CYGWIN__)
++ /* Cygwin */
++ sprintf (name, "/dev/fd%d", unit);
++#elif defined(__MINGW32__)
++ (void) unit;
++ *name = 0;
++#else
++# warning "BIOS floppy drives cannot be guessed in your operating system."
++ /* Set NAME to a bogus string. */
++ *name = 0;
++#endif
++}
++
++static void
++get_ide_disk_name (char *name, int unit)
++{
++#if defined(__linux__)
++ /* GNU/Linux */
++ sprintf (name, "/dev/hd%c", unit + 'a');
++#elif defined(__GNU__)
++ /* GNU/Hurd */
++ sprintf (name, "/dev/hd%d", unit);
++#elif defined(__FreeBSD_kernel__)
++ /* kFreeBSD */
++ if (get_kfreebsd_version () >= 400000)
++ sprintf (name, "/dev/ad%d", unit);
++ else
++ sprintf (name, "/dev/rwd%d", unit);
++#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
++ /* NetBSD */
++ char shortname[16];
++ int fd;
++
++ sprintf (shortname, "wd%d", unit);
++ fd = opendisk (shortname, O_RDONLY, name,
++ 16, /* length of NAME */
++ 0 /* char device */
++ );
++ close (fd);
++#elif defined(__OpenBSD__)
++ /* OpenBSD */
++ sprintf (name, "/dev/rwd%dc", unit);
++#elif defined(__QNXNTO__)
++ /* QNX RTP */
++ /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
++ contain SCSI disks. */
++ sprintf (name, "/dev/hd%d", unit);
++#elif defined(__CYGWIN__)
++ /* Cygwin emulates all disks as /dev/sdX. */
++ (void) unit;
++ *name = 0;
++#elif defined(__MINGW32__)
++ sprintf (name, "//./PHYSICALDRIVE%d", unit);
++#else
++# warning "BIOS IDE drives cannot be guessed in your operating system."
++ /* Set NAME to a bogus string. */
++ *name = 0;
++#endif
++}
++
++static void
++get_scsi_disk_name (char *name, int unit)
++{
++#if defined(__linux__)
++ /* GNU/Linux */
++ sprintf (name, "/dev/sd%c", unit + 'a');
++#elif defined(__GNU__)
++ /* GNU/Hurd */
++ sprintf (name, "/dev/sd%d", unit);
++#elif defined(__FreeBSD_kernel__)
++ /* kFreeBSD */
++ if (get_kfreebsd_version () >= 400000)
++ sprintf (name, "/dev/da%d", unit);
++ else
++ sprintf (name, "/dev/rda%d", unit);
++#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
++ /* NetBSD */
++ char shortname[16];
++ int fd;
++
++ sprintf (shortname, "sd%d", unit);
++ fd = opendisk (shortname, O_RDONLY, name,
++ 16, /* length of NAME */
++ 0 /* char device */
++ );
++ close (fd);
++#elif defined(__OpenBSD__)
++ /* OpenBSD */
++ sprintf (name, "/dev/rsd%dc", unit);
++#elif defined(__QNXNTO__)
++ /* QNX RTP */
++ /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
++ disable the detection of SCSI disks here. */
++ *name = 0;
++#elif defined(__CYGWIN__)
++ /* Cygwin emulates all disks as /dev/sdX. */
++ sprintf (name, "/dev/sd%c", unit + 'a');
++#elif defined(__MINGW32__)
++ (void) unit;
++ *name = 0;
++#else
++# warning "BIOS SCSI drives cannot be guessed in your operating system."
++ /* Set NAME to a bogus string. */
++ *name = 0;
++#endif
++}
++
++#ifdef __FreeBSD_kernel__
++static void
++get_ada_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/ada%d", unit);
++}
++
++static void
++get_ataraid_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/ar%d", unit);
++}
++
++static void
++get_mfi_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/mfid%d", unit);
++}
++
++static void
++get_virtio_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/vtbd%d", unit);
++}
++
++static void
++get_xvd_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/xbd%d", unit);
++}
++#endif
++
++#ifdef __linux__
++static void
++get_virtio_disk_name (char *name, int unit)
++{
++#ifdef __sparc__
++ sprintf (name, "/dev/vdisk%c", unit + 'a');
++#else
++ sprintf (name, "/dev/vd%c", unit + 'a');
++#endif
++}
++
++static void
++get_dac960_disk_name (char *name, int controller, int drive)
++{
++ sprintf (name, "/dev/rd/c%dd%d", controller, drive);
++}
++
++static void
++get_acceleraid_disk_name (char *name, int controller, int drive)
++{
++ sprintf (name, "/dev/rs/c%dd%d", controller, drive);
++}
++
++static void
++get_ataraid_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/ataraid/d%c", unit + '0');
++}
++
++static void
++get_i2o_disk_name (char *name, char unit)
++{
++ sprintf (name, "/dev/i2o/hd%c", unit);
++}
++
++static void
++get_cciss_disk_name (char *name, int controller, int drive)
++{
++ sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
++}
++
++static void
++get_ida_disk_name (char *name, int controller, int drive)
++{
++ sprintf (name, "/dev/ida/c%dd%d", controller, drive);
++}
++
++static void
++get_mmc_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/mmcblk%d", unit);
++}
++
++static void
++get_xvd_disk_name (char *name, int unit)
++{
++ sprintf (name, "/dev/xvd%c", unit + 'a');
++}
++
++static void
++get_nvme_disk_name (char *name, int controller, int namespace)
++{
++ sprintf (name, "/dev/nvme%dn%d", controller, namespace);
++}
++#endif
++
++static struct seen_device
++{
++ struct seen_device *next;
++ struct seen_device **prev;
++ const char *name;
++} *seen;
++
++/* Check if DEVICE can be read. Skip any DEVICE that we have already seen.
++ If an error occurs, return zero, otherwise return non-zero. */
++static int
++check_device_readable_unique (const char *device)
++{
++ char *real_device;
++ char buf[512];
++ FILE *fp;
++ struct seen_device *seen_elt;
++
++ /* If DEVICE is empty, just return error. */
++ if (*device == 0)
++ return 0;
++
++ /* Have we seen this device already? */
++ real_device = canonicalize_file_name (device);
++ if (! real_device)
++ return 0;
++ if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), real_device))
++ {
++ grub_dprintf ("deviceiter", "Already seen %s (%s)\n",
++ device, real_device);
++ goto fail;
++ }
++
++ fp = fopen (device, "r");
++ if (! fp)
++ {
++ switch (errno)
++ {
++#ifdef ENOMEDIUM
++ case ENOMEDIUM:
++# if 0
++ /* At the moment, this finds only CDROMs, which can't be
++ read anyway, so leave it out. Code should be
++ reactivated if `removable disks' and CDROMs are
++ supported. */
++ /* Accept it, it may be inserted. */
++ return 1;
++# endif
++ break;
++#endif /* ENOMEDIUM */
++ default:
++ /* Break case and leave. */
++ break;
++ }
++ /* Error opening the device. */
++ goto fail;
++ }
++
++ /* Make sure CD-ROMs don't get assigned a BIOS disk number
++ before SCSI disks! */
++#ifdef __linux__
++# ifdef CDROM_GET_CAPABILITY
++ if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
++ goto fail;
++# else /* ! CDROM_GET_CAPABILITY */
++ /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */
++ {
++ struct hd_geometry hdg;
++ struct stat st;
++
++ if (fstat (fileno (fp), &st))
++ goto fail;
++
++ /* If it is a block device and isn't a floppy, check if HDIO_GETGEO
++ succeeds. */
++ if (S_ISBLK (st.st_mode)
++ && MAJOR (st.st_rdev) != FLOPPY_MAJOR
++ && ioctl (fileno (fp), HDIO_GETGEO, &hdg))
++ goto fail;
++ }
++# endif /* ! CDROM_GET_CAPABILITY */
++#endif /* __linux__ */
++
++#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
++# ifdef CDIOCCLRDEBUG
++ if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
++ goto fail;
++# endif /* CDIOCCLRDEBUG */
++#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
++
++ /* Attempt to read the first sector. */
++ if (fread (buf, 1, 512, fp) != 512)
++ {
++ fclose (fp);
++ goto fail;
++ }
++
++ /* Remember that we've seen this device. */
++ seen_elt = xmalloc (sizeof (*seen_elt));
++ seen_elt->name = real_device; /* steal memory */
++ grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt));
++
++ fclose (fp);
++ return 1;
++
++fail:
++ free (real_device);
++ return 0;
++}
++
++static void
++clear_seen_devices (void)
++{
++ while (seen)
++ {
++ struct seen_device *seen_elt = seen;
++ seen = seen->next;
++ free (seen_elt);
++ }
++ seen = NULL;
++}
++
++#ifdef __linux__
++struct device
++{
++ char *stable;
++ char *kernel;
++};
++
++/* Sort by the kernel name for preference since that most closely matches
++ older device.map files, but sort by stable by-id names as a fallback.
++ This is because /dev/disk/by-id/ usually has a few alternative
++ identifications of devices (e.g. ATA vs. SATA).
++ check_device_readable_unique will ensure that we only get one for any
++ given disk, but sort the list so that the choice of which one we get is
++ stable. */
++static int
++compare_devices (const void *a, const void *b)
++{
++ const struct device *left = (const struct device *) a;
++ const struct device *right = (const struct device *) b;
++
++ if (left->kernel && right->kernel)
++ {
++ int ret = strcmp (left->kernel, right->kernel);
++ if (ret)
++ return ret;
++ }
++
++ return strcmp (left->stable, right->stable);
++}
++#endif /* __linux__ */
++
++void
++grub_util_iterate_devices (int (*hook) (const char *, int, void *), void *hook_data,
++ int floppy_disks)
++{
++ int i;
++
++ clear_seen_devices ();
++
++ /* Floppies. */
++ for (i = 0; i < floppy_disks; i++)
++ {
++ char name[32];
++ struct stat st;
++
++ get_floppy_disk_name (name, i);
++ if (stat (name, &st) < 0)
++ break;
++ /* In floppies, write the map, whether check_device_readable_unique
++ succeeds or not, because the user just may not insert floppies. */
++ if (hook (name, 1, hook_data))
++ goto out;
++ }
++
++#ifdef __linux__
++ {
++ DIR *dir = opendir ("/dev/disk/by-id");
++
++ if (dir)
++ {
++ struct dirent *entry;
++ struct device *devs;
++ size_t devs_len = 0, devs_max = 1024, dev;
++
++ devs = xcalloc (devs_max, sizeof (*devs));
++
++ /* Dump all the directory entries into names, resizing if
++ necessary. */
++ for (entry = readdir (dir); entry; entry = readdir (dir))
++ {
++ /* Skip current and parent directory entries. */
++ if (strcmp (entry->d_name, ".") == 0 ||
++ strcmp (entry->d_name, "..") == 0)
++ continue;
++ /* Skip partition entries. */
++ if (strstr (entry->d_name, "-part"))
++ continue;
++ /* Skip device-mapper entries; we'll handle the ones we want
++ later. */
++ if (strncmp (entry->d_name, "dm-", sizeof ("dm-") - 1) == 0)
++ continue;
++ /* Skip RAID entries; they are handled by upper layers. */
++ if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0)
++ continue;
++ if (devs_len >= devs_max)
++ {
++ size_t sz;
++
++ devs_max *= 2;
++ sz = devs_max;
++ if (grub_mul (sz, sizeof (*devs), &sz))
++ grub_util_error ("%s", _("overflow is detected"));
++ devs = xrealloc (devs, sz);
++ }
++ devs[devs_len].stable =
++ xasprintf ("/dev/disk/by-id/%s", entry->d_name);
++ devs[devs_len].kernel =
++ canonicalize_file_name (devs[devs_len].stable);
++ devs_len++;
++ }
++
++ qsort (devs, devs_len, sizeof (*devs), &compare_devices);
++
++ closedir (dir);
++
++ /* Now add all the devices in sorted order. */
++ for (dev = 0; dev < devs_len; ++dev)
++ {
++ if (check_device_readable_unique (devs[dev].stable))
++ {
++ if (hook (devs[dev].stable, 0, hook_data))
++ goto out;
++ }
++ free (devs[dev].stable);
++ free (devs[dev].kernel);
++ }
++ free (devs);
++ }
++ }
++
++ if (have_devfs ())
++ {
++ i = 0;
++ while (1)
++ {
++ char discn[32];
++ char name[PATH_MAX];
++ struct stat st;
++
++ /* Linux creates symlinks "/dev/discs/discN" for convenience.
++ The way to number disks is the same as GRUB's. */
++ sprintf (discn, "/dev/discs/disc%d", i++);
++ if (stat (discn, &st) < 0)
++ break;
++
++ if (realpath (discn, name))
++ {
++ strcat (name, "/disc");
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ goto out;
++ }
++#endif /* __linux__ */
++
++ /* IDE disks. */
++ for (i = 0; i < 96; i++)
++ {
++ char name[16];
++
++ get_ide_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++#ifdef __FreeBSD_kernel__
++ /* IDE disks using ATA Direct Access driver. */
++ if (get_kfreebsd_version () >= 800000)
++ for (i = 0; i < 96; i++)
++ {
++ char name[16];
++
++ get_ada_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* ATARAID disks. */
++ for (i = 0; i < 8; i++)
++ {
++ char name[20];
++
++ get_ataraid_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* LSI MegaRAID SAS. */
++ for (i = 0; i < 32; i++)
++ {
++ char name[20];
++
++ get_mfi_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* Virtio disks. */
++ for (i = 0; i < 96; i++)
++ {
++ char name[16];
++
++ get_virtio_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* Xen virtual block devices. */
++ for (i = 0; i < 96; i++)
++ {
++ char name[16];
++
++ get_xvd_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++#endif
++
++#ifdef __linux__
++ /* Virtio disks. */
++ for (i = 0; i < 26; i++)
++ {
++ char name[16];
++
++ get_virtio_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* ATARAID disks. */
++ for (i = 0; i < 8; i++)
++ {
++ char name[20];
++
++ get_ataraid_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* Xen virtual block devices. */
++ for (i = 0; i < 26; i++)
++ {
++ char name[16];
++
++ get_xvd_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++#endif /* __linux__ */
++
++ /* The rest is SCSI disks. */
++ for (i = 0; i < 48; i++)
++ {
++ char name[16];
++
++ get_scsi_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++#ifdef __linux__
++ /* This is for DAC960 - we have
++ /dev/rd/c<controller>d<logical drive>p<partition>.
++
++ DAC960 driver currently supports up to 8 controllers, 32 logical
++ drives, and 7 partitions. */
++ {
++ int controller, drive;
++
++ for (controller = 0; controller < 8; controller++)
++ {
++ for (drive = 0; drive < 15; drive++)
++ {
++ char name[24];
++
++ get_dac960_disk_name (name, controller, drive);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ }
++ }
++
++ /* This is for Mylex Acceleraid - we have
++ /dev/rd/c<controller>d<logical drive>p<partition>. */
++ {
++ int controller, drive;
++
++ for (controller = 0; controller < 8; controller++)
++ {
++ for (drive = 0; drive < 15; drive++)
++ {
++ char name[24];
++
++ get_acceleraid_disk_name (name, controller, drive);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ }
++ }
++
++ /* This is for CCISS - we have
++ /dev/cciss/c<controller>d<logical drive>p<partition>. */
++ {
++ int controller, drive;
++
++ for (controller = 0; controller < 3; controller++)
++ {
++ for (drive = 0; drive < 16; drive++)
++ {
++ char name[24];
++
++ get_cciss_disk_name (name, controller, drive);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ }
++ }
++
++ /* This is for Compaq Intelligent Drive Array - we have
++ /dev/ida/c<controller>d<logical drive>p<partition>. */
++ {
++ int controller, drive;
++
++ for (controller = 0; controller < 3; controller++)
++ {
++ for (drive = 0; drive < 16; drive++)
++ {
++ char name[24];
++
++ get_ida_disk_name (name, controller, drive);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ }
++ }
++
++ /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
++ {
++ char unit;
++
++ for (unit = 'a'; unit < 'f'; unit++)
++ {
++ char name[24];
++
++ get_i2o_disk_name (name, unit);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ }
++
++ /* MultiMediaCard (MMC). */
++ for (i = 0; i < 10; i++)
++ {
++ char name[16];
++
++ get_mmc_disk_name (name, i);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++
++ /* This is for standard NVMe controllers
++ /dev/nvme<controller>n<namespace>p<partition>. No idea about
++ actual limits of how many controllers a system can have and/or
++ how many namespace that would be, 10 for now. */
++ {
++ int controller, namespace;
++
++ for (controller = 0; controller < 10; controller++)
++ {
++ for (namespace = 0; namespace < 10; namespace++)
++ {
++ char name[16];
++
++ get_nvme_disk_name (name, controller, namespace);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ goto out;
++ }
++ }
++ }
++ }
++
++# ifdef HAVE_DEVICE_MAPPER
++# define dmraid_check(cond, ...) \
++ if (! (cond)) \
++ { \
++ grub_dprintf ("deviceiter", __VA_ARGS__); \
++ goto dmraid_end; \
++ }
++
++ /* DM-RAID. */
++ if (grub_device_mapper_supported ())
++ {
++ struct dm_tree *tree = NULL;
++ struct dm_task *task = NULL;
++ struct dm_names *names = NULL;
++ unsigned int next = 0;
++ void *top_handle, *second_handle;
++ struct dm_tree_node *root, *top, *second;
++
++ /* Build DM tree for all devices. */
++ tree = dm_tree_create ();
++ dmraid_check (tree, "dm_tree_create failed\n");
++ task = dm_task_create (DM_DEVICE_LIST);
++ dmraid_check (task, "dm_task_create failed\n");
++ dmraid_check (dm_task_run (task), "dm_task_run failed\n");
++ names = dm_task_get_names (task);
++ dmraid_check (names, "dm_task_get_names failed\n");
++ dmraid_check (names->dev, "No DM devices found\n");
++ do
++ {
++ names = (struct dm_names *) ((char *) names + next);
++ dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev),
++ MINOR (names->dev)),
++ "dm_tree_add_dev (%s) failed\n", names->name);
++ next = names->next;
++ }
++ while (next);
++
++ /* Walk the second-level children of the inverted tree; that is, devices
++ which are directly composed of non-DM devices such as hard disks.
++ This class includes all DM-RAID disks and excludes all DM-RAID
++ partitions. */
++ root = dm_tree_find_node (tree, 0, 0);
++ top_handle = NULL;
++ top = dm_tree_next_child (&top_handle, root, 1);
++ while (top)
++ {
++ second_handle = NULL;
++ second = dm_tree_next_child (&second_handle, top, 1);
++ while (second)
++ {
++ const char *node_name, *node_uuid;
++ char *name;
++
++ node_name = dm_tree_node_get_name (second);
++ dmraid_check (node_name, "dm_tree_node_get_name failed\n");
++ node_uuid = dm_tree_node_get_uuid (second);
++ dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n");
++ if (strstr (node_uuid, "DMRAID-") == 0)
++ {
++ grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name);
++ goto dmraid_next_child;
++ }
++
++ name = xasprintf ("/dev/mapper/%s", node_name);
++ if (check_device_readable_unique (name))
++ {
++ if (hook (name, 0, hook_data))
++ {
++ free (name);
++ if (task)
++ dm_task_destroy (task);
++ if (tree)
++ dm_tree_free (tree);
++ goto out;
++ }
++ }
++ free (name);
++
++dmraid_next_child:
++ second = dm_tree_next_child (&second_handle, top, 1);
++ }
++ top = dm_tree_next_child (&top_handle, root, 1);
++ }
++
++dmraid_end:
++ if (task)
++ dm_task_destroy (task);
++ if (tree)
++ dm_tree_free (tree);
++ }
++# endif /* HAVE_DEVICE_MAPPER */
++#endif /* __linux__ */
++
++out:
++ clear_seen_devices ();
++}
+diff --git a/util/devicemap.c b/util/devicemap.c
+new file mode 100644
+index 000000000..c61864420
+--- /dev/null
++++ b/util/devicemap.c
+@@ -0,0 +1,13 @@
++#include <stdio.h>
++
++#include <grub/util/deviceiter.h>
++
++void
++grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy,
++ int *num_fd, int *num_hd)
++{
++ if (is_floppy)
++ fprintf (fp, "(fd%d)\t%s\n", (*num_fd)++, name);
++ else
++ fprintf (fp, "(hd%d)\t%s\n", (*num_hd)++, name);
++}
+diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c
+new file mode 100644
+index 000000000..c4bbdbf69
+--- /dev/null
++++ b/util/grub-mkdevicemap.c
+@@ -0,0 +1,181 @@
++/* grub-mkdevicemap.c - make a device map file automatically */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
++ *
++ * GRUB is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GRUB is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <limits.h>
++
++#include <grub/emu/misc.h>
++#include <grub/emu/hostdisk.h>
++#include <grub/util/misc.h>
++#include <grub/util/deviceiter.h>
++#include <grub/env.h>
++#include <grub/i18n.h>
++
++#define _GNU_SOURCE 1
++#include <getopt.h>
++
++#include "progname.h"
++
++/* Context for make_device_map. */
++struct make_device_map_ctx
++{
++ FILE *fp;
++ int num_fd;
++ int num_hd;
++};
++
++/* Helper for make_device_map. */
++static int
++process_device (const char *name, int is_floppy, void *data)
++{
++ struct make_device_map_ctx *ctx = data;
++
++ grub_util_emit_devicemap_entry (ctx->fp, (char *) name,
++ is_floppy, &ctx->num_fd, &ctx->num_hd);
++ return 0;
++}
++
++static void
++make_device_map (const char *device_map, int floppy_disks)
++{
++ struct make_device_map_ctx ctx = {
++ .num_fd = 0,
++ .num_hd = 0
++ };
++
++ if (strcmp (device_map, "-") == 0)
++ ctx.fp = stdout;
++ else
++ ctx.fp = fopen (device_map, "w");
++
++ if (! ctx.fp)
++ grub_util_error (_("cannot open %s"), device_map);
++
++ grub_util_iterate_devices (process_device, &ctx, floppy_disks);
++
++ if (ctx.fp != stdout)
++ fclose (ctx.fp);
++}
++
++static struct option options[] =
++ {
++ {"device-map", required_argument, 0, 'm'},
++ {"probe-second-floppy", no_argument, 0, 's'},
++ {"no-floppy", no_argument, 0, 'n'},
++ {"help", no_argument, 0, 'h'},
++ {"version", no_argument, 0, 'V'},
++ {"verbose", no_argument, 0, 'v'},
++ {0, 0, 0, 0}
++ };
++
++static void
++usage (int status)
++{
++ if (status)
++ fprintf (stderr,
++ _("Try `%s --help' for more information.\n"), program_name);
++ else
++ printf (_("\
++Usage: %s [OPTION]...\n\
++\n\
++Generate a device map file automatically.\n\
++\n\
++ -n, --no-floppy do not probe any floppy drive\n\
++ -s, --probe-second-floppy probe the second floppy drive\n\
++ -m, --device-map=FILE use FILE as the device map [default=%s]\n\
++ -h, --help display this message and exit\n\
++ -V, --version print version information and exit\n\
++ -v, --verbose print verbose messages\n\
++\n\
++Report bugs to <%s>.\n\
++"), program_name,
++ DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
++
++ exit (status);
++}
++
++int
++main (int argc, char *argv[])
++{
++ char *dev_map = 0;
++ int floppy_disks = 1;
++
++ grub_util_host_init (&argc, &argv);
++
++ /* Check for options. */
++ while (1)
++ {
++ int c = getopt_long (argc, argv, "snm:r:hVv", options, 0);
++
++ if (c == -1)
++ break;
++ else
++ switch (c)
++ {
++ case 'm':
++ if (dev_map)
++ free (dev_map);
++
++ dev_map = xstrdup (optarg);
++ break;
++
++ case 'n':
++ floppy_disks = 0;
++ break;
++
++ case 's':
++ floppy_disks = 2;
++ break;
++
++ case 'h':
++ usage (0);
++ break;
++
++ case 'V':
++ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
++ return 0;
++
++ case 'v':
++ verbosity++;
++ break;
++
++ default:
++ usage (1);
++ break;
++ }
++ }
++
++ if (verbosity > 1)
++ grub_env_set ("debug", "all");
++
++ make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
++
++ free (dev_map);
++
++ return 0;
++}
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..714292a
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,129 @@
+olpc-prefix-hack.patch
+core-in-fs.patch
+dpkg-version-comparison.patch
+grub-legacy-0-based-partitions.patch
+disable-floppies.patch
+grub.cfg-400.patch
+gfxpayload-keep-default.patch
+install-stage2-confusion.patch
+mkrescue-efi-modules.patch
+mkconfig-loopback.patch
+restore-mkdevicemap.patch
+gettext-quiet.patch
+install-efi-fallback.patch
+mkconfig-ubuntu-recovery.patch
+install-locale-langpack.patch
+mkconfig-nonexistent-loopback.patch
+default-grub-d.patch
+blacklist-1440x900x32.patch
+mkconfig-ubuntu-distributor.patch
+linuxefi.patch
+mkconfig-signed-kernel.patch
+install-signed.patch
+wubi-no-windows.patch
+maybe-quiet.patch
+install-efi-adjust-distributor.patch
+quick-boot.patch
+quick-boot-lvm.patch
+gfxpayload-dynamic.patch
+vt-handoff.patch
+probe-fusionio.patch
+ignore-grub_func_test-failures.patch
+mkconfig-recovery-title.patch
+install-powerpc-machtypes.patch
+ieee1275-clear-reset.patch
+ppc64el-disable-vsx.patch
+grub-install-pvxen-paths.patch
+insmod-xzio-and-lzopio-on-xen.patch
+grub-install-extra-removable.patch
+mkconfig-other-inits.patch
+zpool-full-device-name.patch
+net-read-bracketed-ipv6-addr.patch
+bootp-new-net_bootp6-command.patch
+efinet-uefi-ipv6-pxe-support.patch
+bootp-process-dhcpack-http-boot.patch
+efinet-set-network-from-uefi-devpath.patch
+efinet-set-dns-from-uefi-proto.patch
+fix-lockdown.patch
+skip-grub_cmd_set_date.patch
+bash-completion-drop-have-checks.patch
+at_keyboard-module-init.patch
+uefi-secure-boot-cryptomount.patch
+efi-variable-storage-minimise-writes.patch
+grub-install-removable-shim.patch
+dejavu-font-path.patch
+xen-no-xsm-policy-in-non-xsm-options.patch
+pc-verifiers-module.patch
+debug_verifiers.patch
+mkimage-fix-section-sizes.patch
+tpm-unknown-error-non-fatal.patch
+xfs-fix-v4-superblock.patch
+tests-ahci-update-qemu-device-name.patch
+minilzo-2.10.patch
+0063-loader-efi-chainloader-Simplify-the-loader-state.patch
+0064-commands-boot-Add-API-to-pass-context-to-loader.patch
+0065-loader-efi-chainloader-Use-grub_loader_set_ex.patch
+0066-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
+0067-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
+0068-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
+0069-video-readers-png-Refuse-to-handle-multiple-image-he.patch
+0070-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
+0071-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
+0072-video-readers-png-Sanity-check-some-huffman-codes.patch
+0073-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
+0074-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
+0075-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
+0076-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
+0077-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
+0078-net-netbuff-Block-overly-large-netbuff-allocs.patch
+0079-net-ip-Do-IP-fragment-maths-safely.patch
+0080-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
+0081-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
+0082-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
+0083-net-tftp-Avoid-a-trivial-UAF.patch
+0084-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
+0085-net-http-Fix-OOB-write-for-split-http-headers.patch
+0086-net-http-Error-out-on-headers-with-LF-without-CR.patch
+0087-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
+0088-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
+0089-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
+0090-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
+0091-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
+0092-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
+fs-tester-time-fail.patch
+cve_2022_2601/0001-video-readers-Add-artificial-limit-to-image-dimensio.patch
+cve_2022_2601/0002-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch
+cve_2022_2601/0003-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch
+cve_2022_2601/0004-font-Fix-several-integer-overflows-in-grub_font_cons.patch
+cve_2022_2601/0005-font-Remove-grub_font_dup_glyph.patch
+cve_2022_2601/0006-font-Fix-integer-overflow-in-ensure_comb_space.patch
+cve_2022_2601/0007-font-Fix-integer-overflow-in-BMP-index.patch
+cve_2022_2601/0008-font-Fix-integer-underflow-in-binary-search-of-char-.patch
+cve_2022_2601/0009-kern-efi-sb-Enforce-verification-of-font-files.patch
+cve_2022_2601/0010-fbutil-Fix-integer-overflow.patch
+cve_2022_2601/0011-font-Fix-an-integer-underflow-in-blit_comb.patch
+cve_2022_2601/0012-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
+cve_2022_2601/0013-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
+cve_2022_2601/0014-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch
+font-Try-opening-fonts-from-the-bundled-memdisk.patch
+kern-file-Fix-error-handling-in-grub_file_open.patch
+gcc12_build_dangling_pointer.patch
+gcc12_build_array_bounds.patch
+gcc12_build_array_bounds2.patch
+arm64_remove_magic_number_check.patch
+grub_mkconfig_restore_umask.patch
+ignore_checksum_seed_incompat_feature.patch
+ignore_the_large_dir_incompat_feature.patch
+987008-lvrename-boot-fail.patch
+disk-cryptodisk-when-cheatmounting-use-the-sector-info-of-the-cheat-device.patch
+osdep-devmapper-getroot-have-devmapper-recognize-luks2.patch
+osdep-devmapper-getroot-set-up-cheated-luks2-cryptodisk-mount-from-dm-parameters.patch
+arm64-handover-to-kernel-if-sb-enabled.patch
+grub_os-prober.patch
+os-prober-Allow-initrd-to-contain-spaces.patch
+ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_LIST-.patch
+ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-reside.patch
+ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entries-fr.patch
+ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-index-at.patch
+ntfs-cve-fixes/fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
+ntfs-cve-fixes/fs-ntfs-Make-code-more-readable.patch
diff --git a/debian/patches/skip-grub_cmd_set_date.patch b/debian/patches/skip-grub_cmd_set_date.patch
new file mode 100644
index 0000000..830b887
--- /dev/null
+++ b/debian/patches/skip-grub_cmd_set_date.patch
@@ -0,0 +1,27 @@
+From dc8f60ab6ca24cb871fe17955385138d43712727 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sun, 28 Oct 2018 19:45:56 +0000
+Subject: Skip flaky grub_cmd_set_date test
+
+Bug-Debian: https://bugs.debian.org/906470
+Last-Update: 2018-10-28
+
+Patch-Name: skip-grub_cmd_set_date.patch
+---
+ tests/grub_cmd_set_date.in | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tests/grub_cmd_set_date.in b/tests/grub_cmd_set_date.in
+index aac120a6c..1bb5be4ca 100644
+--- a/tests/grub_cmd_set_date.in
++++ b/tests/grub_cmd_set_date.in
+@@ -1,6 +1,9 @@
+ #! @BUILD_SHEBANG@
+ set -e
+
++echo "Skipping flaky test."
++exit 77
++
+ . "@builddir@/grub-core/modinfo.sh"
+
+ case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in
diff --git a/debian/patches/tests-ahci-update-qemu-device-name.patch b/debian/patches/tests-ahci-update-qemu-device-name.patch
new file mode 100644
index 0000000..f10fc08
--- /dev/null
+++ b/debian/patches/tests-ahci-update-qemu-device-name.patch
@@ -0,0 +1,34 @@
+From 1a1c93cd19a9ec67d6237d5a537976ff9297ab78 Mon Sep 17 00:00:00 2001
+From: Marius Bakke <marius@gnu.org>
+Date: Sun, 13 Jun 2021 15:11:51 +0200
+Subject: tests/ahci: Change "ide-drive" deprecated QEMU device name to
+ "ide-hd"
+
+The "ide-drive" device was removed in QEMU 6.0. The "ide-hd" has been
+available for more than 10 years now in QEMU. Thus there shouldn't be
+any need for backwards compatible names.
+
+Signed-off-by: Marius Bakke <marius@gnu.org>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=aaea244a6ddd1e35aed60a5c7a08ddc41f51805b
+Last-Update: 2021-09-24
+
+Patch-Name: tests-ahci-update-qemu-device-name.patch
+---
+ tests/ahci_test.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/ahci_test.in b/tests/ahci_test.in
+index 7df560462..d844fe680 100644
+--- a/tests/ahci_test.in
++++ b/tests/ahci_test.in
+@@ -41,7 +41,7 @@ echo "hello" > "$outfile"
+
+ tar cf "$imgfile" "$outfile"
+
+-if [ "$(echo "nativedisk; source '(ahci0)/$outfile';" | "${grubshell}" --qemu-opts="-drive id=disk,file=$imgfile,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 " | tail -n 1)" != "Hello World" ]; then
++if [ "$(echo "nativedisk; source '(ahci0)/$outfile';" | "${grubshell}" --qemu-opts="-drive id=disk,file=$imgfile,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 " | tail -n 1)" != "Hello World" ]; then
+ rm "$imgfile"
+ rm "$outfile"
+ exit 1
diff --git a/debian/patches/tpm-unknown-error-non-fatal.patch b/debian/patches/tpm-unknown-error-non-fatal.patch
new file mode 100644
index 0000000..5f3c3ee
--- /dev/null
+++ b/debian/patches/tpm-unknown-error-non-fatal.patch
@@ -0,0 +1,31 @@
+From ba3a0d4b6c0b56f6d7935911b53a02a7d0504da5 Mon Sep 17 00:00:00 2001
+From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Date: Sat, 10 Jul 2021 22:32:00 +0100
+Subject: tpm: Pass unknown error as non-fatal, but debug print the error we
+ got
+
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+
+Bug-Debian: https://bugs.debian.org/940911
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1848892
+Last-Update: 2021-09-24
+
+Patch-Name: tpm-unknown-error-non-fatal.patch
+---
+ grub-core/commands/efi/tpm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
+index a97d85368..e73bd5561 100644
+--- a/grub-core/commands/efi/tpm.c
++++ b/grub-core/commands/efi/tpm.c
+@@ -145,7 +145,8 @@ grub_efi_log_event_status (grub_efi_status_t status)
+ case GRUB_EFI_NOT_FOUND:
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
+ default:
+- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
++ grub_dprintf ("tpm", "Unknown TPM error: %" PRIdGRUB_SSIZE, status);
++ return 0;
+ }
+ }
+
diff --git a/debian/patches/uefi-secure-boot-cryptomount.patch b/debian/patches/uefi-secure-boot-cryptomount.patch
new file mode 100644
index 0000000..cbef39c
--- /dev/null
+++ b/debian/patches/uefi-secure-boot-cryptomount.patch
@@ -0,0 +1,48 @@
+From 7fd79864c87c57d586989d12c3d4a7e432b3d73a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Herv=C3=A9=20Werner?= <dud225@hotmail.com>
+Date: Mon, 28 Jan 2019 17:24:23 +0100
+Subject: Fix setup on Secure Boot systems where cryptodisk is in use
+
+On full-encrypted systems, including /boot, the current code omits
+cryptodisk commands needed to open the drives if Secure Boot is enabled.
+This prevents grub2 from reading any further configuration residing on
+the encrypted disk.
+This patch fixes this issue by adding the needed "cryptomount" commands in
+the load.cfg file that is then copied in the EFI partition.
+
+Bug-Debian: https://bugs.debian.org/917117
+Last-Update: 2019-02-10
+
+Patch-Name: uefi-secure-boot-cryptomount.patch
+---
+ util/grub-install.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index b51fe4710..58f1453ba 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -1531,6 +1531,23 @@ main (int argc, char *argv[])
+ || uefi_secure_boot)
+ {
+ char *uuid = NULL;
++
++ if (uefi_secure_boot && config.is_cryptodisk_enabled)
++ {
++ if (grub_dev->disk)
++ probe_cryptodisk_uuid (grub_dev->disk);
++
++ for (curdrive = grub_drives + 1; *curdrive; curdrive++)
++ {
++ grub_device_t dev = grub_device_open (*curdrive);
++ if (!dev)
++ continue;
++ if (dev->disk)
++ probe_cryptodisk_uuid (dev->disk);
++ grub_device_close (dev);
++ }
++ }
++
+ /* generic method (used on coreboot and ata mod). */
+ if (!force_file_id
+ && grub_fs->fs_uuid && grub_fs->fs_uuid (grub_dev, &uuid))
diff --git a/debian/patches/vt-handoff.patch b/debian/patches/vt-handoff.patch
new file mode 100644
index 0000000..153c58d
--- /dev/null
+++ b/debian/patches/vt-handoff.patch
@@ -0,0 +1,101 @@
+From 4336395ce7d82827b466a0088e1b08d42ef24ae8 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:30 +0000
+Subject: Add configure option to use vt.handoff=7
+
+This is used for non-recovery Linux entries only; it enables
+flicker-free booting if gfxpayload=keep is in use and a suitable kernel
+is present.
+
+Author: Andy Whitcroft <apw@canonical.com>
+Forwarded: not-needed
+Last-Update: 2013-12-25
+
+Patch-Name: vt-handoff.patch
+---
+ configure.ac | 11 +++++++++++
+ util/grub.d/10_linux.in | 28 +++++++++++++++++++++++++++-
+ 2 files changed, 38 insertions(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 947fd529f..e11df6bc5 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1948,6 +1948,17 @@ else
+ fi
+ AC_SUBST([GFXPAYLOAD_DYNAMIC])
+
++AC_ARG_ENABLE([vt-handoff],
++ [AS_HELP_STRING([--enable-vt-handoff],
++ [use Linux vt.handoff option for flicker-free booting (default=no)])],
++ [], [enable_vt_handoff=no])
++if test x"$enable_vt_handoff" = xyes ; then
++ VT_HANDOFF=1
++else
++ VT_HANDOFF=0
++fi
++AC_SUBST([VT_HANDOFF])
++
+ LIBS=""
+
+ AC_SUBST([FONT_SOURCE])
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index d46d7852b..64204c216 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -24,6 +24,7 @@ ubuntu_recovery="@UBUNTU_RECOVERY@"
+ quiet_boot="@QUIET_BOOT@"
+ quick_boot="@QUICK_BOOT@"
+ gfxpayload_dynamic="@GFXPAYLOAD_DYNAMIC@"
++vt_handoff="@VT_HANDOFF@"
+
+ . "$pkgdatadir/grub-mkconfig_lib"
+
+@@ -104,6 +105,14 @@ if [ "$ubuntu_recovery" = 1 ]; then
+ GRUB_CMDLINE_LINUX_RECOVERY="$GRUB_CMDLINE_LINUX_RECOVERY nomodeset"
+ fi
+
++if [ "$vt_handoff" = 1 ]; then
++ for word in $GRUB_CMDLINE_LINUX_DEFAULT; do
++ if [ "$word" = splash ]; then
++ GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT \$vt_handoff"
++ fi
++ done
++fi
++
+ linux_entry ()
+ {
+ os="$1"
+@@ -149,7 +158,7 @@ linux_entry ()
+ fi
+ if ([ "$ubuntu_recovery" = 0 ] || [ x$type != xrecovery ]) && \
+ ([ "x$GRUB_GFXPAYLOAD_LINUX" != x ] || [ "$gfxpayload_dynamic" = 1 ]); then
+- echo " set gfxpayload=\$linux_gfx_mode" | sed "s/^/$submenu_indentation/"
++ echo " gfxmode \$linux_gfx_mode" | sed "s/^/$submenu_indentation/"
+ fi
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
+@@ -228,6 +237,23 @@ prepare_root_cache=
+ boot_device_id=
+ title_correction_code=
+
++cat << 'EOF'
++function gfxmode {
++ set gfxpayload="${1}"
++EOF
++if [ "$vt_handoff" = 1 ]; then
++ cat << 'EOF'
++ if [ "${1}" = "keep" ]; then
++ set vt_handoff=vt.handoff=7
++ else
++ set vt_handoff=
++ fi
++EOF
++fi
++cat << EOF
++}
++EOF
++
+ # Use ELILO's generic "efifb" when it's known to be available.
+ # FIXME: We need an interface to select vesafb in case efifb can't be used.
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != x ] || [ "$gfxpayload_dynamic" = 0 ]; then
diff --git a/debian/patches/wubi-no-windows.patch b/debian/patches/wubi-no-windows.patch
new file mode 100644
index 0000000..407d391
--- /dev/null
+++ b/debian/patches/wubi-no-windows.patch
@@ -0,0 +1,57 @@
+From f36695098443076b8eb12399c286136ac8ed50d3 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:24 +0000
+Subject: Skip Windows os-prober entries on Wubi systems
+
+Since we're already being booted from the Windows boot loader, including
+entries that take us back to it mostly just causes confusion, and stops
+us from being able to hide the menu if there are no other OSes
+installed.
+
+https://blueprints.launchpad.net/ubuntu/+spec/foundations-o-wubi
+
+Forwarded: not-needed
+Last-Update: 2013-11-26
+
+Patch-Name: wubi-no-windows.patch
+---
+ util/grub.d/30_os-prober.in | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index e2ec80eb9..98aee403e 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -113,6 +113,8 @@ EOF
+
+ used_osprober_linux_ids=
+
++wubi=
++
+ for OS in ${OSPROBED} ; do
+ DEVICE="`echo ${OS} | cut -d ':' -f 1`"
+ LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
+@@ -149,6 +151,23 @@ for OS in ${OSPROBED} ; do
+ case ${BOOT} in
+ chain)
+
++ case ${LONGNAME} in
++ Windows*)
++ if [ -z "$wubi" ]; then
++ if [ -x /usr/share/lupin-support/grub-mkimage ] && \
++ /usr/share/lupin-support/grub-mkimage --test; then
++ wubi=yes
++ else
++ wubi=no
++ fi
++ fi
++ if [ "$wubi" = yes ]; then
++ echo "Skipping ${LONGNAME} on Wubi system" >&2
++ continue
++ fi
++ ;;
++ esac
++
+ onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ cat << EOF
+ menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' $CLASS --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' {
diff --git a/debian/patches/xen-no-xsm-policy-in-non-xsm-options.patch b/debian/patches/xen-no-xsm-policy-in-non-xsm-options.patch
new file mode 100644
index 0000000..315bdab
--- /dev/null
+++ b/debian/patches/xen-no-xsm-policy-in-non-xsm-options.patch
@@ -0,0 +1,35 @@
+From 4d208a51f41c6df932805dfd681ad64a02c2c728 Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson@eu.citrix.com>
+Date: Wed, 27 May 2020 17:00:45 +0100
+Subject: 20_linux_xen: Do not load XSM policy in non-XSM options
+
+For complicated reasons, even if you have XSM/FLASK disabled (as is
+the default) the Xen build system still builds a policy file and puts
+it in /boot.
+
+Even so, we shouldn't be loading this in the usual non-"XSM enabled"
+entries. It doesn't do any particular harm but it is quite confusing.
+
+Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
+
+Bug-Debian: https://bugs.debian.org/961673
+Last-Update: 2020-05-29
+
+Patch-Name: xen-no-xsm-policy-in-non-xsm-options.patch
+---
+ util/grub.d/20_linux_xen.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index d99751a94..a12780ebe 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -173,7 +173,7 @@ EOF
+ ${module_loader} --nounzip $(echo $initrd_path)
+ EOF
+ fi
+- if test -n "${xenpolicy}" ; then
++ if ${xsm} && test -n "${xenpolicy}" ; then
+ message="$(gettext_printf "Loading XSM policy ...")"
+ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
diff --git a/debian/patches/xfs-fix-v4-superblock.patch b/debian/patches/xfs-fix-v4-superblock.patch
new file mode 100644
index 0000000..7bafc46
--- /dev/null
+++ b/debian/patches/xfs-fix-v4-superblock.patch
@@ -0,0 +1,122 @@
+From bf29fbd997292bbf6be2eec03594ec82f0899f57 Mon Sep 17 00:00:00 2001
+From: Erwan Velu <erwanaliasr1@gmail.com>
+Date: Wed, 25 Aug 2021 15:31:52 +0200
+Subject: fs/xfs: Fix unreadable filesystem with v4 superblock
+
+The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support)
+introduced the bigtime support by adding some features in v3 inodes.
+This change extended grub_xfs_inode struct by 76 bytes but also changed
+the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this
+commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes
+XFS_V2_INODE_SIZE becomes 16 bytes too small.
+
+As a result, the data structures aren't properly aligned and the GRUB
+generates "attempt to read or write outside of partition" errors when
+trying to read the XFS filesystem:
+
+ GNU GRUB version 2.11
+ ....
+ grub> set debug=efi,gpt,xfs
+ grub> insmod part_gpt
+ grub> ls (hd0,gpt1)/
+ partmap/gpt.c:93: Read a valid GPT header
+ partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125
+ fs/xfs.c:931: Reading sb
+ fs/xfs.c:270: Validating superblock
+ fs/xfs.c:295: XFS v4 superblock detected
+ fs/xfs.c:962: Reading root ino 128
+ fs/xfs.c:515: Reading inode (128) - 64, 0
+ fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840
+ error: attempt to read or write outside of partition.
+
+This commit change the XFS_V2_INODE_SIZE computation by subtracting 76
+bytes instead of 92 bytes from the actual size of grub_xfs_inode struct.
+This 76 bytes value comes from added members:
+ 20 grub_uint8_t unused5
+ 1 grub_uint64_t flags2
+ 48 grub_uint8_t unused6
+
+This patch explicitly splits the v2 and v3 parts of the structure.
+The unused4 is still ending of the v2 structures and the v3 starts
+at unused5. Thanks to this we will avoid future corruptions of v2
+or v3 inodes.
+
+The XFS_V2_INODE_SIZE is returning to its expected size and the
+filesystem is back to a readable state:
+
+ GNU GRUB version 2.11
+ ....
+ grub> set debug=efi,gpt,xfs
+ grub> insmod part_gpt
+ grub> ls (hd0,gpt1)/
+ partmap/gpt.c:93: Read a valid GPT header
+ partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125
+ fs/xfs.c:931: Reading sb
+ fs/xfs.c:270: Validating superblock
+ fs/xfs.c:295: XFS v4 superblock detected
+ fs/xfs.c:962: Reading root ino 128
+ fs/xfs.c:515: Reading inode (128) - 64, 0
+ fs/xfs.c:515: Reading inode (128) - 64, 0
+ fs/xfs.c:931: Reading sb
+ fs/xfs.c:270: Validating superblock
+ fs/xfs.c:295: XFS v4 superblock detected
+ fs/xfs.c:962: Reading root ino 128
+ fs/xfs.c:515: Reading inode (128) - 64, 0
+ fs/xfs.c:515: Reading inode (128) - 64, 0
+ fs/xfs.c:515: Reading inode (128) - 64, 0
+ fs/xfs.c:515: Reading inode (131) - 64, 768
+ efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0
+ grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024
+ grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816
+ grub>
+
+Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support)
+
+Signed-off-by: Erwan Velu <e.velu@criteo.com>
+Tested-by: Carlos Maiolino <cmaiolino@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=a4b495520e4dc41a896a8b916a64eda9970c50ea
+Last-Update: 2021-09-24
+
+Patch-Name: xfs-fix-v4-superblock.patch
+---
+ grub-core/fs/xfs.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 0f524c3a8..e3816d1ec 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy
+ grub_uint32_t nanosec;
+ } GRUB_PACKED;
+
++/*
++ * The struct grub_xfs_inode layout was taken from the
++ * struct xfs_dinode_core which is described here:
++ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
++ */
+ struct grub_xfs_inode
+ {
+ grub_uint8_t magic[2];
+@@ -208,14 +213,15 @@ struct grub_xfs_inode
+ grub_uint32_t nextents;
+ grub_uint16_t unused3;
+ grub_uint8_t fork_offset;
+- grub_uint8_t unused4[37];
++ grub_uint8_t unused4[17]; /* Last member of inode v2. */
++ grub_uint8_t unused5[20]; /* First member of inode v3. */
+ grub_uint64_t flags2;
+- grub_uint8_t unused5[48];
++ grub_uint8_t unused6[48]; /* Last member of inode v3. */
+ } GRUB_PACKED;
+
+ #define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode)
+-/* Size of struct grub_xfs_inode until fork_offset (included). */
+-#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92)
++/* Size of struct grub_xfs_inode v2, up to unused4 member included. */
++#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76)
+
+ struct grub_xfs_dirblock_tail
+ {
diff --git a/debian/patches/zpool-full-device-name.patch b/debian/patches/zpool-full-device-name.patch
new file mode 100644
index 0000000..4f6ce65
--- /dev/null
+++ b/debian/patches/zpool-full-device-name.patch
@@ -0,0 +1,33 @@
+From be244ee23f3b12266a5671486af814c57c616a6c Mon Sep 17 00:00:00 2001
+From: Chad MILLER <chad.miller@canonical.com>
+Date: Thu, 27 Oct 2016 17:15:07 -0400
+Subject: Tell zpool to emit full device names
+
+zfs-initramfs currently provides extraneous, undesired symlinks to
+devices directly underneath /dev/ to satisfy zpool's historical output
+of unqualified device names. By including this environment variable to
+signal our intent to zpool, zfs-linux packages can drop the symlink
+behavior when updating to its upstream or backported output behavior.
+
+Bug: https://savannah.gnu.org/bugs/?43653
+Bug-Debian: https://bugs.debian.org/824974
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1527727
+Last-Update: 2016-11-01
+
+Patch-Name: zpool-full-device-name.patch
+---
+ grub-core/osdep/unix/getroot.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
+index 46d7116c6..da102918d 100644
+--- a/grub-core/osdep/unix/getroot.c
++++ b/grub-core/osdep/unix/getroot.c
+@@ -243,6 +243,7 @@ grub_util_find_root_devices_from_poolname (char *poolname)
+ argv[2] = poolname;
+ argv[3] = NULL;
+
++ setenv ("ZPOOL_VDEV_NAME_PATH", "YES", 1);
+ pid = grub_util_exec_pipe (argv, &fd);
+ if (!pid)
+ return NULL;
diff --git a/debian/platform-subst b/debian/platform-subst
new file mode 100755
index 0000000..436ffca
--- /dev/null
+++ b/debian/platform-subst
@@ -0,0 +1,38 @@
+#! /usr/bin/perl
+use warnings;
+use strict;
+
+my %subst = ();
+while ($ARGV[0] =~ /(.*?)=(.*)/) {
+ $subst{$1} = $2;
+ shift;
+}
+
+die "no package specified\n" unless exists $subst{PACKAGE};
+(my $package = $subst{PACKAGE}) =~ s/-(?:bin|dbg)$//;
+
+my $grub_dir_path = "debian/tmp-$package/usr/lib/grub";
+opendir my $grub_dir, $grub_dir_path or die "can't opendir $grub_dir_path: $!";
+my @cpu_platforms = grep { !/^\./ } readdir $grub_dir;
+closedir $grub_dir;
+
+$subst{FIRST_CPU_PLATFORM} = $cpu_platforms[0];
+
+sub emit ($) {
+ my $line = shift;
+ while (my ($key, $value) = each %subst) {
+ $line =~ s/\@$key\@/$value/g;
+ }
+ print $line;
+}
+
+while (<>) {
+ if (/\@CPU_PLATFORM\@/) {
+ for my $cpu_platform (@cpu_platforms) {
+ (my $line = $_) =~ s/\@CPU_PLATFORM\@/$cpu_platform/g;
+ emit($line);
+ }
+ } else {
+ emit($_);
+ }
+}
diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in
new file mode 100644
index 0000000..2151919
--- /dev/null
+++ b/debian/po/POTFILES.in
@@ -0,0 +1,2 @@
+[type: gettext/rfc822deb] grub-pc.templates.in
+[type: gettext/rfc822deb] templates.in
diff --git a/debian/po/ar.po b/debian/po/ar.po
new file mode 100644
index 0000000..e58ff9c
--- /dev/null
+++ b/debian/po/ar.po
@@ -0,0 +1,494 @@
+# translation of grub.ar.po to Arabic
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Ossama M. Khayat <okhayat@yahoo.com>, 2008, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub.ar\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2010-07-16 02:38+0300\n"
+"Last-Translator: Ossama M. Khayat <okhayat@yahoo.com>\n"
+"Language-Team: Arabic <support@arabeyes.org>\n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "تÙعيل التحميل التسلسلي من menu.lstØŸ"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "عثرت بريمجيات ترقية GRUB على إعداد سابق ÙÙŠ /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+#, fuzzy
+#| msgid ""
+#| "In order to replace the Legacy version of GRUB in your system, it is "
+#| "recommended that /boot/grub/menu.lst is adjusted to chainload GRUB 2 from "
+#| "your existing GRUB Legacy setup. This step may be automaticaly performed "
+#| "now."
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"لتستبدل النسخة السابقة من GRUB ÙÙŠ نظامك، ÙŠÙستحسن تعديل المل٠/boot/grub/menu."
+"lst لتحميل GRUB 2 تسلسلياً من إعداد GRUB السابق. ويمكن تنÙيذ هذه الخطوة "
+"تلقائياً الآن."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+#, fuzzy
+#| msgid ""
+#| "It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+#| "verify that your new GRUB 2 setup is functional for you, before you "
+#| "install it directly to your MBR (Master Boot Record)."
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"ÙŠÙستحسن أن تقبل التحميل التسلسلي لمدير الإقلاع GRUB من خلال المل٠menu.lstØŒ "
+"وتحقق من أن إعداد GRUB 2 صالح لاستخدامك، قبل أن تÙبّته مباشرة على سجل الإقلاع "
+"الرئيسي MBR الخاص بك."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+#, fuzzy
+#| msgid "GRUB failed to install to the following devices:"
+msgid "GRUB install devices:"
+msgstr "تعذر تثبيت GRUB على الأجهزة التالية:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+#, fuzzy
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} م.ب.، ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+#, fuzzy
+#| msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "${DEVICE} (${SIZE} م.ب.، ${MODEL})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "تعذر تثبيت GRUB على الأجهزة التالية:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"هل تريد الاستمرار على أي حال؟ إن Ùعلت، Ùقد لا يتمكن جهازك من بدء التشغيل كما "
+"يجب."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+#, fuzzy
+#| msgid "GRUB installation failed. Try again?"
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "تعذر تثبيت GRUB. تريد المحاولة مجدداً؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"قد تتمكن من تثبيت GRUB على جهاز آخر، لكن يجب أن تتحقق من إمكانية نظامك "
+"الإقلاع من ذلك الجهاز. وإن لم يكن كذلك، Ùسيتم إلغاء الترقية من نظام GRUB "
+"القديم."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "تريد الاستمرار دون تثبيت GRUB؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+#, fuzzy
+#| msgid ""
+#| "You chose not to install GRUB to any devices. If you continue, the boot "
+#| "loader may not be properly configured, and when your computer next starts "
+#| "up it will use whatever was previously in the boot sector. If there is an "
+#| "earlier version of GRUB 2 in the boot sector, it may be unable to load "
+#| "modules or handle the current configuration file."
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"اخترت عدم تثبيت GRUB على أية جهاز. إن استمريت، Ùقد لا يتم تهيئة محمّل الإقلاع "
+"بشكل صحيح، كما يستخدم حاسبك أي نظام موجود على قطاع الإقلاع مسبقاً. إن كان "
+"هناك نسخة سابقة من GRUB 2 ÙÙŠ قطاع الإقلاع، Ùقد لا يستطيع تحميل الوحدات أو "
+"قراءة مل٠التهيئة الحالي بشكل صحيح."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+#, fuzzy
+#| msgid ""
+#| "If you are already running a different boot loader and want to carry on "
+#| "doing so, or if this is a special environment where you do not need a "
+#| "boot loader, then you should continue anyway. Otherwise, you should "
+#| "install GRUB somewhere."
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"إن كنت تستخدم محمل إقلاع آخر وتريد الاستمرار باستخدامه، أو إن كانت لديك بيئة "
+"عمل خاصة حيث لا تحتاج إلى محمل إقلاع، Ùيجب عليك الاستمرار على أي حال. وإلا "
+"يجب أن تقوم بتثبيت GRUB ÙÙŠ مكان ما."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "إنهاء التحويل إلى GRUB 2 الآن؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"لا زال النظام يحتوي على ملÙات GRUB قديمة مثبتة، كما يحتوي أيضاً على سجلات "
+"إقلاع GRUB 2 على هذه الأقراص:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"يبدو أن GRUB القديم لم يعد مستخدماً، ويجب عليك الترقية إلى GRUB 2 وإنهاء "
+"التحويل إلى GRUB 2 بإزالة ملÙات GRUB القديمة. وإن لم تقم بعملية الترقية هذه، "
+"Ùقد لا يكون نظام الإقلاع متواÙقاً مع الحزم الجديدة ويتسبب ذلك بعدم إقلاع نظام "
+"كما هو Ù…Ùترض."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"بشكل عام، يجب عليك إنهاء التحويل إلى GRUB 2 إلا إن كانت سجلات الإقلاع هذه قد "
+"أنشأها تثبيت GRUB 2 لنظام تشغيل آخر."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "سطر أوامر لينكس:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+#, fuzzy
+#| msgid ""
+#| "The following Linux command line was extracted from /etc/default/grub or "
+#| "the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+#| "correct, and modify it if necessary."
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"سطر أوامر لينكس التالي تم استخراجه من /etc/default/grub أو\n"
+"Ù…Ùعطى `kopt' ÙÙŠ مل٠menu.lst الخاص بحزمة GRUB القديمة. رجاءً تحقق من\n"
+"صحته وقم بتعديله إن كانت هناك ضرورة."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "سطر أوامر لينكس الاÙتراضي:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"سيتم استخدام سلسلة الحرو٠التالية كمÙعطيات لتشغيل النظام لمÙدخل القائمة\n"
+"الاÙتراضي ولكن ليس لوضع الإنقاذ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "سطر أوامر KFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+#, fuzzy
+#| msgid ""
+#| "The following kFreeBSD command line was extracted from /etc/default/grub "
+#| "or the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it "
+#| "is correct, and modify it if necessary."
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"سطر أوامر KFreeBSD التالي تم استخراجه من /etc/default/grub أو\n"
+"Ù…Ùعطى `kopt' ÙÙŠ مل٠menu.lst الخاص بحزمة GRUB القديمة. رجاءً تحقق من صحته وقم "
+"بتعديله إن كانت هناك ضرورة."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "سطر أوامر KFreeBSD الاÙتراضي:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"سيتم استخدام النص التالي كمÙعطى KFreeBSD لمÙدخل القائمة\n"
+"الاÙتراضي ولكن ليس لوضع الإنقاذ."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "تم إعادة إنشاء /boot/grub/device.map"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "تم إعادة كتابة المل٠/boot/grub/device.map ليستخدم أسماء الأجهزة الصحيحة. "
+#~ "ÙÙŠ معظم الحالات، سيقلل هذا العمل الحاجة إلى التغييرات بشكل كبير ÙÙŠ "
+#~ "المستقبل، كما أن Ù…Ùدخلات قائمة إقلاع GRUB الناتجة لن تتأثر."
+
+#, fuzzy
+#~| msgid ""
+#~| "However, since you have more than one disk in your system, it is "
+#~| "possible that you were depending on the old device map. Please check "
+#~| "whether you have any custom boot menu entries that rely on GRUB's (hdN) "
+#~| "drive numbering, and update them if necessary."
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "على كل، حيث أنه لديك اكثر من قرص ÙÙŠ نظامك، من المحتمل أنه كان يعتمد على "
+#~ "خريطة الأجهزة القديمة. Ùالرجاء التحقق مما إذا كان لديك أية Ù…Ùدخلات قائمة "
+#~ "مخصصة تعتمد على طريقة GRUB لترقيم الأجهزة، (hdN)، وقم بتحديثها إن كانت "
+#~ "ضرورياً."
+
+#, fuzzy
+#~| msgid ""
+#~| "If you do not understand this message, or if you do not have any custom "
+#~| "boot menu entries, you can ignore this message."
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "إن لم تعر٠مقصود هذه الرسالة، أو إن لم يكن لديك أية Ù…Ùدخلات Ù…Ùخصصة ÙÙŠ "
+#~ "القائمة، يمكنك تجاهل هذه الرسالة."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "ÙÙŠ أي من الحالتين، متى ما أردت تحميل GRUB 2 مباشرة من سجل الإقلاع الرئيسي "
+#~ "MBRØŒ يمكنك ذلك بإصدار الأمر التالي كمÙستخدم root:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "تعذر تثبيت GRUB. تريد الاستمرار؟"
diff --git a/debian/po/ast.po b/debian/po/ast.po
new file mode 100644
index 0000000..4a59bd8
--- /dev/null
+++ b/debian/po/ast.po
@@ -0,0 +1,467 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-01-27 11:10+0100\n"
+"Last-Translator: Mikel González <mikelglez@softastur.org>\n"
+"Language-Team: Asturian <alministradores@softastur.org>\n"
+"Language: ast\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "¿Cadena de carga dende menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"El scripts d'actualización GRUB detectó una configuración GRUB Legacy en /"
+"boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Cola fin de trocar la versión Legacy de GRUB nel to sistema, ye recomendable "
+"que /boot/grub/menu.lst seya axustáu a la cadena de carga GRUB 2 dende la to "
+"configuración Legacy GRUB existente. Esti pasu puede ser fechu "
+"automáticamente agora."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Ye recomendable que aceptes la cadena de carga GRUB 2 dende'l menu.lst, y "
+"compruebes que la to nueva configuración de GRUB 2 ye funcional pa ti, "
+"anantes de que lo instales directamente nel to MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Independientemente de la to decisión, puedes trocar la imaxe vieya MBR con "
+"GRUB 2 más tarde executando como root el comandu que vien darréu:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB falló al instalar nos siguientes preseos:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Anovóse'l paquete grup-pc. Esti menú val pa esbillar en que preseos quie "
+"que'l grub-install s'execute automáticamente, si hai dalgún."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Executar grub-install automaticamente ye recomendable na mayoría de les "
+"situaciones, pa evitar que la imaxe del motor de GRUB quede ensin "
+"sincronizase colos módulos de GRUB o grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Si nun tas seguru/a de que discu t'asignau como discu d'arranque pola BIOS, "
+"ye una bona idea instalar GRUB en tolos discos."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: puedes instalar GRUB nos rexistros d'arranque de les particiones "
+"tamién, y úfrense dalgunes particiones apropiaes. Sicasí, esto fuercia a "
+"GRUB a usar un mecanismu de llista de torgues, que lo fai menos fiable poro "
+"nun ye recomendable."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"El xestor d'arranque GRUB instalóse nun discu que nun ta presente, o que "
+"cambió d'identificador únicu por dalguna razón. Ye importante asegurase de "
+"que la imaxe del motor de GRUB sigui sincronizada colos módulos de GRUB y "
+"grub.cfg. Por favor prueba otra vuelta p'asegurate de que GRUB ta escritu "
+"nel preséu d'arranque correutu."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Fallu al escribir GRUB al preséu d'arranque - ¿siguir?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Falló GRUB al instalar nos siguientes preseos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"¿Quies siguir igualmente? Si quies, el to ordenador podría nun arrancar bien."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "La instalación de GRUB falló. ¿Intentalo otra vegada?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Puedes instalar GRUB a otru preséu, aunque deberíes comprobar que'l to "
+"sistema arrancará dende esi preséu. De lo contrario, l'anovamientu de GRUB "
+"encaboxarase."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "¿Siguir ensin instalar GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Escoyistes nun instalar GRUB en dengún preséu. De siguir, el xestor "
+"d'arranque podría nun tar configuráu dafechu, y nel siguiente aniciu del "
+"ordenador usarás lo que teníes previamente nel sector d'arranque. Si hai un "
+"versión anterior de GRUB 2 nel sector d'arranque, podría ser capaz de cargar "
+"módulos o remanar el ficheru de configuración actual."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Si ya tas executando un xestor d'arranque distintu y quies siguir "
+"faciéndolo, o si ye un ambiente especial onde nun necesites un xestor "
+"d'arranque, entós puedes siguir. D'otra miente, deberíes instalar GRUB en "
+"dalgún sitiu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "¿Desaniciar GRUB 2 de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "¿Quiés desaniciar tolos ficheros de GRUB 2 de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Esto fadrá qué nun puedas aniciar el sistema a nun ser qu'instales otru "
+"xestor d'arranque."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "¿Finar agora conversión a GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Esti sistema tovía tien ficheros del xestor d'arranque GRUB instaláu, pero "
+"agora tamién registros d'arranque GRUB 2 instaláu n'estos discos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Parez probable que GRUB ya nun ta n'usu, y que deberíes anovar les imáxenes "
+"de GRUB 2 d'estos discos y finar la conversión a GRUB 2, desaniciando vieyos "
+"ficheros heredaos de GRUB. Si nun anoves estes imáxenes de GRUB, entós "
+"pueden ser incompatibles colos nuevos paquetes y facer que'l to sistema nun "
+"arranque correutamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"En xeneral, deberíes finar la conversión a GRUB 2 a menos qu'estos rexistros "
+"d'arranque fueren creaos por una instalación de GRUB 2 en dalgún otru "
+"sistema operativu."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linia comandos Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La siguiente llinia de comandu Linux salió de /etc/default/grub o del "
+"parámetru `kopt' nel menú Legacy GRUB menu.lst. Por favor, comprueba que ye "
+"correuto, y modificalo si ye necesario. La llinia de comandu puede tar erma."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linia comandos por defeutu de Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"La siguiente cadena será usada como parámetros Linux pa la entrada del menú "
+"por defeutu, pero non pal mou recuperación."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Linia comandos kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La siguiente llinia de comandu kFreeBSD salió de /etc/default/grub o del "
+"parámetru `kopt' nel menú Legacy GRUB menu.lst. Por favor, comprueba que ye "
+"correuto, y modificalo si ye necesario. La lliniea de comandu puede tar erma."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Llínia comandos por defeutu kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"La siguiente cadena será usada cómo parametros kFreeBSD pa la entrada del "
+"menú por defeutu, pero non pal mou recuperación."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map foi xeneráu"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "El ficheru /boot/grub/device.map foi sobroescritu pa usar nomes estables "
+#~ "pal preséu. Na mayoría de los casos, esto va a amenorgar "
+#~ "considerablemente la necesidá de camudar nel futuru, y les entraes del "
+#~ "menú d'arranque GRUB xeneraos nun deberíen vese afectaes."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Sicasí, ya tienes más d'un discu nel to sistema, ye posible que "
+#~ "dependieres del mapa antigüu del preséu. Por favor, comprueba si tienes o "
+#~ "non entraes d'arranque del menú personalizaes que se basen na númberación "
+#~ "de la unidá GRUB's (hdN), y anovalos si ye necesario."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Si nun entiendes esti mensaxe, o si nun tienes nenguna entrada "
+#~ "personalizada nel menú d'arranque, puedes ignorar esti mensaxe."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "En cualisquier casu, cuando quieras que GRUB 2 seya cargáu directamente "
+#~ "dende'l MBR, puedes facelo col siguiente comandu (como root):"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "La instalación de GRUB falló. ¿Siguir?"
diff --git a/debian/po/be.po b/debian/po/be.po
new file mode 100644
index 0000000..a7992c7
--- /dev/null
+++ b/debian/po/be.po
@@ -0,0 +1,524 @@
+# Belarusian translation of grub2 templates
+# Copyright (C) 2009 respective translators (see below)
+# This file is distributed under the same license as the grub2 package.
+# Hleb Rubanau <g.rubanau@gmail.com>, 2009,
+# Viktar Siarheichyk <vics@eq.by>, 2010, 2012, 2014.
+# Viktar Siarheichyk <vics@fsfe.org>, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: be\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-23 11:22+0300\n"
+"Last-Translator: Viktar Siarheichyk <vics@fsfe.org>\n"
+"Language-Team: Debian l10n team for Belarusian <debian-l10n-belarusian@lists."
+"debian.org>\n"
+"Language: be\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Virtaal 0.7.1\n"
+"X-Poedit-Language: Belarusian\n"
+"X-Poedit-Country: BELARUS\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Ð›Ð°Ð½Ñ†ÑƒÐ³Ð¾Ð²Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° з menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Скрыпты Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ GRUB выÑвілі папÑÑ€Ñднюю верÑÑ–ÑŽ GRUB, уÑталÑваную Ñž /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Каб замÑніць папÑÑ€Ñднюю верÑÑ–ÑŽ GRUB у Вашай ÑÑ–ÑÑ‚Ñме, пажадана выправіць "
+"файл /boot/grub/menu.lst такім чынам, каб GRUB 2 загружаўÑÑ Ð· Ñ–Ñнуючай "
+"папÑÑ€ÑднÑй верÑÑ–Ñ– GRUB. Зараз можна зрабіць гÑтую наладку аўтаматычна."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Раім абраць ланцуговую загрузку GRUB 2 з menu.lst, і праверыць, што нанова "
+"ÑžÑталÑваны GRUB 2 працуе, перад тым Ñк уÑталёўваць Ñго Ñž галоўны загрузачны "
+"Ð·Ð°Ð¿Ñ–Ñ (MBR, Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Як бы вы ні вырашылі, можна пазней замÑніць Ñтары вобраз MBR на GRUB 2, калі "
+"выканаць Ñк root наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ ÐºÐ°Ð¼Ð°Ð½Ð´Ñ‹:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Прылады, на ÑÐºÑ–Ñ ÑžÑталёўваць GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"x`Пакет grub-pc абнаўлÑецца. ГÑтае меню дазвалÑе абраць, Ð´Ð»Ñ Ñкіх прыладаў "
+"Ñ‚Ñ€Ñба, калі ўвогуле Ñ‚Ñ€Ñба, аўтаматычна запуÑкаць grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"У большаÑці выпадкаў Ñ€Ñкамендуецца запуÑкаць grub-install аўтаматычна, каб "
+"уÑталÑваны аÑноўны вобраз GRUB заÑтаваўÑÑ Ñž адпаведнаÑці з модулÑмі GRUB Ñ– "
+"grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Калі вы не пÑўныÑ, ÑÐºÐ°Ñ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ð° Ñž вашым BIOS Ð¿Ñ€Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ð°Ñ Ñк галоўнаÑ, то "
+"хутчÑй за ÑžÑÑ‘ лепей будзе ÑžÑталÑваць GRUB на Ñ–Ñ… уÑÑ–Ñ…."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Увага: такÑама магчыма ÑžÑталÑваць GRUB у Ñектары пачатковай загрузкі "
+"падзелаў, Ñ– Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð°Ð´Ð¿Ð°Ð²ÐµÐ´Ð½Ñ‹Ñ Ð¿Ð°Ð´Ð·ÐµÐ»Ñ‹ тут прапануюцца. Ðднак, Ð´Ð»Ñ Ð³Ñтага "
+"GRUB муÑіць карыÑтацца механізмам ÑпіÑаў блокаў, што змÑншае надзейнаÑць Ñ– "
+"таму не Ñ€Ñкамендуецца."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Пачатковы запуÑкальнік GRUB раней быў уÑталÑваны на дыÑк, Ñкі зараз "
+"адÑутнічае, альбо чый унікальны ідÑнтыфікатар па нейкай прычыне змÑніўÑÑ. "
+"Важна, каб уÑталÑваны аÑноўны вобраз GRUB адпавÑдаў модулÑм GRUB Ñ– grub.cfg. "
+"Калі лаÑка, праверце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·, каб упÑўніцца, што GRUB запіÑаны Ñž Ð°Ð´Ð¿Ð°Ð²ÐµÐ´Ð½Ñ‹Ñ "
+"Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°Ð²Ñ‹Ñ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ñ‹."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} Мб; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Ð—Ð°Ð¿Ñ–Ñ GRUB на загрузкавую прыладу не ўдаўÑÑ - працÑгваць?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Ðе атрымалаÑÑ ÑžÑталÑваць GRUB на наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ñ‹:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ð’Ñ‹ жадаеце працÑгваць, не зважаючы на гÑта? Калі працÑгнеце, ваш кампутар "
+"можа не запуÑціцца."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Ðе атрымалаÑÑ Ð·Ð°Ð¿Ñ–Ñаць GRUB у загрузкавую прыладу - паÑпрабаваць ізноў?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Магчыма, што вы зможаце ÑžÑталÑваць GRUB на нейкую іншую прыладу, але вам "
+"варта Ñпраўдзіць, што Ð²Ð°ÑˆÐ°Ñ ÑÑ–ÑÑ‚Ñма запуÑціцца з гÑтае прылады. Іначай, "
+"абнаўленне з папÑÑ€ÑднÑе верÑÑ–Ñ– GRUB будзе адмененае."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "ПрацÑгваць, не ÑžÑталёўваючы GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Ð’Ñ‹ выбралі не ÑžÑталёўваць GRUB ні на Ñкую прыладу. Калі Ð’Ñ‹ працÑгнеце далей, "
+"пачатковы запуÑкальнік, магчыма, не будзе Ñканфігураваны належным чынам, Ñ– "
+"калі гÑÑ‚Ñ‹ кампутар запуÑціцца наÑтупным разам, ён загрузіцца з таго, што "
+"было раней у Ñектары запуÑку. Калі там была ÑÑ‚Ð°Ñ€Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ GRUB 2, ён можа не "
+"здолець загрузіць модулі альбо не разабраць цÑперашні канфігурацыйны файл."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Калі Ð’Ñ‹ ўжо карыÑтаецеÑÑ Ñ–Ð½ÑˆÑ‹Ð¼ пачатковым запуÑкальнікам Ñ– хочаце так рабіць "
+"Ñ– надалей альбо калі гÑта адмыÑловае аÑÑроддзе, дзе загрузчык непатрÑбны, то "
+"вам варта ÑžÑÑ‘ ж працÑгваць. Іначай вам Ñ‚Ñ€Ñба некуды ÑžÑталÑваць GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Выдаліць GRUB 2 з /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Хочаце выдаліць уÑе файлы GRUB 2 з /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"З-за гÑтага ÑÑ–ÑÑ‚Ñма будзе не Ñž Ñтане запуÑціцца, пакуль не будзе ÑžÑталÑваны "
+"іншы пачатковы запуÑкальнік."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Скончыць зараз перавод на GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ðа гÑтай ÑÑ–ÑÑ‚Ñме ÑžÑÑ‘ ÑÑˆÑ‡Ñ ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ з папÑÑ€ÑднÑе верÑÑ–Ñ– загрузчыка "
+"GRUB, але зараз тут такÑама ÑžÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·Ñ‡Ñ‹ÐºÑ– GRUB 2 на наÑтупных "
+"дыÑках:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Падаецца, што папÑÑ€ÑднÑÑ Ð²ÐµÑ€ÑÑ–Ñ GRUB болей не выкарыÑтоўваецца, Ñ– што вы "
+"павінны замеÑÑ‚ гÑтага абнавіць вобразы GRUB 2 на гÑÑ‚Ñ‹Ñ… дыÑках Ñ– Ñкончыць "
+"пераход на GRUB 2, выдаліўшы ÑÑ‚Ð°Ñ€Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ папÑÑ€ÑднÑй верÑÑ–Ñ– GRUB. Калі вы не "
+"абновіце гÑÑ‚Ñ‹Ñ Ð²Ð¾Ð±Ñ€Ð°Ð·Ñ‹ GRUB 2, то Ñны могуць Ñтаць неÑумÑшчальнымі з новымі "
+"пакетамі Ñ– ваша ÑÑ–ÑÑ‚Ñма пераÑтане нармальна запуÑкацца."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Звычайна, Ð’Ñ‹ павінны Ñкончыць пераход на GRUB 2, калі толькі гÑÑ‚Ñ‹Ñ "
+"загрузчыкі не былі ÑÑ‚Ð²Ð¾Ñ€Ð°Ð½Ñ‹Ñ ÑžÑталёўкай GRUB 2 на нейкай іншай аперацыйнай "
+"ÑÑ–ÑÑ‚Ñме."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Радок камандаў Ð´Ð»Ñ Ñдра Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ГÑÑ‚Ñ‹ радок камандаў Ð´Ð»Ñ Ñдра Linux узÑÑ‚Ñ‹ з файла /etc/default/grub або з "
+"параметра `kopt' у файле наладак (menu.lst) папÑÑ€ÑднÑй верÑÑ–Ñ– GRUB (Legacy). "
+"Калі лаÑка, пераканайцеÑÑ, што каманды запіÑÐ°Ð½Ñ‹Ñ Ð¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°, або папраўце Ñ–Ñ…, "
+"калі Ñ‚Ñ€Ñба. ГÑÑ‚Ñ‹ радок камандаў можа быць пуÑтым."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Прадвызначаны радок камандаў Ð´Ð»Ñ Ñдра Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"ÐаÑтупны радок будзе выкарыÑтаны Ñž ÑкаÑці параметраў Ñдра Linux Ð´Ð»Ñ "
+"прадвызначанага пункту меню (але не Ð´Ð»Ñ Ñ€Ñжыму аднаўленнÑ)."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "ПрымуÑова ÑžÑталÑваць дадаткова па адраÑе EFI на зменным ноÑьбце?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"ÐÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ EFI-ÑÑ–ÑÑ‚Ñмы утрымліваюць памылкі Ñ– некарÑктна працуюць з новымі "
+"пачатковымі загрузчыкамі. Калі вы прымуÑова ÑžÑталюеце дадаткова па адраÑе "
+"EFI на зменным ноÑьбіце, Ñ‚Ñ€Ñба ўпÑўніцца, што гÑÑ‚Ð°Ñ ÑÑ–ÑÑ‚Ñма карÑктна "
+"загрузіць Debian, нÑгледзÑчы на такую праблему. Ðднак, з-за гÑтага можа "
+"Ñтраціцца магчымаÑць запуÑціць любую іншую аперацыйную ÑÑ–ÑÑ‚Ñму (ÐС), ÑÐºÐ°Ñ "
+"такÑама выкарыÑтоўвае гÑÑ‚Ñ‹ ноÑьбіт Ñ– шлÑÑ…. У гÑтым выпадку Ñ‚Ñ€Ñба ўпÑўніцца, "
+"што GRUB правільна Ñканфігураваны Ð´Ð»Ñ ÐºÐ°Ñ€Ñктнага запуÑку іншай ÐС."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Ðбнавіць Ð·Ð¼ÐµÐ½Ð½Ñ‹Ñ NVRAM Ð´Ð»Ñ Ð°ÑžÑ‚Ð°Ð¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ð°Ð³Ð° запуÑку Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB можа так Ñканфігураваць Ð·Ð¼ÐµÐ½Ð½Ñ‹Ñ NVRAM вашай платформы, каб Ñна "
+"аўтаматычна запуÑкала Debian пры ўключÑнні. Ðднак магчыма, вам ÑпатрÑбіцца "
+"адключыць гÑта Ñ– не змÑнÑць вашу канфігурацыю запуÑку. Ðапрыклад, калі вашы "
+"Ð·Ð¼ÐµÐ½Ð½Ñ‹Ñ NVRAM наÑтроеныÑ, каб ваша ÑÑ–ÑÑ‚Ñма кантактавала Ñервер PXE пры "
+"кожным запуÑку, гÑта захавае такі Ñ€Ñжым."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Радок камандаў Ð´Ð»Ñ Ñдра kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ГÑÑ‚Ñ‹ радок камандаў Ð´Ð»Ñ kFreeBSD узÑÑ‚Ñ‹ з файлу /etc/default/grub або з "
+"параметру `kopt' у файле наладак (menu.lst) папÑÑ€ÑднÑй верÑÑ–Ñ– GRUB (Legacy). "
+"Калі лаÑка, пераканайцеÑÑ, што каманды запіÑÐ°Ð½Ñ‹Ñ Ð¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°, або папраўце Ñ–Ñ…, "
+"калі Ñ‚Ñ€Ñба. ГÑÑ‚Ñ‹ радок камандаў можа быць пуÑтым."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Прадвызначаны радок камандаў Ð´Ð»Ñ Ñдра kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"ÐаÑтупны радок будзе выкарыÑтаны Ñž ÑкаÑці параметраў Ñдра kFreeBSD Ð´Ð»Ñ "
+"прадвызначанага пункту меню (але не Ð´Ð»Ñ Ñ€Ñжыму аднаўленнÑ)."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map быў перагенераваны"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Файл /boot/grub/device.map быў перапіÑаны, каб выкарыÑтоўваць ÑÑ‚Ð°Ð±Ñ–Ð»ÑŒÐ½Ñ‹Ñ "
+#~ "імёны прыладаў. У бальшыні выпадкаў гÑта значна знізіць неабходнаÑць "
+#~ "змÑнÑць Ñго Ñž будучыні, Ñ– пункты загрузачнага меню, Ð·Ð³ÐµÐ½ÐµÑ€Ð°Ð²Ð°Ð½Ñ‹Ñ GRUB, не "
+#~ "давÑдзецца закрануць."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ðднак, паколькі Ñž вашай ÑÑ–ÑÑ‚Ñме больш за адзін дыÑк, то магчыма, што Ñž "
+#~ "ÑÑ–ÑÑ‚Ñме выкарыÑтоўваецца ÑÑ‚Ð°Ñ€Ð°Ñ Ñ‚Ð°Ð±Ð»Ñ–Ñ†Ð° прыладаў. Праверце, ці Ñ‘Ñць "
+#~ "пункты загрузкавага меню, што ўжываюць нумарацыю прыладаў GRUB (hdN) і "
+#~ "абнавіце Ñ–Ñ…, калі патрÑбна."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Калі вы не зразумелі гÑтае паведамленне, альбо калі вы не маеце ўлаÑных "
+#~ "пунктаў загрузкавага меню, вы можаце ігнараваць гÑтае паведамленне."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Калі ж Ð’Ñ‹ хочаце, каб GRUB 2 запуÑкаўÑÑ Ð½ÐµÐ¿Ð°ÑÑ€Ñдна з MBR, даÑтаткова "
+#~ "запуÑціць з правамі карыÑтальніка root наÑтупную каманду:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Ðе атрымалаÑÑ ÑžÑталÑваць GRUB. ПрацÑгваць?"
+
+#~ msgid "GRUB 1.95 numbering scheme transition"
+#~ msgstr "Змена Ñхемы нумарацыі GRUB 1.95"
+
+#~ msgid ""
+#~ "As of version 1.95, GRUB 2 has changed its numbering scheme. Partitions "
+#~ "are now counted starting from 1 rather than 0. This is to make it "
+#~ "consistent with device names of Linux and the other kernels used in "
+#~ "Debian. For example, when using Linux as the kernel, \"(hd0,1)\" refers "
+#~ "to the same partition as the /dev/sda1 device node."
+#~ msgstr ""
+#~ "Схема нумарацыі Ñž GRUB 2 змÑнілаÑÑ Ñž параўнанні з верÑÑ–Ñй 1.95 . Зараз "
+#~ "падзелы дыÑку адлічваюцца пачынаючы з 1 замеÑÑ‚ 0. ГÑта зроблена, каб "
+#~ "адпавÑдаць назвам прыладаў у Linux Ñ– іншых Ñдрах, ÑÐºÑ–Ñ Ð²Ñ‹ÐºÐ°Ñ€Ñ‹Ñтоўваюцца Ñž "
+#~ "Debian. Ðапрыклад, калі Ñž ÑкаÑці Ñдра выкарыÑтоўваецца Linux, радок "
+#~ "\"(hd0,1)\" датычыцца таго Ñамага падзелу дыÑку, Ñк Ñ– файл прылады /dev/"
+#~ "sda1."
+
+#~ msgid ""
+#~ "Because of this, there's a chance your system becomes unbootable if "
+#~ "update-grub(8) is run before GRUB is updated, generating a grub.cfg file "
+#~ "that your installed GRUB won't yet be able to parse correctly. To ensure "
+#~ "your system will be able to boot, you have to:"
+#~ msgstr ""
+#~ "З гÑтай прычыны Ваша ÑÑ–ÑÑ‚Ñма можа Ñтаць нÑздольнай да загрузкі, калі "
+#~ "праграма update-grub(8), Ð·Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð½Ð°Ñ Ð´Ð° Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ GRUB, Ñтварыла файл "
+#~ "grub.cfg, Ñкі немагчыма карÑктна апрацаваць уÑталÑваным GRUB. Каб "
+#~ "пераканацца, што Ваша ÑÑ–ÑÑ‚Ñма Ð·Ð´Ð¾Ð»ÑŒÐ½Ð°Ñ Ð´Ð° загрузкі, варта: "
+
+#~ msgid ""
+#~ " - Reinstall GRUB (typically, by running grub-install).\n"
+#~ " - Rerun update-grub to generate a new grub.cfg."
+#~ msgstr ""
+#~ " - ПераўÑталÑваць GRUB (звычайна, праз запуÑк grub-install).\n"
+#~ " - ПеразапуÑціць update-grub, каб Ñтварыць новы grub.cfg."
diff --git a/debian/po/bg.po b/debian/po/bg.po
new file mode 100644
index 0000000..cfda91e
--- /dev/null
+++ b/debian/po/bg.po
@@ -0,0 +1,483 @@
+# Bulgarian translation of grub2 debconf messages.
+# Copyright (C) grub2 packagers.
+# This file is distributed under the same license as the grub2 package.
+# Damyan Ivanov <dmn@debian.org>, 2009, 2010, 2011, 2014, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-20 21:19+0200\n"
+"Last-Translator: Damyan Ivanov <dmn@debian.org>\n"
+"Language-Team: БългарÑки <dict@fsa-bg.org>\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Gtranslator 2.91.7\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Верижно зареждане от menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "Открита е Ñтара инÑÑ‚Ð°Ð»Ð°Ñ†Ð¸Ñ Ð½Ð° GRUB в /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"За замÑна на Ñтарата инÑÑ‚Ð°Ð»Ð°Ñ†Ð¸Ñ Ð½Ð° GRUB Ñе препоръчва наÑтройване на /boot/"
+"grub/menu.lst за каÑкадно зареждане на GRUB2 от ÑъщеÑтвуващата инÑÑ‚Ð°Ð»Ð°Ñ†Ð¸Ñ Ð½Ð° "
+"GRUB. Това може да извършено автоматично."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"КаÑкадното зареждане на GRUB2 от menu.lst Ñе препоръчва за да е Ñигурно, че "
+"наÑтройките на GRUB2 Ñа правилни, преди инÑталирането му в запиÑа за начално "
+"зареждане (MBR)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Каквото и да решите, по-къÑно можете да замените ÑÑ‚Ð°Ñ€Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ Ð² MBR Ñ Ñ‚Ð¾Ð·Ð¸ "
+"на GRUB2 ÑÑŠÑ Ñледната команда, изпълнена като админиÑтратор:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "ИнÑталиране на GRUB на Ñледните уÑтройÑтва:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Пакетът grub-pc Ñе обновÑва. Това меню позволÑва избиране за кои уÑтройÑтва "
+"(и дали изобщо) да Ñе изпълни командата grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Ð’ повечето Ñлучаи автоматичното изпълнение на grub-install Ñе препоръчва за "
+"предотвратÑване на разминаване между образа на GRUB на диÑка и модулите или "
+"файла grub.cfg във файловата ÑиÑтема."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ðко не Ñте Ñигурни кое уÑтройÑтво е определено за начално зареждане в BIOS, "
+"добра Ð¸Ð´ÐµÑ Ðµ да инÑталирате GRUB на вÑички налични уÑтройÑтва."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Забележка: по принцип е възможно GRUB да Ñе инÑталира на запиÑите за начално "
+"зареждане на диÑковите дÑлове. СпиÑъка включва подходÑщи дÑлове, но подобна "
+"инÑÑ‚Ð°Ð»Ð°Ñ†Ð¸Ñ Ñ‰Ðµ накара GRUB да използва ÑпиÑъци Ñ Ð±Ð»Ð¾ÐºÐ¾Ð²Ðµ, което прави "
+"работата му по-малко надеждна и поради тази причина не Ñе препоръчва."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Програмата за начално зареждане на GRUB е била инÑталирана на диÑк, който "
+"вече не е доÑтъпен или чийто уникален идентификатор е бил променен. Много е "
+"важно инÑталираниÑÑ‚ образ винаги да е Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° модулите на GRUB и файла "
+"grub.cfg на файловата ÑиÑтема. Проверете и Ñе убедете, че GRUB Ñе инÑталира "
+"на правилните уÑтройÑтва."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+"ЗапиÑването на GRUB върху уÑтройÑтвото за начално зареждане не уÑпÑ. "
+"Продължаване?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Опитът за инÑталиране на GRUB на Ñледните уÑтройÑтва беше неуÑпешен:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Желаете ли да продължите въпреки това? Ðко го направите е възможно "
+"компютърът да не може да зареди операционна ÑиÑтема."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"ЗапиÑването на GRUB върху уÑтройÑтвото за начално зареждане на уÑпÑ. Ðов "
+"опит?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Възможно е инÑталирането на GRUB на друго уÑтройÑтво да уÑпее, но Ñ‚Ñ€Ñбва да "
+"проверите дали компютърът може да извършва първоначално зареждане от него. "
+"Ðко откажете, обновÑването от ÑÑ‚Ð°Ñ€Ð¸Ñ GRUB ще бъде отменено."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Продължаване без инÑталиране на GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Избрано е GRUB да не Ñе инÑталира на никакви уÑтройÑтва. Ðко продължите, "
+"програмата за начално зареждане може да не е наÑтроена правилно и при "
+"Ñледващото Ñтартиране на компютъра ще Ñе използва предишното Ñъдържание на "
+"Ñектора за начално зареждане. Ðко в него има предишна инÑÑ‚Ð°Ð»Ð°Ñ†Ð¸Ñ Ð½Ð° GRUB 2 е "
+"възможно Ñ‚Ñ Ð´Ð° не уÑпее да използва обновените модули или ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ "
+"файл."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ðко използвате друга програма за начално зареждане и желаете да Ñ Ð·Ð°Ð¿Ð°Ð·Ð¸Ñ‚Ðµ "
+"или ако обкръжението е Ñпециално и не изиÑква програма за начално зареждане, "
+"тогава е редно да продължите без да инÑталирате GRUB. Ð’ противен Ñлучай би "
+"Ñ‚Ñ€Ñбвало да инÑталирате GRUB нÑкъде."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Изтриване на GRUB 2 от /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Желаете ли да изтриете вÑички файлове на GRUB от папката /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Това ще възпрепÑÑ‚Ñтва зареждането на ÑиÑтемата, до инÑталиране на друга "
+"програма за начално зареждане."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Завършване на преминаването към GRUB2 ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ðа ÑиÑтемата има файлове от ÑÑ‚Ð°Ñ€Ð¸Ñ GRUB, но има Ñектори за начално зареждане "
+"от GRUB 2, инÑталирани на Ñледните диÑкове:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Изглежда, че ÑтариÑÑ‚ GRUB не Ñе използва и вмеÑто него е редно Ñе инÑталира "
+"GRUB 2 върху диÑковете и да Ñе завърши прехода чрез премахване на файловете "
+"на ÑÑ‚Ð°Ñ€Ð¸Ñ GRUB. Ðко не обновите инÑталациÑта на GRUB 2 е възможно да Ñе "
+"поÑвÑÑ‚ проблеми Ñ Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¾Ñ‚Ð¾ зареждане поради неÑъвмеÑтимоÑÑ‚ Ñ Ð½Ð¾Ð²Ð¸Ñ‚Ðµ пакети."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Ð’ Ð¾Ð±Ñ‰Ð¸Ñ Ñлучай е добре преходът към GRUB 2 да бъде завършен, оÑвен ако "
+"Ñекторите за начално зареждане Ñа Ñъздадени от GRUB 2 или от друга "
+"операционна ÑиÑтема."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Команден ред на ЛинукÑ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ð¡Ð»ÐµÐ´Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ÐµÐ½ ред за зареждане на Ð›Ð¸Ð½ÑƒÐºÑ Ð±ÐµÑˆÐµ извлечен от /etc/default/"
+"grub или от параметъра „kopt“ от файла menu.lst на ÑÑ‚Ð°Ñ€Ð¸Ñ GRUB. Проверете го "
+"и ако е нужно го коригирайте. ДопуÑтимо е командниÑÑ‚ ред да бъде празен."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Параметри на Ð›Ð¸Ð½ÑƒÐºÑ Ð¿Ð¾ подразбиране:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Следните параметри ще бъдат използвани по подразбиране при зареждане на "
+"ЛинукÑ, оÑвен в авариен режим."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+"Допълнително инÑталиране в Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¸Ñ Ð¿ÑŠÑ‚ на EFI за преноÑими уÑтройÑтва?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"ÐÑкои базирани на EFI ÑиÑтеми Ñъдържат грешки и не работÑÑ‚ добре Ñ Ð´Ð¾Ð±Ð°Ð²ÐµÐ½Ð¸ "
+"програми за начално зареждане (като GRUB). Допълнителното инÑталиране на "
+"GRUB в Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¸Ñ Ð¿ÑŠÑ‚ за преноÑими уÑтройÑтва ще оÑигури правилно зареждане "
+"на Дебиан дори и ако ÑиÑтемата има такъв проблем. Това обаче ще попречи на "
+"зареждането на други операционни ÑиÑтеми, които може да разчитат на този "
+"път. Ð’ такъв Ñлучай Ñ‚Ñ€Ñбва да Ñе уверите, че GRUB е наÑтроен да зарежда "
+"другите операционни ÑиÑтеми."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "ПромÑна на параметрите в NVRAM за автоматично зареждане на Дебиан?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB може да наÑтрои параметрите в NVRAM на ÑиÑтемата така че при включване "
+"на захранването да Ñе зарежда Дебиан. Ðко имате Ñпециални нужди като "
+"например връзка Ñ PXE Ñървър при начално зареждане може да предпочетете да "
+"не Ñе правÑÑ‚ промени."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Команден ред за kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ð¡Ð»ÐµÐ´Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ÐµÐ½ ред за зареждане на kFreeBSD беше извлечен от /etc/default/"
+"grub или от параметъра „kopt“ от файла menu.lst на ÑÑ‚Ð°Ñ€Ð¸Ñ GRUB. Проверете го "
+"и ако е нужно го коригирайте. ДопуÑтимо е командниÑÑ‚ ред да бъде празен."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Параметри на Ð›Ð¸Ð½ÑƒÐºÑ Ð¿Ð¾ подразбиране:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Следните параметри ще бъдат използвани по подразбиране при зареждане на "
+"kFreeBSD, оÑвен в авариен режим."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map е Ñъздаден наново"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Файлът /boot/grub/device.map е Ñъздаден наново, използвайки поÑтоÑнни "
+#~ "имена на уÑтройÑтва. Ð’ повечето Ñлучаи това води до намалÑване на нуждата "
+#~ "да Ñе правÑÑ‚ промени в бъдеще. Елементите в менюто за начално зареждане "
+#~ "на GRUB не Ñа заÑегнати."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ð’Ñе пак, понеже в ÑиÑтемата има повече от един диÑк, е възможно "
+#~ "Ñъдържанието на ÑÑ‚Ð°Ñ€Ð¸Ñ Ñ„Ð°Ð¹Ð» да е от критична важноÑÑ‚. Проверете дали "
+#~ "имате елементи в менюто за начално зареждане на GRUB, в които да Ñе "
+#~ "използват уÑтройÑтва от вида „(hdN)“ и ако е нужно ги коригирайте."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ðко не разбирате предупреждението или ако нÑмате ръчно-въведени елементи "
+#~ "в менюто на GRUB, не обръщайте внимание на това Ñъобщение."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Когато речите да инÑталирате GRUB 2 в запиÑа за начално зареждане, "
+#~ "изпълнете Ñледната команда като админиÑтратор:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "ИнÑталирането на GRUB Ñе провали. Продължаване?"
diff --git a/debian/po/ca.po b/debian/po/ca.po
new file mode 100644
index 0000000..43dad90
--- /dev/null
+++ b/debian/po/ca.po
@@ -0,0 +1,490 @@
+# Catalan translation of grub2's debconf messages
+# Copyright © 2009, 2010, 2011 Free Software Foundation, Inc.
+# This file is distributed under the same license as the grub2 package.
+#
+# Jordi Mallach <jordi@debian.org>, 2009, 2010, 2011.
+# Juan Andrés Gimeno Crespo <juagicre@gmail.com>, 2009.
+# Innocent De Marchi <tangram.peces.gmail.com>, 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.02~beta3-4\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-23 17:31+0100\n"
+"Last-Translator: Innocent De Marchi <tangram.peces@gmail.com>\n"
+"Language-Team: Catalan <debian-l10n-catalan@lists.debian.org>\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.11\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Voleu carregar en cadena des del menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Els scripts d'actualització del GRUB han detectat una configuració del GRUB "
+"Legacy en /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"A l'hora de reemplaçar la versió Legacy del GRUB que hi ha al sistema, és "
+"recomanable que es modifique /boot/grub/menu.lst per a carregar una imatge "
+"d'arrencada del GRUB 2 des de la vostra configuració del GRUB Legacy "
+"existent. Aquest pas es pot dur a terme ara."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"És recomanable que accepteu la càrrega en cadena del GRUB 2 des del menu."
+"lst, per a verificar que la nova configuració del GRUB 2 funciona "
+"correctament, abans de que s'escriga al registre mestre d'arrencada (MBR)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Independentment de la vostra decisió, podeu reemplaçar la imatge antiga de "
+"l'MBR amb el GRUB2 executant l'ordre següent com a root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Dispositius d'instaŀlació del GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"S'està actualitzant el paquet grub-pc. Aquest menú us permet seleccionar "
+"sobre quins dispositius voleu que s'execute el grub-install automàticament, "
+"en cas de voler-ho."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"L'execució automàtica del grub-install és recomanable en la majoria de les "
+"situacions, per a evitar que la imatge del nucli del GRUB es desincronitze "
+"amb els mòduls del GRUB o el grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Si no esteu segur sobre quina és la unitat designada com a unitat "
+"d'arrencada per la BIOS, normalment és una bona idea instaŀlar el GRUB a "
+"tots ells."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: també és possible instaŀlar el GRUB a registres d'arrencada de "
+"particions, i s'ofereixen algunes particions adients. Tanmateix, això força "
+"al GRUB a usar el mecanisme de llistes de blocs, que fa que siga menys "
+"fiable, per la qual cosa no és recomanable."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"El carregador GRUB estava instaŀlat a un disc que ja no és present, o per al "
+"qual ha canviat el seu identificador únic per alguna raó. És important "
+"assegurar-se que la imatge del nucli del GRUB roman sincronitzada amb els "
+"mòduls del GRUB i el grub.cfg. Comproveu de nou que el GRUB s'escriu als "
+"dispositius d'arrencada apropiats."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Ha fallat l'escriptura del GRUB al dispositiu. Voleu continuar?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "El GRUB no s'ha pogut instaŀlar als dispositius següents:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Voleu continuar tot i això? Si ho feu, és possible que l'ordinador no "
+"arrenque correctament."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Ha fallat l'escriptura del GRUB al dispositiu. Voleu tornar a provar-ho?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"És possible que pugueu instaŀlar el GRUB en un altre dispositiu, tot i que "
+"hauríeu de comprovar que el sistema arrencarà des d'aquell dispositiu. En "
+"cas contrari, es canceŀlarà l'actualització des del GRUB Legacy."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Voleu continuar sense instaŀlar el GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Heu triat no instaŀlar el GRUB en cap dispositiu. Si continueu, és possible "
+"que el carregador no estiga configurat correctament, i quan s'arrenque "
+"l'ordinador la pròxima vegada, emprarà allò que estigués al sector "
+"d'arrencada. Si hi ha una versió anterior del GRUB2 al sector d'arrencada, "
+"és possible que no puga carregar mòduls o gestionar el fitxer de "
+"configuració actual."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Si ja esteu emprant un altre carregador i voleu continuar fent-ho, o aquest "
+"és un entorn especial on no necessiteu un carregador, hauríeu de continuar. "
+"Si no és així, hauríeu d'instaŀlar el GRUB en algun lloc."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Voleu suprimir el GRUB 2 de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Voleu suprimir tots els fitxers del GRUB 2 de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Això farà que el sistema no arrenque si no s'instaŀla un altre carregador."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Voleu finalitzar la conversió al GRUB 2 ara?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Aquest sistema encara té fitxers antics del carregador GRUB Legacy "
+"instaŀlats, però ara també té registres d'arrencada del GRUB 2 instaŀlats "
+"als discs següents:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Sembla probable que el GRUB Legacy no estiga ja en ús, i que hauríeu "
+"d'actualitzar les imatges del GRUB 2 presents a aquests discs per a "
+"finalitzar la conversió al GRUB 2, suprimint els fitxers vells del GRUB "
+"Legacy. Si no actualitzeu aquestes imatges del GRUB 2, és possible que "
+"romanen incompatibles amb els paquets nous i que causen que el sistema deixe "
+"d'arrencar correctament."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"En general, hauríeu de finalitzar la conversió al GRUB 2 a no ser que "
+"aquests registres d'arrencada els haja creat una instaŀlació del GRUB 2 des "
+"d'un altre sistema operatiu."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Línia d'ordres de Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La línia d'ordres de Linux següent ha sigut extreta de /etc/default/grub o "
+"del paràmetre «kopt» del fitxer menu.lst del GRUB Legacy. Verifiqueu que és "
+"correcta, i modifiqueu-la si és necessari. La línia d'ordres pot ser buida."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Línia d'ordres de Linux per defecte:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"La cadena següent serà emprada com a paràmetres del Linux per al menú "
+"d'entrada per defecte però no per al mode de recuperació."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+"Forçar la instal·lació addicional de EFI per la ruta a mitjans extraïbles?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Alguns sistemes basats en EFI tenen errors i no gestionen correctament els "
+"nous carregadors d'arrencada. Si forçau la instal·lació del GRUB en mitjans "
+"extraïbles, això hauria de garantir que el sistema arranqui correctament amb "
+"Debian tot i aquest problema. Però pot impedir que es pugui arrencar un "
+"altre sistema operatiu que també depengui de la mateixa ruta. En aquest cas, "
+"heu d'assegurar-vos que GRUB està correctament configurat per a arrencar "
+"qualsevol altre sistema operatiu correctament."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Actualitzar les variables NVRAM per arrancar automàticament Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB pot configurar les variables NVRAM de la vostra plataforma per iniciar "
+"automàticament Debian quan s'engegui. També pot ésser que desitgeu "
+"deshabilitar aquest possibilitat i evitar canvis en la configuració de "
+"l'arrencada. Per exemple, si les variables NVRAM estan configurades de "
+"manera que el vostre sistema connecta amb un servidor PXE cada vegada que "
+"arranca, això hauria de conservar aquest comportament."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Línia d'ordres de kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La línia d'ordres de kFreeBSD següent ha sigut extreta de /etc/default/grub "
+"o del paràmetre «kopt» del fitxer menu.lst del GRUB Legacy. Verifiqueu que "
+"és correcta, i modifiqueu-la si és necessari. La línia d'ordres pot ser "
+"buida."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Línia d'ordres de kFreeBSD per defecte:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"La cadena següent serà emprada com a paràmetres del kFreeBSD per al menú "
+"d'entrada per defecte però no per al mode de recuperació."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "S'ha regenerat el fitxer «/boot/grub/device.map»"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "S'ha reescrit el fitxer «/boot/grub/device.map» per a usar noms estables "
+#~ "de dispositiu. En la majoria dels casos, això hauria de reduir la "
+#~ "necessitat de canviar-ho en el futur, i no hauria d'afectar les entrades "
+#~ "del menú d'arrencada generades pel GRUB."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Tanmateix, com hi ha més d'un disc al sistema, és possible que el sistema "
+#~ "depenga del mapa de dispositius antic. Comproveu si hi ha entrades del "
+#~ "menú d'arrencada personalitzades que requerisquen la numeració d'unitats "
+#~ "del GRUB (hdN), i actualitzeu-les si és necessari."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Si no enteneu aquest missatge, o si no hi ha cap entrada del menú "
+#~ "d'arrencada personalitzada, podeu descartar aquest missatge."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "En qualsevol cas, quan vulgueu que es carregue el GRUB 2 directament des "
+#~ "de l'MBR, podeu fer-ho executant (com a root) l'ordre següent:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Ha fallat la instaŀlació del GRUB. Voleu continuar?"
diff --git a/debian/po/cs.po b/debian/po/cs.po
new file mode 100644
index 0000000..3cfc53c
--- /dev/null
+++ b/debian/po/cs.po
@@ -0,0 +1,477 @@
+# Czech translation of grub2 debconf messages.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub2 package.
+# Miroslav Kure <kurem@debian.cz>, 2008 -- 2017
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-22 11:18+0100\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Zavést přes menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"AktualizaÄní skripty GRUBu rozpoznaly v /boot/grub nastavení pro pÅ™edchozí "
+"verzi GRUBu (tzv. GRUB Legacy)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Abyste na svém systému nahradili zastaralou verzi GRUBu, je doporuÄeno "
+"upravit /boot/grub/menu.lst tak, aby zavedl obraz GRUBu 2 pomocí stávajícího "
+"GRUB Legacy. Tento krok je nyní možné provést automaticky."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"PÅ™ed instalací GRUBu 2 přímo do MBR (Master Boot Record) se doporuÄuje "
+"nejprve vyzkoušet zavedení GRUBu 2 skrze menu.lst a teprve po ověření, že "
+"vÅ¡e funguje oÄekávaným způsobem, zkusit instalaci do MBR."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Ať se rozhodnete jakkoliv, obraz v MBR můžete kdykoliv později nahradit "
+"GRUBem 2. StaÄí jako root spustit následující příkaz:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Zařízení pro instalaci GRUBu:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Balík grub-pc se právě aktualizuje. Tato nabídka vám umožňuje zvolit "
+"zařízení, na kterých se má automaticky spouštět grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Automatické spouÅ¡tÄ›ní grub-install je ve vÄ›tÅ¡inÄ› případů doporuÄeno, protože "
+"tak předcházíte tomu, aby se obraz jádra GRUBu rozcházel s GRUB moduly nebo "
+"souborem grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Pokud si nejste jisti, který disk je v BIOSu oznaÄen jako zavádÄ›cí, bývá "
+"Äasto dobrým nápadem nainstalovat GRUB na vÅ¡echny disky."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Poznámka: GRUB je možné instalovat také do zaváděcích záznamů jednotlivých "
+"oblastí, jejichž seznam zde vidíte. Tímto však donutíte GRUB, aby používal "
+"mechanismus zvaný blocklist, který je ménÄ› spolehlivý tudíž se nedoporuÄuje."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"ZavadÄ›Ä GRUB byl dříve nainstalován na disk, který již není dostupný, nebo "
+"jehož unikátní identifikátor se z nějakého důvodu změnil. Je důležité, aby "
+"nainstalovaný obraz jádra GRUBu odpovídal GRUB modulům a souboru grub.cfg. "
+"Ještě jednou se prosím ujistěte, že je GRUB zapsán na příslušných zaváděcích "
+"zařízeních."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Zápis GRUBu na zavádÄ›cí zařízení selhal - pokraÄovat?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB se nepodařilo nainstalovat na následující zařízení:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Chcete pÅ™esto pokraÄovat? Pokud ano, je možné, že poÄítaÄ nemusí korektnÄ› "
+"nastartovat."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Zápis GRUBu na zaváděcí zařízení selhal - zkusit znovu?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Je možné, že se povede instalace GRUBu na nějaké jiné zařízení, ovšem měli "
+"byste se ujistit, že váš systém umí z daného zařízení zavádÄ›t. V opaÄném "
+"případě bude aktualizace z GRUB Legacy zrušena."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "PokraÄovat bez instalace GRUBu?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Rozhodli jste se neinstalovat GRUB na žádné zařízení. Budete-li pokraÄovat, "
+"zavadÄ›Ä nemusí být nastaven správnÄ› a pÅ™i příštím spuÅ¡tÄ›ní poÄítaÄe se "
+"použije cokoliv, co bylo dříve v zaváděcím sektoru. Pokud tam je dřívější "
+"verze GRUBu 2, nemusí se jí podaÅ™it naÄíst moduly, nebo zpracovat souÄasný "
+"konfiguraÄní soubor."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Pokud používáte jiný zavadÄ›Ä a chcete ho používat i nadále, nebo pokud je "
+"toto speciální prostÅ™edí, ve kterém zavadÄ›Ä nepotÅ™ebujete, můžete "
+"pokraÄovat. V opaÄném případÄ› byste nÄ›kam mÄ›li GRUB nainstalovat."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Odstranit GRUB 2 z /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Chcete z /boot/grub odstranit všechny soubory GRUBu 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Tímto se stane systém nezaveditelným do doby, než nainstalujete jiný zavadÄ›Ä."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "DokonÄit nyní pÅ™echod na GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Tento systém stále obsahuje soubory starého zavadÄ›Äe GRUB Legacy, ale na "
+"následujících discích již má zaváděcí záznamy GRUBu 2:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Je dosti pravděpodobné, že se GRUB Legacy již nepoužívá a tudíž byste na "
+"tÄ›chto discích mÄ›li aktualizovat obrazy GRUBu 2 a dokonÄit konverzi na GRUB "
+"2 odstraněním starých souborů z GRUB Legacy. Neaktualizujete-li tyto obrazy "
+"GRUBu 2, nemusí být kompatibilní s novými balíky a mohou způsobit, že se váš "
+"systém přestane zavádět správně."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Obvykle byste mÄ›li konverzi na GRUB 2 dokonÄit, s výjimkou situace, kdy tyto "
+"zavádÄ›cí záznamy vytvoÅ™ila instalace nÄ›jakého jiného operaÄního systému."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Parametry pro Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Následující řádka s parametry pro Linux byla získána ze starého souboru menu."
+"lst z parametru „kopt“ nebo ze souboru /etc/default/grub. Zkontrolujte "
+"prosím, zda jsou parametry v pořádku a případně je upravte do požadované "
+"podoby. Řádka s parametry může být i prázdná."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Výchozí parametry pro Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Následující parametry pro Linux se použijí pro výchozí položku menu, ale ne "
+"pro záchranný režim."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Vynutit další instalaci do EFI cesty pro výměnná média?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Některé systémy používající EFI obsahují chyby a neumí správně pracovat s "
+"novými zavadÄ›Äi. Vynutíte-li další instalaci GRUBu do EFI cesty pro výmÄ›nná, "
+"média, mělo by to zajistit, že se na tomto systému bude Debian zavádět i "
+"přes zmíněné chyby. Tím však můžete přijít o možnost zavádění jiných "
+"operaÄních systémů, které na této cestÄ› také závisí. V takovém případÄ› si "
+"budete muset pohlídat nastavení GRUBu, aby zvládlo zavést ostatní operaÄní "
+"systémy."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Aktualizovat proměnné v NVRAM pro automatické zvedení Debianu?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB může nakonfigurovat NVRAM proměnné na vaší platformě tak, že se po "
+"zapnutí rovnou zavede Debian. Možná ale máte důvod toto chování nepovolit a "
+"do zavádění nezasahavat. Jedním takovým případem by mohla být situace, kdy "
+"máte NVRAM proměnné nastavené tak, aby při každém zavádění kontaktovaly PXE "
+"server."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Parametry pro kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Následující řádka s parametry pro kFreeBSD byla získána ze starého souboru "
+"menu.lst z parametru „kopt“ nebo ze souboru /etc/default/grub. Zkontrolujte "
+"prosím, zda jsou parametry v pořádku a případně je upravte do požadované "
+"podoby. Řádka s parametry může být i prázdná."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Výchozí parametry pro kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Následující parametry pro kFreeBSD se použijí pro výchozí položku menu, ale "
+"ne pro záchranný režim."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map byl aktualizován"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Soubor /boot/grub/device.map byl přepsán tak, aby používal stabilní jména "
+#~ "zařízení. Ve většině případů by to mělo výrazně snížit potřebu jejich "
+#~ "změny v budoucnosti a položky v zaváděcí nabídce vygenerované GRUBem by "
+#~ "neměly být nijak ovlivněny."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Nicméně je možné (protože je v systému více než jeden disk), že se systém "
+#~ "spoléhal na starý soubor device.map. Zkontrolujte prosím, zda používáte "
+#~ "vlastní upravené položky zaváděcí nabídky, které spoléhají na GRUBovské "
+#~ "Äíslování disků (hdN) a podle potÅ™eby je aktualizujte."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Nerozumíte-li této zprávě, nebo pokud žádné vlastní upravené položky "
+#~ "zaváděcí nabídky nemáte, můžete tuto zprávu ignorovat."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Až se rozhodnete zavádÄ›t GRUB 2 přímo z MBR, staÄí jako uživatel root "
+#~ "spustit příkaz:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Instalace GRUBu selhala. PokraÄovat?"
diff --git a/debian/po/cy.po b/debian/po/cy.po
new file mode 100644
index 0000000..a2f94d3
--- /dev/null
+++ b/debian/po/cy.po
@@ -0,0 +1,485 @@
+# Translation of grub2 debconf template to Welsh
+#
+# Copyright (C) 2012
+#
+# This file is distributed under the same license as the grub2 package.
+#
+# Dafydd Tomos <l10n@da.fydd.org>, 2023
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 00:08+0100\n"
+"Last-Translator: Dafydd Tomos <l10n@da.fydd.org>\n"
+"Language-Team: Welsh\n"
+"Language: cy\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Cadwyn-lwytho o menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Mae sgriptiau uwchraddio GRUB wedi canfod gosodiad GRUB etifeddol yn /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Er mwyn disodli yr hen fersiwn o GRUB yn eich system, argymhellir fod /boot/"
+"grub/menu.lst yn cael ei addasu i lwytho delwedd ymgychwyn GRUB 2 o'ch "
+"gosodiad GRUB etifeddol. Gall y cam hwn gael ei wneud yn awtomatig nawr."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Argymhellir eich bod yn derbyn cadwyn-lwytho GRUB 2 o menu.lst, a gwirio fod "
+"y gosodiad GRUB 2 yn gweithio cyn iddo gael ei ysgrifennu i'r Cofnod "
+"Ymgychwyn Meistr (MBR)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Beth bynnag yw eich dewis, fe allwch chi ddisodli eich hen ddelwedd MBR gyda "
+"GRUB 2 nes ymlaen drwy redeg y gorchymyn canlynol fel root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Dyfeisiau sefydlu GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Mae'r pecyn grub-pc yn cael ei uwchraddio. Mae'r fwydlen yma yn eich "
+"caniatáu i ddewis pa ddyfeisiau yr hoffech redeg grub-install arno yn "
+"awtomatig, os o gwbl."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Argymhellir rhedeg grub-install yn awtomatig yn y rhan fwyaf o sefyllfaoedd, "
+"i wneud yn siwr fod y ddelwedd GRUB craidd yn gyson gyda'r modiwlau GRUB a "
+"grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Os nad ydych yn siwr pa ddisg sydd wedi ei benodi fel disg ymgychwyn gan "
+"eich BIOS, mae yn syniad da fel arfer i sefydlu GRUB i bob un."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nodyn: mae'n bosibl sefydlu GRUB i gofnodion ymgychwyn rhaniadau hefyd, a "
+"mae rhai rhaniadau addas yn cael eu cynnig yma. Fodd bynnag, mae hyn yn "
+"gorfodi GRUB i ddefnyddio techneg rhestr flocio, sy'n ei wneud yn llai "
+"dibynadwy, a felly ni argymhellir ei ddefnyddio."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Roedd y llwythwr ymgychwyn GRUB wedi ei osod yn flaenorol i ddisg sydd ddim "
+"yn bresennol bellach, neu fod ei rif unigryw wedi newid am rhyw reswm. Mae'n "
+"bwysig i wneud yn siwr fod y ddelwedd craidd GRUB a osodwyd yn gyson gyda "
+"modiwlau GRUB a grub.cfg. Gwiriwch eto i wneud yn siwr fod GRUB yn "
+"ysgrifennu i'r dyfeisiau ymgychwyn addas."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Methwyd ysgrifennu GRUB i'r ddyfais ymgychwyn - parhau?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Methwyd sefydlu GRUB i'r dyfeisiau canlynol:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ydych am barhau beth bynnag? Os ydych, mae'n bosib na fydd eich cyfrifiadur "
+"yn cychwyn yn gywir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Methwyd ysgrifennu GRUB o'r ddyfais ymgychwyn - ceisio eto?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Mae'n bosib y gallwch sefydlu GRUB i ryw ddyfais arall, ond fe ddylech wirio "
+"fod y system yn gallu ymgychwyn o'r ddyfais honno. Fel arall, i fydd "
+"uwchraddio o GRUB etifeddol yn cael ei ganslo."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Parhau heb sefydlu GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Fe ddewisoch i beidio sefydlu GRUB i unrhyw ddyfeisiau. Os ydych yn parhau, "
+"mae'n bosib na fydd y llwythwr ymgychwyn wedi ei gyflunio'n gywir, a'r tro "
+"nesa fydd y cyfrifiadur hwn yn cychwyn mi fydd yn defnyddio beth bynnag oedd "
+"yn y sector ymgychwyn o'r blaen. Os oes fersiwn cynharach o GRUB 2 yn y "
+"sector ymgychwyn, mae'n bosib na fydd yn gallu llwytho modiwlau na deall y "
+"ffeil gyfluniad presennol."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Os ydych yn defnyddio llwythwr ymgychwyn gwahanol yn barod ac eisiau parhau "
+"i wneud hynny, neu os yw hwn yn amgylchedd arbennig lle nad oes angen "
+"llwythwr ymgychwyn, yna fe allwch barhau beth bynnag. Fel arall, fe ddylech "
+"sefydlu GRUB yn rhywle."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Dileu GRUB 2 o /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Ydych am i holl ffeiliau GRUB 2 cael eu dileu o /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Mi fydd hyn yn golygu na fydd y system yn gallu cychwyn nes i lwythwr "
+"ymgychwyn arall ei sefydlu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Cwblhau y newid i GRUB 2 nawr?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Mae yna ffeiliau o lwythwr ymgychwyn GRUB etifeddol dal i fod ar y system "
+"hwn, ond mae yna hefyd gofnodion ymgychwyn GRUB 2 wedi ei sefydlu ar y "
+"disgiau hyn:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Mae'n edrych yn debyg nad yw GRUB etifeddol yn cael ei ddefnyddio rhagor, a "
+"fe ddylech uwchraddio i'r delweddau GRUB 2 ar y disgiau hyn a cwblhau y "
+"newid i GRUB 2 drwy ddileu yr hen ffeiliau GRUB etifeddol. Os nad ydych yn "
+"uwchraddio'r delweddau GRUB 2, mae'n bosib y byddant yn anghydnaws gyda'r "
+"pecynnau newydd a fe allai hyn atal eich system rhag cychwyn yn gywir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Yn gyffredinol, fe ddylech gwblhau'r newid i GRUB 2 heblaw fod y cofnodion "
+"ymgychwyn hyn wedi eu creu gan sefydliad GRUB 2 gan ryw system weithredu "
+"arall."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Llinell orchymyn Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Mae'r llinell orchymyn Linux canlynol wedi ei dynnu o /etc/default/grub "
+"neu'r paramedr 'kopt' yn ffeil menu.lst GRUB etifeddol. Gwiriwch fod hyn yn "
+"gywir a newidiwch os oes angen. Caniateir i'r linell orchymyn fod yn wag."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Llinell orchymyn ddiofyn Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Defnyddir y llinyn canlynol fel paramedrau Linux ar gyfer y cofnod bwydlen "
+"diofyn ond ddim ar gyfer y modd achub."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Gorfodi gosodiad ychwanegol i'r llwybr cyfrwng symudadwy EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Mae rhai systemau EFI yn wallus ac nid ydynt yn trin llwythwr ymgychwyn "
+"newydd yn gywir. Os ydych chi'n gorfodi gosodiad ychwanegol o GRUB i lwybr "
+"cyfrwng symudadwy EFI, dylai hyn sicrhau y bydd y system hon yn cychwyn "
+"Debian yn gywir er gwaethaf problem o'r fath. Fodd bynnag, efallai y bydd yn "
+"dileu'r gallu i gychwyn unrhyw systemau gweithredu eraill sydd hefyd yn "
+"dibynnu ar y llwybr hwn. Os felly, bydd angen i chi sicrhau bod GRUB wedi'i "
+"ffurfweddu'n llwyddiannus i allu cychwyn unrhyw osodiadau OS eraill yn gywir."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Diweddaru newidynnau NVRAM i gychwyn yn awtomatig i Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"Gall GRUB ffurfweddu newidynnau NVRAM eich platfform fel ei fod yn cychwyn i "
+"Debian yn awtomatig pan gaiff ei droi ymlaen. Fodd bynnag, efallai y "
+"byddai'n well gennych analluogi'r ymddygiad hwn ac osgoi newidiadau i'ch "
+"cyfluniad ymgychwyn. Er enghraifft, os yw'ch newidynnau NVRAM wedi'u gosod "
+"fel bod eich system yn cysylltu â gweinydd PXE bob tro wrth gychwyn, byddai "
+"hyn yn cadw'r ymddygiad hwnnw."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr "Rhedeg os-prober yn awtomatig i ddarganfod a chychwyn OSau eraill?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"Gall GRUB ddefnyddio'r teclyn os-prober i geisio ddarganfod systemau "
+"gweithredu arall ar eich cyfrifiadur a'u ychwanegu yn awtomatig i'r rhestr o "
+"ddewisiadau ymgychwyn."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Os oes nifer o systemau gweithredu wedi eu gosod ar eich cyfrifiadur, mae'n "
+"debygol mai dyma'r dewis i chi. Fodd bynnag, os yw eich cyfrifiadur yn "
+"westeiwr i OSau a osodwyd drwy LVM neu ddyfeisiau disg crai, gall rhedeg os-"
+"prober achosi difrod i'r OSau gwadd yma wrth iddo agor systemau ffeilio i "
+"chwilio am bethau."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "llinell orchymyn kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Mae'r llinell orchymyn kFreeBSD canlynol wedi ei dynnu o /etc/default/grub "
+"neu'r paramedr 'kopt' yn ffeil menu.lst GRUB etifeddol. Gwiriwch fod hyn yn "
+"gywir a newidiwch os oes angen. Caniateir i'r linell orchymyn fod yn wag."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "llinell orchymyn ddiofyn kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Defnyddir y llinyn canlynol fel paramedrau kFreeBSD ar gyfer y cofnod "
+"bwydlen diofyn ond ddim ar gyfer y modd achub."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "Mae'r ffeil /boot/grub/device.map wedi ei ail-greu"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Mae'r ffeil /boot/grub/device.map wedi ei ailsgrifennu i ddefnyddio enwau "
+#~ "dyfeisiau sefydlog. Yn y rhan fwyaf o achosion, fe ddylai hwn leihau'n "
+#~ "sylweddol yr angen i'w newid yn dyfodol, a ni ddylai hyn effeithio ar y "
+#~ "cofnodion bwydlen ymgychwyn a gynhyrchir gan GRUB."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Fodd bynnag, gan fod mwy na un disg yn bresennol yn y system, mae'n bosib "
+#~ "fod y system yn dibynnu ar hen fap dyfais. Gwiriwch os oes unrhyw "
+#~ "gofnodion bwydlen ymgychwyn sydd wedi'i addasu ac yn dibynnu ar rhifo "
+#~ "disg GRUB (hdN), a diweddarwch nhw os oes angen."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Os nad ydych yn deall y neges hwn, neu os nad oes unrhyw gofnodion "
+#~ "bwydlen ymgychwyn wedi'i addasu, fe allwch chi anwybyddu'r neges hwn."
diff --git a/debian/po/da.po b/debian/po/da.po
new file mode 100644
index 0000000..6e20eb1
--- /dev/null
+++ b/debian/po/da.po
@@ -0,0 +1,484 @@
+# Danish translation grub2.
+# Copyright (C) 2017 grub2 & nedenstående oversættere.
+# This file is distributed under the same license as the grub2 package.
+# Joe Hansen <joedalton2@yahoo.dk>, 2010, 2011, 2015.
+# Korrekturlæst Kenneth Nielsen, Keld Jørn Simonsen, Torben Grøn Helligsø.
+#
+# Chain loading -> Chain loading is a method used by computer programs
+# to replace the currently executing program with a new program,
+# using a common data area (a so-called core common area) to pass
+# information from the current program to the new program. It occurs
+# in several areas of computing. Et dansk navn?
+# man kunne måske med nogen rimelighed kalde det for kædeindlæsning, men
+# egentlig er det her jo et af de ord som jeg ikke mener at behøver at
+# oversætte. Dem der har brug for at vide hvad det er, kender kun det
+# engelsk ord og det danske vil måske endda forvirre mere end det vil
+# gøre gavn. I hvert fald, hvis du vil oversætte vil jeg anbefale at
+# sætte chainloade i parentes der hvor du kan. Beholdt uoversat.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-23 11:30+01:00\n"
+"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
+"Language-Team: Danish <debian-l10n-danish@lists.debian.org>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Chainload fra menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Opgraderingsskripterne til GRUB har fundet en GRUB Legacy-opsætning i /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"For at erstatte GRUB-versionen Legacy på dit system, anbefales det at /boot/"
+"grub/menu.lst justeres til at indlæse GRUB 2's opstartsaftryk fra din "
+"eksisterende GRUB Legacy-opsætning. Dette trin kan udføres automatisk nu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Det anbefales, at du accepterer at chainloade GRUB 2 fra menu.lst, og "
+"verificerer at din nye GRUB 2-opsætning virker for dig, før du installerer "
+"den direkte til din MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Uanset din beslutning kan du senere erstatte dit gamle MBR-aftryk med GRUB 2 "
+"ved at foretage den følgende kommando som administrator (root):"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUBs installationsenheder:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Pakken grub-pc bliver opgraderet. Denne menu tillader dig at vælge, hvilke "
+"enheder om nogen, du vil have at grub-install automatisk skal køres for."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Automatisk kørsel af grub-install anbefales i de fleste situationer, for at "
+"forhindre at det installerede GRUB-kerneaftryk kommer ud af synkronisering "
+"med GRUB-moduler eller grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Hvis du er usikker på hvilket drev, der er bestemt som opstartsdrev af din "
+"BIOS, er det ofte en god ide at installere GRUB på dem alle."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Bemærk: Det er også muligt at installere GRUB til partitioners "
+"opstartspunkter, og nogle egnede partitioner tilbydes her. Dette tvinger dog "
+"GRUB til at bruge blokeringslistemekanismen, som gør den mindre pålidelig, "
+"og dette anbefales derfor ikke."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB-opstartsindlæseren blev tidligere installeret til en disk, som ikke "
+"længere er tilgængelig, eller hvis unikke identifikation er blevet ændret. "
+"Det er vigtigt at sikre sig, at det installerede GRUB-kerneaftryk forbliver "
+"i synkronisering med GRUB-moduler og grub-cfg. Kontroller venligst en ekstra "
+"gang så du er sikker på, at GRUB skrives til de relevante opstartsenheder."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Skrivning af GRUB til opstartsenhed fejlede - vil du fortsætte?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Kunne ikke installere GRUB på de følgende enheder:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ønsker du at fortsætte alligevel? Hvis du fortsætter, kan din computer måske "
+"ikke starte korrekt op."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Skrivning af GRUB til opstartsenhed fejlede - forsøg igen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Du kan måske installere GRUB til en anden enhed, selvom du skal tjekke at "
+"dit system kan/vil opstarte fra denne enhed. Ellers vil opgraderingen fra "
+"GRUB Legacy blive afbrudt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Fortsæt uden at installere GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Du har valgt ikke at installere GRUB på nogen enhed. Hvis du fortsætter, vil "
+"opstarteren (boot loader) måske ikke være korrekt konfigureret, og når din "
+"computer starter op næste gang, vil den bruge det tidligere indhold i din "
+"opstartssektor (boot sector). Hvis der er en tidligere version af GRUB 2 i "
+"opstartsektoren, vil den måske ikke være i stand til at indlæse moduler "
+"eller håndtere den aktuelle konfigurationsfil."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Hvis du allerede kører en anden opstarter (boot loader) og ønsker at "
+"fortsætte sådan, eller hvis dette er et specielt miljø, hvor du ikke har "
+"brug for en opstarter, så skal du fortsætte alligevel. Ellers skal du "
+"installere GRUB et eller andet sted."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Fjern GRUB 2 fra /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Ønsker du at alle GRUB 2-filer skal fjernes fra /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Dette vil medføre, at systemet ikke kan opstartes med mindre en anden "
+"opstarter (boot loader) er installeret."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Afslut konvertering til GRUB 2 nu?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Dette system har stadig filer fra GRUB Legacy-opstarteren installeret, men "
+"systemet har nu også GRUB 2 opstartsposter installeret på disse diske:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Det virker sandsynligt at GRUB Legacy ikke længere er i brug, og at du i "
+"steden fir skal opgradere GRUB 2-billederne på disse diske og afslutte "
+"konverteringen til GRUB 2 ved af fjerne ældre GRUB Legacy-filer. Hvis du "
+"ikke opgraderer disse GRUB 2-billeder, så er de måske ikke kompatible med de "
+"nye pakker og får dit system til at holde op med at starte korrekt op."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Du bør generelt afslutte konverteringen til GRUB 2 medmindre disse "
+"opstartsposter blev oprettet af en GRUB 2-installation på et andet "
+"operativsystem."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Kommandolinje til Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Den følgende kommandolinje i Linux blev udtrukket fra /etc/default/grub "
+"eller parameteren `kopt' i GRUB Legacys menu.lst. Verificer venligst at den "
+"er korrekt, og ændre den om nødvendigt. Kommandolinjen må være tom."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Standardkommandolinje i Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Den følgende streng vil blive brugt som Linuxparametre for "
+"standardmenupunktet men ikke for gendannelsestilstanden."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Fremtving ekstra installation til den flytbare mediesti for EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Nogle EFI-baserede systemer er fejlramte og håndterer ikke nye "
+"opstartsindlæsere korrekt. Hvis du fremtvinger en ekstra installation af "
+"GRUB til den flytbare mediesti for EFI, bør dette sikre, at systemet vil "
+"starte Debian korrekt op på trods af et sådant problem. Det kan dog fjerne "
+"muligheden for at starte et andet operativsystem op, som også afhænger af "
+"denne sti. Hvis dette er tilfældet, så skal du sikre dig, at GRUB er "
+"konfigureret succesfuldt for at kunne starte andre operativsystemer op "
+"korrekt."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Opdater NVRAM-variabler til automatisk at starte i Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB kan konfigurere din platforms NVRAM-variabler, så de starter i Debian "
+"automatisk når tændt. Du kan dog foretrække at deaktivere denne opførsel og "
+"undgå ændringer til din opstartskonfiguration. For eksempel hvis dine NVRAM-"
+"variabler er blevet sat sådan op, at dit system kontakter en PXE-server ved "
+"hver opstart, vil dette bevare denne opførsel."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Kommandolinje for kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Den følgende kommandolinje i kFreeBSD blev udtrukket fra /etc/default/grub "
+"eller fra parameteren `kopt' i GRUB Legacys menu.lst. Verificer venligst at "
+"den er korrekt, og ændre den om nødvendigt. Kommandolinjen må være tom."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Standardkommandolinje i kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Den følgende streng vil blive brugt som kFreeBSD-parametre for "
+"standardmenupunktet men ikke for gendannelsestilstanden."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map er blevet gendannet"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Filen /boot/grub/device.map er blevet genskrevet til at bruge stabile "
+#~ "enhedsnavne. I de fleste tilfælde vil dette markant reducere behovet for "
+#~ "at ændre filen fremover, og opstartsmenupunkter oprettet af GRUB vil ikke "
+#~ "blive påvirket."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Da du har mere end en disk i dit sytem, er det dog muligt, at du har en "
+#~ "afhængighed af det gamle enhedskort. Tjek venligst om der er nogle "
+#~ "tilpassede opstartsmenupunkter som afhænger af GRUB's (hdn) "
+#~ "drevnummerering, og opdater dem om nødvendigt."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Hvis du ikke forstår denne besked, eller der ikke er nogen tilpassede "
+#~ "opstartsmenupunkter, kan du ignorere denne besked."
diff --git a/debian/po/de.po b/debian/po/de.po
new file mode 100644
index 0000000..c096496
--- /dev/null
+++ b/debian/po/de.po
@@ -0,0 +1,498 @@
+# Translation of GRUB 2 debconf templates to German
+# Copyright (C) Helge Kreutzmann <debian@helgefjell.de>, 2007-2009, 2017, 2023.
+# Martin Eberhard Schauer <Martin.E.Schauer@gmx.de>,
+# 2010, 2011, 2014.
+# This file is distributed under the same license as the grub2 package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 2.02 2.06-13\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 19:48+0200\n"
+"Last-Translator: Helge Kreutzmann <debian@helgefjell.de>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Aus »menu.lst« laden (Chainload)?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Die Upgrade-Skripte von GRUB haben eine Installation von »GRUB Legacy« in /"
+"boot/grub gefunden."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Um die Legacy-Version von GRUB auf Ihrem System zu ersetzen, wird die "
+"Anpassung von /boot/grub/menu.lst empfohlen, so dass GRUB 2 aus Ihrer "
+"bestehenden GRUB-Legacy-Konfiguration heraus geladen wird. Dieser Schritt "
+"kann jetzt automatisch vollzogen werden."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Es wird empfohlen, dass Sie dem Laden von GRUB 2 aus menu.lst zustimmen und "
+"überprüfen, dass Ihre neue »GRUB 2«-Installation funktioniert, bevor diese "
+"in den MBR (Master Boot Record) geschrieben wird."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Unabhängig von Ihrer Entscheidung können Sie den alten MBR später durch GRUB "
+"2 ersetzen. Geben Sie dazu als »root« den folgenden Befehl ein:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Geräte für die GRUB-Installation:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Für das Paket grub-pc wird gerade ein Upgrade durchgeführt. In diesem Menü "
+"können Sie auswählen, ob und für welche Geräte grub-install automatisch "
+"ausgeführt werden soll."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Für die Mehrzahl der Fälle wird empfohlen, grub-install automatisch laufen "
+"zu lassen. So wird vermieden, dass das installierte GRUB-Image nicht zu den "
+"GRUB-Modulen oder grub.cfg passt."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Wenn Sie nicht sicher sind, welches Gerät das BIOS zum Booten benutzt, ist "
+"es oft eine gute Idee, GRUB auf allen Geräten zu installieren."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Hinweis: Sie können GRUB auch in die Boot-Blöcke von Partitionen schreiben."
+"Hier werden auch einige geeignete Partitionen angeboten. Das zwingt GRUB "
+"allerdings dazu, den Blocklist-Mechanismus zu verwenden. Dieser ist weniger "
+"zuverlässig und wird daher nicht empfohlen."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Der GRUB-Bootloader wurde zuvor auf einem Datenträger, der nicht mehr im "
+"System vorhanden ist oder dessen eindeutige Kennung aus irgendeinem Grund "
+"geändert wurde, installiert. Es ist wichtig, sicherzustellen, dass das "
+"installierte GRUB-Core-Image synchron mit den GRUB-Modulen und grub.cfg "
+"bleibt. Bitte prüfen Sie erneut, um sicherzustellen, dass GRUB auf die "
+"entsprechenden Boot-Geräte geschrieben wird."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUB konnte nicht auf das Boot-Gerät geschrieben werden - fortfahren?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB konnte nicht auf den folgenden Geräten installiert werden:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Wollen Sie trotzdem fortfahren? Falls ja, wird Ihr Rechner vielleicht nicht "
+"problemlos hochfahren."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Das Schreiben von GRUB auf das Boot-Gerät ist fehlgeschlagen. Noch einmal "
+"versuchen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Vielleicht können Sie GRUB auf einem anderen Gerät installieren. Sie sollten "
+"aber prüfen, ob Ihr System von diesem Gerät startet. Sonst wird das Upgrade "
+"von GRUB Legacy abgebrochen."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Fortsetzen, ohne Grub zu installieren?"
+
+# (mes) Seht Ihr einen Unterschied zwischen der alten und der neuen Version?
+# Ich habe jetzt nur das fuzzy rausgenommen.
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Sie haben sich entschieden, GRUB auf kein Gerät zu installieren. Wenn Sie "
+"fortfahren, könnte der Boot-Loader nicht richtig konfiguriert sein. Beim "
+"nächsten Hochfahren dieses Computers wird der Boot-Loader benutzen, was "
+"immer sich vorher im Boot-Sektor befand. Wenn sich schon eine ältere Version "
+"von GRUB 2 im Boot-Sektor befindet, kann sie möglicherweise keine Module "
+"laden oder nicht mehr mit der aktuellen Konfigurationsdatei umgehen."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Falls Sie bereits einen anderen Boot-Loader einsetzen und diesen beibehalten "
+"wollen oder Ihre spezielle Umgebung keinen Boot-Loader erfordert, dann "
+"sollten Sie trotzdem fortfahren. Anderenfalls sollten Sie GRUB irgendwo "
+"installieren."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "GRUB 2 aus /boot/grub entfernen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Wollen Sie alle Daten von GRUB 2 aus /boot/grub entfernen lassen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Wenn kein anderer Boot-Loader installiert ist, kann Ihr System anschließend "
+"nicht mehr booten (hochfahren)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Jetzt die Umstellung auf GRUB 2 abschließen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Auf diesem System sind noch Dateien des GRUB-Legacy-Boot-Loaders "
+"installiert, aber es sind nun auch GRUB-2-Boot-Sektoren auf den folgenden "
+"Datenträgern installiert:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Es sieht so aus, als ob Sie GRUB Legacy nicht mehr verwenden. Daher sollten "
+"Sie stattdessen ein Upgrade der GRUB-2-Images auf diesen Datenträgern "
+"durchführen und die Umstellung auf GRUB 2 abschließen, indem Sie die alten "
+"GRUB-Legacy-Dateien entfernen. Falls Sie das Upgrade für diese GRUB-2-Images "
+"nicht durchführen, könnten diese mit den neuen Paketen nicht kompatibel sein "
+"und dazu führen, dass Ihr System nicht mehr einwandfrei startet."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Grundsätzlich sollten Sie die Umstellung auf GRUB 2 abschließen, es sei "
+"denn, diese GRUB-2-Boot-Sektoren wurden von einem anderen Betriebssystem "
+"installiert."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux-Befehlszeile:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Die folgende Linux-Befehlszeile wurde aus /etc/default/grub oder dem "
+"Parameter »kopt« in der Datei menu.lst von GRUB Legacy extrahiert. Bitte "
+"überprüfen Sie, ob die Befehlszeile korrekt ist und ändern Sie diese, wenn "
+"es notwendig ist. Diese Befehlszeile darf leer sein."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Standard-Befehlszeile für Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Die folgende Zeichenkette wird als Linux-Parameter für den "
+"Standardmenüeintrag, nicht aber für den Rettungsmodus verwandt."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Zusätzliche Installation in den Pfad für EFI-Wechselmedien erzwingen?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Einige EFI-basierte Systeme haben einen Fehler und handhaben neue Bootloader "
+"nicht korrekt. Falls Sie eine zusätzliche Installation von GRUB in den Pfad "
+"für EFI-Wechselmedien erzwingen, sollten Sie gewährleisten, dass das System "
+"Debian trotz dieses Problems korrekt startet. Es besteht jedoch die "
+"Möglichkeit, dass ein anderes von diesem Pfad abhängiges Betriebssystem "
+"nicht mehr starten kann. In diesem Fall müssen Sie sicherstellen, dass GRUB "
+"erfolgreich konfiguriert wurde und Installationen beliebiger anderer "
+"Betriebssystem korrekt starten können."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "NVRAM aktualisieren, um direkt in Debian hineinzustarten?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB kann die Plattformvariablen Ihres NVRAMs so konfigurieren, dass es "
+"direkt beim Einschalten in Debian hineinstartet. Es könnte allerdings sein, "
+"dass Sie es vorziehen, dieses Verhalten zu deaktivieren und Änderungen an "
+"Ihrer Systemstartkonfiguration zu vermeiden. Falls beispielsweise Ihre NVRAM-"
+"Variablen so konfiguriert wurden, dass Ihr System bei jedem Systemstart mit "
+"einem PXE-Server Kontakt aufnimmt, dann würde dies dieses Verhalten "
+"beibehalten."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Automatisch os-prober ausführen, um andere Betriebssysteme zu erkennen und "
+"zu starten?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB kann das Werkzeug os-prober verwenden, um das Erkennen anderer "
+"Betriebssystem auf Ihrem Computer zu versuchen und sie automatisch zu der "
+"Liste der Startoptionen hinzuzufügen."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Falls auf Ihrem Computer mehrere Betriebssystem installiert sind, dann "
+"möchten Sie das wahrscheinlich. Falls Ihr Computer als Betreiber für "
+"Gastbetriebssysteme dient, die mittels LVM oder rohen Plattengeräten "
+"installiert sind, dann kann die Ausführung von os-prober diese "
+"Gastbetriebssysteme beschädigen, da es Dateisysteme einhängt, um nach "
+"bestimmten Sachen zu suchen."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Befehlszeile für kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Die folgende kFreeBSD-Befehlszeile wurde aus /etc/default/grub oder dem "
+"Parameter »kopt« in der Datei menu.lst von GRUB Legacy extrahiert. Bitte "
+"überprüfen Sie, ob diese korrekt ist und passen Sie sie an, wenn das "
+"erforderlich ist. Diese Befehlszeile darf leer sein."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Standard-Befehlszeile für kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Die folgende Zeichenkette wird als kFreeBSD-Parameter für den "
+"Standardmenüeintrag, nicht aber für den Rettungsmodus verwandt."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map wurde neu erstellt."
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Die Datei /boot/grub/device.map wurde umgeschrieben, um stabile "
+#~ "Gerätenamen zu verwenden. In der Mehrzahl der Fälle sollte dies die "
+#~ "Notwendigkeit zukünftiger Änderungen deutlich verringern. Von GRUB "
+#~ "erstellte Boot-Menü-Einträge sollten nicht betroffen sein."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Da sich in diesem System mehrere Festplatten befinden, ist es möglich, "
+#~ "dass das System von der alten »device map« abhängig ist. Bitte überprüfen "
+#~ "Sie, obbenutzerdefinierte Boot-Menü-Einträge mit der (hdn)-"
+#~ "Laufwerkszählung von GRUB vorhanden sind und aktualisieren Sie diese "
+#~ "gegebenenfalls."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Wenn Sie diese Nachricht nicht verstehen oder wenn keine modifizierten "
+#~ "Boot-Menü-Einträge vorhanden sind, können Sie diese Nachricht ignorieren."
diff --git a/debian/po/dz.po b/debian/po/dz.po
new file mode 100644
index 0000000..1540ebf
--- /dev/null
+++ b/debian/po/dz.po
@@ -0,0 +1,460 @@
+# Translation of grub2 debconf templates to Dzongkha
+# Copyright (C) 2010 Dzongkha Localization
+# This file is distributed under the same license as the PACKAGE package.
+# Jurmey Rabgay <jrabgay@dit.gov.bt>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2001-12-31 19:57-0500\n"
+"Last-Translator: Dawa <dpemo@dit.gov.bt>\n"
+"Language-Team: Dzongkha <LL@li.org>\n"
+"Language: dz\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2;plural=(n!=1)\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst ནང་ལས་ ཅེན་ལོཌི་འབད་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB དུས་མà½à½´à½“་ཡིག་ཚུགས་ཚུ་གིས་ /boot/grub ནང་ལུ་ GRUB སྔོན་བཤུལ་གཞི་སྒྲིག་ཅིག་སà¾à¾±à½¼à½“་འཛིན་འབད་ནུག"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"à½à¾±à½¼à½‘་རའི་རིམ་ལུགས་ནང་ལུ་ GRUB གི་སྔོན་བཤུལ་à½à½¼à½“་རིམ་ཚབ་བཙུགས་འབད་ནི་གི་དོན་ལུ་ /boot/grub/menu."
+"lst འདི་ à½à¾±à½¼à½‘་རའི་ཡོད་བཞིན་པའི་སྔོན་བཤུལ་གཞི་སྒྲིག་ནང་ལས་ ཅེན་ལོཌི་ GRUB ༢ ལུ་ བདེ་སྒྲིག་འབད་དགོཔ་སྦེ་"
+"འོས་སྦྱོར་འབད་ནུག༠གཞི་སྒྲིག་འདི་ ཡང་ཅིན་ འཕྲལ་ར་རང་བཞིན་གྱིས་ལཱ་འབད་བà½à½´à½–à¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"à½à¾±à½¼à½‘་ཀྱིས་ menu.lst ནང་ལས་ ཅེན་ལོ་ཌིང་དང་ལེན་འབད་དེ་ GRUB ༢ གཞི་སྒྲིག་གསརཔ་འདི་ MBR "
+"(Master Boot Record) ལུ་à½à½‘་ཀར་གཞི་བཙུགས་མ་འབད་བའི་ཧེ་མ་ གཡོག་བཀོལ་བà½à½´à½–་མི་བà½à½´à½–་བལྟ་དགོ་"
+"པའི་འོས་སྦྱོར་འབད་དེ་ཡོདà¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"à½à¾±à½¼à½‘་ཀྱིས་ག་དེ་སྦེ་ གྲོས་à½à½‚་གཅད་རུང་ ཤུལ་ལས་ MBR གཟུགས་བརྙན་་རྙིངམ་འདི་ འོག་གི་བརྡ་བཀོད་འདི་ རུཊི་སྦེ་"
+"སྤྲོད་à½à½¼à½‚་ལས་ GRUB 2 གིས་ཚབ་བཙུགས་འབད་ཚུགསà¼"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB གཞི་བཙུགས་ à½à½–ས་འཕྲུལ་ཚུ :"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc à½à½´à½˜à¼‹à½¦à¾’ྲིལ་འདི་ ཡར་བསà¾à¾±à½ºà½‘་འབད་ཡོདཔ༠དཀར་ཆག་འདི་གིས་ རང་བཞིན་ གཡོག་བཀོལ་ grub-གཞི་"
+"བཙུགས་ གང་རུང་ཡོད་པ་ཅིན་ à½à½–ས་འཕྲུལ་ སེལ་འà½à½´à¼‹à½ à½–ད་བཅུགཔ་ཨིནà¼"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+" GRUB core གཟུགས་བརྙན་ འདི་ GRUB modulesཡང་ན་ grub.cfg ལས་ སོ་སོ་སྦེ་མི་འགྱོ་ནིའི་དོན་ལུ་ "
+"གནས་སྟངས་མང་ཤོས་ཅིག་ནང་ རང་བཞིན་གྱི་ grub-གཞི་བཙུགས་ གཡོག་བཀོལ་ནི་འདི་ འོས་སྦྱོར་འབད་ཡོདཔ་ཨིན༠"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ག་དེམ་ཅིག་སྦེ་ à½à¾±à½¼à½‘་རའི་BIOS གིས་ ཌའིབ་ག་འདི་ བུཊི་ ཌའིབ་སྦེ་ ངོས་འཛིན་འབད་འབདà½à¼‹à½¨à½²à½“་ན་མ་ཤེས་པ་"
+"ཅིན་ ཆ་མཉམ་ལུ་ GRUB གཞི་བཙུགས་འབད་ནི་འི་à½à½–ས་ལམ་ལེགས་ཤོམ་ཅིག་ཨིནà¼"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"དྲན་འཛིན: GRUB འདི་ བར་བཅད་ བུཊི་ དྲན་à½à½¼à¼‹à½£à½´à¼‹à½¡à½„་ གཞི་བཙུགས་འབད་ཚུགསཔ་ཨིནམ་དང་ འོས་ལྡན་ བར་"
+"བཅད་ལ་ལོ་གཅིག་ནཱ་ལུ་བྱིན་à½à½ºà¼‹à½¡à½¼à½‘པ་ཨིན༠ཨིན་རུང་ འདི་གིས་ GRUB ལུ་ blocklist à½à½–ས་རིག་ལག་ལེ་ན་"
+"འà½à½–་ཅབུག་སྟེ་ བློ་གà½à½‘་མ་ཚུགསཔ་བཟོà½à¼‹à½¨à½²à½“མ་ལས་ འདི་ངོ་སྦྱོར་མི་འབདà¼"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB བུཊི་ མངོན་གསལ་པ་འདི་ ཧེ་མ་ལས་ ཌིཀསི་མེད་མི་ ཡང་ན་ མà½à½´à½“་མོང་མ་ཡིན་པའི་ངོས་འཛིན་པ་འདི་ "
+"དོན་དག་གང་རུང་ལུ་བརྟེན་ བསྒྱུར་བཅོས་སོང་ཡོད་མི་ལུ་གཞི་བཙུགས་འབད་ནུག༠གཞི་བཙུགས་འབད་ཡོད་པའི་ GRUB "
+"core གཟུགས་བརྙན་འདི་ GRUB མོ་ཌུལསི་ དང་ grub.cfg དང་ མཉམ་འབྱུང་སྦེ་སྡོད་བà½à½´à½–་ ངེས་བདེན་བཟོ་"
+"དགོ༠GRUB འདི་ བུཊི་à½à½–ས་འཕྲུལ་ འོས་ལྡན་ལུ་འབྲི་ཡོདཔ་ངེས་བདེན་་སྦེ་ཤེས་ཚུགས་ནིའི་དོལུ་ ལོག་ཞིབ་དཔྱད་"
+"འབད་གནང་à¼"
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr " GRUB བུཊི་ à½à½–ས་འཕྲུལ་ལུ་འབྲི་ནི་ འà½à½´à½¦à¼‹à½¤à½¼à½¢à¼‹à½ à½–ྱུང་ཡོདཔ - འཕྲོ་མà½à½´à½‘་དེ་འབད་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB འདི་ འོག་གི་à½à½–ས་འཕྲུལ་ཚུ་ནང་གཞི་བཙུགས་འབད་མ་ཚུགས་པས:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"ག་དེ་འབད་རུང་ འཕྲོ་མà½à½´à½‘་འབད་ནི་ཨིན་ན? འཕྲོ་མà½à½´à½‘་འབད་བ་ཅིན་ à½à¾±à½¼à½‘་ཀྱི་གློག་རིག་འདི་ལེགས་ཤོམ་སྦེ་འགོ་"
+"བཙུགས་མི་ཚུགསà¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "GRUB གཞི་བཙུགས་འà½à½´à½¦à¼‹à½¤à½¼à½¢à¼‹à½–ྱུང་ཡོདཔ༠- ལོག་འབད་རྩོལ་བསà¾à¾±à½ºà½‘་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"à½à¾±à½¼à½‘་ཀྱིས་ à½à½–ས་འཕྲུལ་གཞན་ཚུ་ནང་ GRUB གཞི་བཙུགས་འབད་ཚུགསཔ་འོང་ ཨིན་རུང་ à½à¾±à½¼à½‘་རའི་རིམ་ལུགས་འདི་ "
+"à½à½–ས་འཕྲུལ་དེ་ལས་བུཊི་འབད་བà½à½´à½–་ག་ཞིབ་དཔྱད་འབད་དགོ༠དེ་མེན་པ་ཅིན་ GRUB སྔོན་བཤུལ་ལས་དུས་མà½à½´à½“་"
+"འབད་མི་དེ་ཆ་མེད་འགྱོ་འོང་à¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB གཞི་བཙུགས་མ་འབད་བར་འཕྲོ་མà½à½´à½‘་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"à½à¾±à½¼à½‘་ཀྱིས་ à½à½–ས་འཕྲུལ་གང་རུང་ནང་ GRUB གཞི་བཙུགས་མ་འབད་ནི་སྦེ་གདམ་à½à¼‹à½–རà¾à¾±à½–ས་ནུག འཕྲོ་མà½à½´à½‘་དེ་འབད་བ་"
+"ཅིན་ བུཊི་མངོན་གསལ་པ་འདི་ ལེགས་ཤོམ་སྦེ་རིམ་སྒྲིག་མི་འབདà½à¼‹à¼‹à½ à½¼à½„་༠དེ་ལས་ à½à¾±à½¼à½‘་ཀྱི་གློག་རིག་འདི་ཤུལ་ལས་"
+"འགོ་བཙུགསཔ་ད་ ཧེ་མ་ལས་བུཊི་ས་à½à½¼à½„ས་ག་ཅི་ཡོད་རུང་ ལག་ལེན་འà½à½–་འོང་༠གལ་སྲིད་ བུཊི་ས་à½à½¼à½„ས་ ནང་ ཧེ་"
+"མའི་à½à½¼à½“་རིམ་ GRUB ༢ འདི་ཡོད་པ་ཅིན་ མོ་ཌུལ་འདི་མངོན་གསལའབད་མི་ཚུགས་ནི་ ཡང་ན་ ད་ལྟོའི་རིམ་སྒྲིག་ཡིག་"
+"སྣོད་འདི་ལེགས་སà¾à¾±à½¼à½„་འà½à½–་མི་ཚུགསཔ་འོང་à¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"à½à¾±à½¼à½‘་ཀྱིས་ ཧེ་མ་ལས་ བུཊི་མངོན་གསལ་འབད་མི་སོར་སོ་ཅིག་གཡོག་བཀོལ་འདོད་ཡོད་པ་ཅིན་ ཡང་ན་ འ་ནི་འདི་ "
+"བུཊི་མངོན་གསལ་འབད་མི་ཅིག་དགོཔ་མེད་པའི་དམིགས་བསལ་གྱི་ས་à½à½¼à½„ས་མེན་པ་ཅིན་ འཕྲོ་མà½à½´à½‘་མ་འབད༠དེ་མེན་པ་"
+"ཅིན་ ག་à½à½ºà¼‹à½ à½–ད་རུང་ GRUB གཞི་བཙུགས་འབད་དགོà¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "/boot/grub ནང་ལས་GRUB 2 རྩ་བསà¾à¾²à½‘་གà½à½„་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "/boot/grub ནང་ལས་ GRUB 2 ཡིག་སྣོད་ཆ་མཉམ་ རྩ་བསà¾à¾²à½‘་གà½à½„་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"འདི་གིས་ བུཊི་མངོན་གསལ་པ་སོ་སོ་གཅིག་གཞི་བཙུགས་མ་འབད་ཚུན་ རིམ་སྒྲིག་འདི་ བུཊི་འབད་མ་བà½à½´à½–་བཟོ་འོང་à¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "ད་ལྟོ་ར་ GRUB ༢ ལུ་གཞི་བསྒྱུར་མཇུག་བསྡུ་ནི་ཨིན་ན?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"རིམ་ལུགས་འདི་ལུ་ གཞི་བཙུགས་འབད་ཡོད་པའི་ GRUB སྔོན་བཤུལ་བུཊི་མངོན་གསལ་འབད་མིའི་ནང་ལས་ཡིག་སྣོད་ཚུ་"
+"འདུག ཨིན་རུང་ ད་ལྟོ་འབདà½à¼‹à½‘་ ཌིཀསི་ཚུ་གུ་ GRUB ༢ བུཊི་དྲན་à½à½¼à¼‹à½‚ཞི་བཙུགས་འབད་དེ་ཡོད:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"GRUB སྤྱོད་ཤུལ་འདི་ ལག་ལེན་འà½à½–་སྟེ་མེདཔ་བཟུམ་ཅིག་ཡོདཔ་དང་ འདི་གི་ཚབ་ལུ་ ཌིཀསི་གུ་ཡོད་མི་ GRUB 2 "
+"གཟུགས་བརྙན་ཚུ་དུས་མà½à½´à½“་བཟོ་ཞིནམ་ལས་ GRUB སྤྱོད་ཤུལ་ཡིག་སྣོད་རྙིངམ་ཚུ་ གཞི་བསྒྱུར་འབད་ནི་མཇུག་བསྡུ༠à½à¾±à½¼à½‘་"
+"ཀྱིས་ GRUB 2 གཟུགས་བརྙན་ཚུ་དུས་མà½à½´à½“་མ་བཟོ་བ་ཅིན་ འདི་ཚུ་ à½à½´à½˜à¼‹à½¦à¾’ྲིལ་གསརཔ་ཚུ་དང་གཅིག་à½à½¢à¼‹à½˜à½à½´à½“་འགྱུར་"
+"ཅན་མི་འོང་ནི་ཨིནམ་དང་ à½à¾±à½¼à½‘་ཀྱི་རིམ་ལུགས་ཚུལ་མà½à½´à½“་སྦེ་ཊི་འབད་ནི་ལས་བཀག་ཆ་འབད་འོང་à¼"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"GRUB 2 གཞི་བཙུགས་ཀྱིས་ བཀོད་སྤྱོད་རིམ་ལུགས་ གཞན་གཅིག་གུ་ བུཊི་དྲན་à½à½¼à¼‹à½ à½‘ི་ཚུ་ གསར་བསà¾à¾²à½´à½“་མ་འབདà½à¼‹"
+"ལས་ GRUB 2 ལུ་ གཞི་བསྒྱུར་འབད་ཚར་དགོà¼"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "ལི་ནགསི་བརྡ་བཀོད་གྲལ་à½à½²à½‚་:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"འོག་གི་ ལི་ནགསི་བརྡ་བཀོད་གྲལà½à½²à½‚་འདི་ from from /etc/default/grub or the `kopt' "
+"parameter in GRUB Legacy's menu.lst. ལས་ ཕྱིར་དོན་འབད་འབདà½à¼‹à½¨à½²à½“༠འདི་ངེས་བདེན་ཨིནམ་"
+"བདེན་སྦྱོར་འབད་ཞིནམ་ལས་ དགོས་མà½à½¼à¼‹à½¡à½¼à½‘་པ་ཅིན་ལེགས་བཅོས་འབད༠བརྡ་བཀོད་གྲལ་à½à½²à½‚་འདི་སྟོངམ་ཨིན་རུང་བà½à½´à½–à¼"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "ལི་ནགསི་སྔོན་སྒྲིག་བརྡ་བཀོད་གྲལ་à½à½²à½‚་:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"འོག་གི་ཡིག་རྒྱུན་འདི་ སྔོན་སྒྲིག་དཀར་ཆག་à½à½¼à¼‹à½–ཀོད་ཀྱི་དོན་ལུ་ ལི་ནགསི་ཚད་འཛིན་སྦེ་ལག་ལེན་འà½à½–་ནི་ཨིན་ དེ་"
+"འབདà½à¼‹à½‘་ སླར་གསོ་à½à½–ས་ལམ་གྱི་དོན་ལུ་མེནà¼"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD བརྡ་བཀོད་གྲལ་à½à½²à½‚་:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"འོག་གི་ kFreeBSD བརྡ་བཀོད་གྲལ་à½à½²à½‚་འདི་ /etc/default/grub or the `kopt' parameter "
+"in GRUB Legacy's menu.lst ལས་ ཕྱིར་འདོན་འབད་འབདà½à¼‹à½¨à½²à½“༠འདི་ངེས་དེན་ཨིནམ་བདེན་སྦྱོར་འབད་"
+"ཞིནམ་ལས་ དགོས་མà½à½¼à¼‹à½¡à½¼à½‘་པ་ཅིན་ ལེགས་བཅོས་འབད༠བརྡ་བཀོད་གྲལ་à½à½²à½‚་འདི་ སྟོངམ་ཨིན་རུང་བà½à½´à½–à¼"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD སྔོན་སྒྲིག་བརྡ་བཀོད་གྲལ་à½à½²à½‚་:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"འོག་གི་ཡིག་རྒྱུན་ཚུ་ སྔོན་སྒྲིག་དཀར་ཆག་à½à½¼à¼‹à½–ཀོད་ཀྱི་དོན་ལུ་ kFreeBSD སྦེ་ལག་ལེན་འà½à½–་འོང་ དེ་འབདà½à½‘་ "
+"སླར་གསོ་à½à½–ས་ལམ་གྱི་དོན་ལུ་ལག་ལེན་མི་འà½à½–à¼"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map འདི་ ལོག་བཟོ་ཡོདཔà¼"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "ཡིག་སྣོད་ /boot/grub/device.map འདི་ རྩ་བརྟན་ à½à½–ས་འཕྲུལ་མིང་ཚུ་ལག་ལེན་འà½à½–་སྦེ་ལོག་འབྲི་"
+#~ "ཡོདཔ་ཨིན༠གནད་དོན་མང་ཤོས་ཅིག་ནང་ འདི་གིས་ མ་འོངས་པའི་ནང་བསྒྱུར་བཅོས་འབད་ནི་མར་ཕབ་འབད་"
+#~ "དགོཔ་་ཨིནམ་དང་ GRUB གིས་ བཟོ་བà½à½¼à½“་འབད་ཡོད་པའི་ བུཊི་དཀར་ཆག་à½à½¼à¼‹à½–ཀོད་ཚུ་ལུ་གནོད་སà¾à¾±à½¼à½“་འབྱུ་ཕཅུག་"
+#~ "ནི་མི་འོང་à¼"
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "ག་དེ་སྦེ་རངུ་ à½à¾±à½¼à½‘་ཀྱི་རིམ་ལུགས་ནང་ ཌིཀསི་གཅིག་ལས་ལྷགཔ་སྦེ་ཡོདཔ་ལས་ à½à¾±à½¼à½‘་ à½à½–ས་འཕྲུ་ས་à½à¾²à¼‹à½¢à¾™à½²à½„མ་"
+#~ "འདི་ལུ་བརྟེན་ཚུགས༠à½à¾±à½¼à½‘་ལུ་ GRUB's (hdN) འདྲེན་འཕྲུལ་ ཨང་བà½à½‚ས་ནིའི་་སྲོལ་སྒྲིག་ བུཊི་དཀར་ཆག་à½à½¼à¼‹"
+#~ "བཀོད་ཚུ་ཡོད་མེད་ཞིབ་དཔྱད་འབད་ཞིནམ་ལས་ དགོས་མà½à½¼à¼‹à½‘ང་བསྟུན་à½à½ºà¼‹ དུས་མà½à½´à½“་བཟོà¼"
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "འཕྲིན་དོན་འདི་ཧ་མ་གོà½à¼‹ ཡང་ན་ à½à¾±à½¼à½‘་ལུ་ སྲོལ་སྒྲིག་དཀར་ཆག་à½à½¼à¼‹à½–ཀོད་གང་རངུ་མེད་པ་ཅིན་ འཕྲིན་དོན་"
+#~ "འདི་སྣང་མེད་སྦེ་བཞགà¼"
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "ཡང་ཅིན་ à½à¾±à½¼à½‘་ར་ལུ་ GRUB ༢ འདི་ MBR ལས་ ནམ་ཨིན་རུང་ མངོན་གསལ་འབད་འདོད་ཡོད་པ་ཅིན་ འོག་"
+#~ "གི་བརྡ་བཀོད་འདི་ རྩ་བའི་à½à½¼à½‚་ལས་འབད་བà½à½´à½–:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "GRUB གཞི་བཙུགས་འà½à½´à½¦à¼‹à½¤à½¼à½¢à¼‹à½–ྱུང་ཡོདཔ༠འཕྲོ་མà½à½´à½‘་འབད་ནི་ཨིན་ན?"
diff --git a/debian/po/el.po b/debian/po/el.po
new file mode 100644
index 0000000..269a812
--- /dev/null
+++ b/debian/po/el.po
@@ -0,0 +1,513 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Panagiotis Georgakopoulos <pankgeorg@gmail.com> 2014
+# Emmanuel Galatoulas <galaxico@quad-nrg.net>, 2010, 2012, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-05-12 13:50+0300\n"
+"Last-Translator: galaxico <galas@tee.gr>\n"
+"Language-Team: debian-l10n-greek@lists.debian.org\n"
+"Language: el\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 22.12.3\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Îα γίνει αλυσιδωτή φόÏτωση από το αÏχείο menu.lst;"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Το Ï€ÏόγÏαμμα αναβάθμισης του GRUB έχει εντοπίσει αÏχεία ÏÏθμισης του GRUB "
+"Legacy στον κατάλογο /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Για να αντικαταστήσετε την έκδοση Legacy του GRUB στο σÏστημά σας, "
+"συνιστάται η Ï€ÏοσαÏμογή του αÏχείου /boot/grub/menu.lst ώστε να γίνεται η "
+"φόÏτωση μιας εκκινήσιμης εικόνας του GRUB 2 μέσα από την υπάÏχουσα "
+"διαμόÏφωση του GRUB Legacy. Το βήμα αυτό μποÏεί να Ï€Ïαγματοποιηθεί Ï„ÏŽÏα "
+"αυτόματα."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Συνιστάται η αποδοχή της αλυσιδωτής φόÏτωσης του GRUB 2 από το αÏχείο menu."
+"lst και η επαλήθευση της λειτουÏγικότητας της νέας ÏÏθμισης του GRUB 2 Ï€Ïιν "
+"αυτό εγγÏαφεί στο MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Όποια κι αν είναι η απόφασή σας, μποÏείτε να αντικαταστήσετε αÏγότεÏα το "
+"Ï€ÏοηγοÏμενο αντίγÏαφο του MBR με τη βοήθεια του GRUB 2, εκτελώντας ως "
+"χÏήστης root την ακόλουθη εντολή: "
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Συσκευές εγκατάστασης του GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Γίνεται αναβάθμιση του πακέτου grub-pc. Αυτό το Î¼ÎµÎ½Î¿Ï ÏƒÎ±Ï‚ επιτÏέπει να "
+"επιλέξετε τις συσκευές, αν θέλετε κάποιες, για τις οποίες θα εκτελεστεί "
+"αυτόματα το grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Η αυτόματη εκτέλεση του grub-install συνιστάται στις πεÏισσότεÏες "
+"πεÏιπτώσεις για την αποτÏοπή του αποσυγχÏÎ¿Î½Î¹ÏƒÎ¼Î¿Ï Ï„Î¿Ï… εγκατεστημμένου "
+"αντιγÏάφου του GRUB από τις υποενότητες του GRUB ή το αÏχείο grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Αν δεν είστε βέβαιοι για το ποια συσκευή έχει οÏιστεί ως συσκευή εκκίνησης "
+"από το BIOS του συστήματός σας, είναι συχνά καλή ιδέα να εγκαταστήσετε το "
+"GRUB σε όλες τις συσκευές."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Σημείωση: είναι δυνατόν να εγκαταστήσετε το GRUB και σε αÏχεία εκκίνησης "
+"κατατμήσεων (boot records) και εδώ Ï€ÏοσφέÏονται μεÏικές τέτοιες κατάλληλες "
+"κατατμήσεις. Όμως, αυτό αναγκάζει το GRUB να χÏησιμοποιήσει τον μηχανισμό "
+"blocklist, κάτι που το καθιστά λιγότεÏο αξιόπιστο, κατά συνέπεια αυτή η "
+"μέθοδος δεν συνίσταται."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Ο φοÏτωτής εκκίνησης GRUB είχε εγκατασταθεί Ï€Ïοηγουμένως σε έναν δίσκο που "
+"δεν είναι πλέον παÏών στο σÏστημα ή που ο μοναδικός κωδικός αναγνώÏισής του "
+"έχει για κάποιο λόγο αλλάξει. Είναι σημαντικό να βεβαιωθείτε ότι το κÏÏιο "
+"εγκατεστημένο αντίγÏαφο του GRUB παÏαμένει συγχÏονισμένο με τιςενότητεςτου "
+"GRUB στο αÏχείο grub.cfg. ΠαÏακαλώ ελέγξτε ξανά για νασιγουÏευτείτε ότι το "
+"GRUB έχει εγγÏαφεί στις κατάλληλες εκκινήσιμες συσκευές."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Η εγκατάσταση του GRUB στην συσκευή εκκίνησης απέτυχε - Συνέχεια;"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Η εγκατάσταση του GRUB απέτυχε στις ακόλουθες συσκευές:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Θέλετε να συνεχίσετε παÏόλα αυτά; Αν ναι, είναι πιθανόν ο υπολογιστής σας να "
+"μην μποÏεί να εκκινήσει κανονικά."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Η εγγÏαφή του GRUB στη συσκευή εκκίνησης απέτυχε - Επανάληψη;"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Είναι πιθανόν να εγκαταστήσετε το GRUB σε κάποια άλλη συσκευή, αλλά θα "
+"Ï€Ïέπει να ελέγξετε ότι το σÏστημά σας μποÏεί να εκκινήσει από αυτή τη "
+"συσκευή. ΔιαφοÏετικά, η αναβάθμιση από την έκδοση Legacy του GRUB θα "
+"ακυÏωθεί."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Συνέχεια χωÏίς εγκατάσταση του GRUB;"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Επιλέξατε να μην εγκαταστήσετε το GRUB σε οποιαδήποτε συσκευή. Αν "
+"συνεχίσετε, το Ï€ÏόγÏαμμα εκκίνησης πιθανόν να μην έχει Ïυθμιστεί σωστά και "
+"στην επανεκκίνηση του υπολογιστή σας θα χÏησιμοποιήσει οτιδήποτε υπήÏχε από "
+"Ï€Ïιν στον τομέα εκκίνησης. Αν υπάÏχει μια Ï€ÏοηγοÏμενη έκδοση του GRUB 2 στον "
+"τομέα εκκίνησης, πιθανόν να μην μποÏεί να φοÏτώσει κάποιες ενότητες αλλά "
+"οÏτενα χειÏιστεί το Ï„Ïέχον αÏχείο Ïυθμίσεων."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Αν χÏησιμοποιείτε ήδη ένα διαφοÏετικό Ï€ÏόγÏαμμα εκκίνησης και θέλετε να "
+"συνεχίσετε με αυτόν ή αν το παÏόν σÏστημα είναι ένα ειδικό πεÏιβάλλον στο "
+"οποίο δεν χÏειάζεστε ένα Ï€ÏόγÏαμμα εκκίνησης, τότε θα Ï€Ïέπει να συνεχίσετε "
+"έτσι κι αλλιώς. ΔιαφοÏετικά, θα Ï€Ïέπει να εγκαταστήσετε κάπου το GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Îα αφαιÏεθεί το GRUB 2 από το /boot/grub;"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+"Θέλετε να αφαιÏεθοÏν όλα τα αÏχεία του GRUB 2 από τον κατάλογο /boot/grub;"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Κάτι τέτοιο θα καταστήσει το σÏστημα μη εκκινήσιμο εκτός αν εγκαταστήσετε "
+"κάποιο άλλο Ï€ÏόγÏαμμα εκκίνησης."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Îα τελειώσει Ï„ÏŽÏα η μετατÏοπή σε GRUB 2;"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Το σÏστημα έχει ακόμα εγκατεστημένα αÏχεία από τον φοÏτωτή εκκίνησης GRUB "
+"Legacy, αλλά έχει Ï„ÏŽÏα επίσης εγκατεστημένα αÏχεία εκκίνησης του GRUB 2 "
+"στους εξής δίσκους:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Φαίνεται πιθανόν ότι το Ï€ÏόγÏαμμα εκκίνησης GRUB Legacy δεν είναι πια σε "
+"χÏήση και ότι θα Ï€Ïέπει αντίθετα να αναβαθμίσετε το GRUB 2 στους παÏακάτω "
+"δίσκους και να ολοκληÏώσετε την μετατÏοπή στο GRUB 2 αφαιÏώντας οποιαδήποτε "
+"παλιότεÏα αÏχεία του GRUB Legacy. Αν δεν αναβαθμίσετε αυτά τα αντίγÏαφα του "
+"GRUB 2, τότε πιθανόν να είναι ασÏμβατα με τα νεότεÏα πακέτα, με αποτέλεσμα "
+"να σταματήσει η κανονική εκκίνηση του συστήματός σας."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Στη γενική πεÏίπτωση θα Ï€Ïέπει να τελειώσετε την μετατÏοπή σε GRUB 2 εκτόςκι "
+"αν αυτά τα αÏχεία εκκίνησης έχουν δημιουÏγηθεί από μια εγκατάσταση του GRUB "
+"2 σε ένα άλλο λειτουÏγικό σÏστημα."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "ΓÏαμμή εντολής Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Η επόμενη γÏαμμή εντολών για Linux έχει εξαχθεί από το αÏχείο /etc/default/"
+"grub ή από την παÏάμετÏο `kopt' στο αÏχείο menu.lst του GRUB Legacy. "
+"ΠαÏακαλώ επιβεβαιώστε ότι είναι οÏθή και Ï„Ïοποποιήστε την αν είναι "
+"απαÏαίτητο. Η γÏαμμή επιτÏέπεται να είναι κενή."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "ΠÏοκαθοÏισμένη γÏαμμή εντολών Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Η ακόλουθη συμβολοσειÏά θα χÏησιμοποιηθεί για τις παÏαμέτÏους Linux στην "
+"Ï€ÏοκαθοÏισμένη είσοδο του Î¼ÎµÎ½Î¿Ï ÎµÎºÎºÎ¯Î½Î·ÏƒÎ·Ï‚ αλλά όχι για την κατάσταση "
+"διάσωσης (recovery mode)."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Îα γίνει εξαναγκασμένη εγκατάσταση στην αποσπώμενη EFI συσκευή;"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"ΜεÏικά συστήματα που βασίζουνται στο EFI είναι ελλειπώς ανεπτυγμένα και δεν "
+"διαχειÏίζονται τα νέα Ï€ÏογÏάμματα εκκίνησης σωστά. Αν εξαναγκάσετε το "
+"σÏστημα να κάνει εγκατάσταση του GRUB στην αποσπώμενη EFI συσκευή, είναι "
+"βέβαιο ότι αυτό το σÏστημα θα δÏναται να εκκινεί το Debian σωστά, ακόμα και "
+"να εμφανιστεί τέτοιο Ï€Ïόβλημα. ΠαÏόλα αυτά, ίσβς αφαιÏέσει τη δυνατότητα να "
+"εκκινείτε οποιοδήποτε άλλο λειτουÏγικό σÏστημα που ίσως εξαÏτάται από αυτή "
+"τη συσκευή. Αν υπάÏχει άλλο λειτουÏγικό σÏστημα, θα χÏειαστεί να σιγουÏέψετε "
+"ότι ο GRUB είναι σωστά Ïυθμισμένος να φοÏτώνει όλα τα άλλα λειτουÏγικά. "
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+"Îα γίνει επικαιÏοποίηση των μεταβλητών NVRAM ώστε να εκκινεί αυτόματα στο"
+" Debian;"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"Το GRUB μποÏεί να Ïυθμίσει τις μεταβλητές NVRAM της πλατφόÏμας σας "
+"έτσι ώστε να εκκινεί αυτόματα στο Debian όταν μπαίνει σε λειτουÏγία. "
+"Όμως, μποÏεί να Ï€Ïοτιμάτε να απενεÏγοποιήσετε αυτή τη συμπεÏιφοÏά "
+"και να αποφÏγετε αλλαγές στις Ïυθμίσεις σας για την εκκίνηση. Για παÏάδειγμα, "
+"αν οι μεταβλητές της NVRAM έχουν οÏιστεί έτσι ώστε το σÏστημά σας να "
+"επικοινωνεί με έναν εξυπηÏετητή PXE σε κάθε εκκίνηση, αυτό θα διατηÏήσει "
+"την συγκεκÏιμένη συμπεÏιφοÏά."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Îα γίνει εκτέλεση αυτόματα του os-prober για την ανίχνευση και εκκίνηση άλλων"
+" ΛΣ;"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"Το GRUB μποÏεί να χÏησιμοποιήσει το εÏγαλείο ανίχνευσης ΛΣ os-prober για να "
+"Ï€Ïοσπαθήσει να ανιχνεÏσει άλλα λειτουÏγικά συστήματα στον υπολογιστή σας και "
+"να τα Ï€Ïοσθέσει αυτόματα στην λίστα του με τις επιλογές εκκίνησης."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Αν ο υπολογιστής σας έχει εγκατεστημένα πολλαπλά λειτουÏγικά συστήματα, τότε "
+"αυτό είναι που πιθανόν επιθυμείτε. Αν, όμως, ο υπολογιστής σας φιλοξενεί ΛΣ "
+"εγκατεστημένα μέσω δίσκων LVM ή συσκευών Ï€Ïαγματικών δίσκων, η εκτέλεση του "
+"os-prober μποÏεί να Ï€Ïοκαλέσει βλάβη σε αυτά τα φιλοξενοÏμενα ΛΣ καθώς για"
+" την "
+"αναζήτηση που εκτελεί Ï€ÏοσαÏτά τα συστήματα αÏχείων."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "ΓÏαμμή εντολών kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Η επόμενη γÏαμμή εντολών του kFreeBSD έχει εξαχθεί από το αÏχείο /etc/"
+"default/grub ή από την παÏάμετÏο `kopt' στο αÏχείο menu.lst του GRUB "
+"Legacy. ΠαÏακαλώ επιβεβαιώστε ότι είναι οÏθή και Ï„Ïοποποιήστε την αν είναι "
+"απαÏαίτητο. Η γÏαμμή επιτÏέπεται να είναι κενή."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "ΠÏοκαθοÏισμένη γÏαμμή εντολών kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Η ακόλουθη συμβολοσειÏά θα χÏησιμοποιηθεί για τις παÏαμέτÏους kFreeBSD στην "
+"Ï€ÏοκαθοÏισμένη είσοδο του Î¼ÎµÎ½Î¿Ï ÎµÎºÎºÎ¯Î½Î·ÏƒÎ·Ï‚ αλλά όχι για την κατάσταση "
+"διάσωσης (recovery mode)."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "Το αÏχείο /boot/grub/device.map έχει αναδημιουÏγηθεί"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Το αÏχείο /boot/grub/device.map έχει ξαναγÏαφεί ώστε να χÏησιμοποιεί "
+#~ "σταθεÏά ονόματα συσκευών. Στις πεÏισσότεÏες πεÏιπτώσεις αυτό θα μειώσει "
+#~ "αισθητά την ανάγκη αλλαγής του στο μέλλον, τα δε στοιχεία του Î¼ÎµÎ½Î¿Ï "
+#~ "εκκίνησης που παÏάγονται από το GRUB δεν θα επηÏεάζονται."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "ΠαÏ' όλα αυτά και Î±Ï†Î¿Ï ÏƒÏ„Î¿ σÏστημά σας υπάÏχουν πεÏισσότεÏοι από έναν "
+#~ "δίσκους,είναι πιθανόν το σÏστημά σας να εξαÏτάται από το παλιότεÏο αÏχείο "
+#~ "απεικόνισης συσκευών device.map. ΠαÏακαλώ ελέγξτε αν υπάÏχουν "
+#~ "οποιεσδήποτε ειδικές είσοδοι στο Î¼ÎµÎ½Î¿Ï ÎµÎºÎºÎ¯Î½Î·ÏƒÎ·Ï‚ που βασίζονται στην "
+#~ "αÏίθμηση των συσκευών από το GRUB (hdN) και ενημεÏώστε τις αν είναι "
+#~ "απαÏαίτητο."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Αν δεν καταλαβαίνετε το παÏόν μήνυμα ή δεν έχετε οποιεσδήποτε ειδικές "
+#~ "εισόδους στο Î¼ÎµÎ½Î¿Ï ÎµÎºÎºÎ¯Î½Î·ÏƒÎ·Ï‚, μποÏείτε να το αγνοήσετε."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Σε οποιαδήποτε πεÏίπτωση όποτε θελήσετε να φοÏτωθεί το GRUB 2 απευθείας "
+#~ "από το MBR μποÏείτε να το κάνετε Ï„Ïέχοντας (ως χÏήστης root) την ακόλουθη "
+#~ "εντολή:" \ No newline at end of file
diff --git a/debian/po/eo.po b/debian/po/eo.po
new file mode 100644
index 0000000..d8bf8ba
--- /dev/null
+++ b/debian/po/eo.po
@@ -0,0 +1,487 @@
+# grub2 po-debconf translation to Esperanto
+# Copyright (C) 2010, 2011, 2014, 2017, 2023 Software in the Public Interest
+# This file is distributed under the same license as the grub2 package.
+# Felipe Castro <fefcas@gmail.com>, 2010, 2011, 2014, 2017, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.02-18\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-05-10 19:17-0300\n"
+"Last-Translator: Felipe Castro <fefcas@gmail.com>\n"
+"Language-Team: Esperanto <debian-l10n-esperanto@lists.debian.org>\n"
+"Language: eo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.4.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Ĉu ĉen-Åargi (chainload) el menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Aktualigaj skriptoj de GRUB detektis agordon de la malaktuala GRUB en /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Por anstataÅ­igi la malaktualan version de GRUB en via sistemo, oni "
+"rekomendas ke /boot/grub/menu.lst estu akomodita por Åargi je ekÅarga bildo "
+"GRUB 2 el via ekzistanta agordo de malaktuala GRUB. Tiu ĉi paÅo povas esti "
+"aÅ­tomate farata nun."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Oni rekomendas ke vi akceptu ĉen-Åargi je GRUB 2 el menu.lst, kaj kontrolu "
+"ĉu via nova agordo de GRUB 2 bone funkcias antaÅ­ ol Äi estu skribata al la "
+"MBR (Mastra EkÅarga Registro)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Kia ajn estu via decido, per GRUB 2 vi povos poste anstataÅ­igi la malnovan "
+"bildon MBR, uzante la jenan komandon kiel root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Aparatoj instalataj de GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"La pako grub-pc estas Äisdatigata. Tiu ĉi menuo ebligas al vi elekti iujn "
+"ajn aparatojn por esti aÅ­tomate instalotaj de grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Lanĉi grub-install aŭtomate estas rekomendinda plej kutime, por eviti ke la "
+"instalita kerna bildo GRUB malsinkroniÄu kun la moduloj GRUB aŭ grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Se vi ne certas pri kiu pelilo estas difinita kiel ekÅarga por via BIOS, "
+"ordinare estas bona ideo instali GRUB por ĉiuj el ili."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Rimarko: eblas instali GRUB ankaŭ al diskpartaj ekÅargaj registroj, kaj "
+"kelkaj taŭgaj diskpartoj estas disponigataj ĉi tie. Tamen, tio devigas ke "
+"GRUB uzu meÄ¥anismon bloklisto, kio igas Äin malpli fidinda, do tio ne estas "
+"rekomendinda afero."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"La ekÅargilo GRUB estis antaÅ­e instalita al disko kiu ne plu ekzistas, "
+"aŭ kies unika identigilo ÅanÄis ial ajn. Estas grave certigi ke la instalita "
+"kerna bildo GRUB teniÄu sinkrona kun la moduloj GRUB kaj grub.cfg. Bonvolu "
+"rekontroli por certigi ke GRUB estas skribota al taÅ­gaj ekÅargaj aparatoj."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Skribado de GRUB al ekÅarga aparato malsukcesis - ĉu daÅ­rigi?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB malsukcesis instali al la jenaj aparatoj:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ĉu vi volas daÅ­rigi iel ajn? Se jes, eble via komputilo ne ekÅargiÄu Äuste."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Skribado de GRUB al ekÅarga aparato malsukcesis - ĉu reprovi?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Vi povas instali GRUB en iu alia aparato, kvankam vi devos kontroli ĉu via "
+"sistemo ekÅargiÄos el tiu aparato. Alimaniere, la aktualigo el malnova GRUB "
+"estos nuligata."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Ĉu daŭrigi sen instali GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Vi elektis ne instali GRUB al iu ajn aparato. Se vi daÅ­rigas, la ekÅargilo "
+"eble ne estos Äuste agordita, kaj kiam tiu ĉi komputilo sekve ekÅaltos, Äi "
+"uzos kion ajn estu antaÅ­e en la ekÅarga sektoro. Se ekzistas pli frua versio "
+"de GRUB 2 en la ekÅarga sektoro, Äi eble ne povos Åargi je moduloj aŭ trakti "
+"la nunan agordo-dosieron."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Se vi jam uzas malsaman ekÅargilon kaj vi volas daÅ­rigi kun tio, aŭ se tio "
+"ĉi estas speciala medio kie vi ne bezonas ekÅargilon, tiam vi devos daÅ­rigi "
+"tiel mem. Alie, vi devos instali GRUB ien ajn."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Ĉu forviÅi GRUB 2 el /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Ĉu vi volas forviÅi ĉiujn dosierojn GRUB 2 el /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Tio ĉi igos la sistemon ne ekÅargebla, krom se alia ekÅargilo estu instalita."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Ĉu finigi konverton al GRUB 2 nun?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Tiu ĉi sistemo ankoraÅ­ havas dosierojn el la malaktuala ekÅargilo GRUB "
+"instalita, sed Äi nun ankaÅ­ havas ekÅargajn registrojn de GRUB 2 instalitaj "
+"en tiuj ĉi diskoj:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Åœajnas ke la malaktuala GRUB ne plu estas uzata, kaj ke vi devos anstataÅ­e "
+"aktualigi al bildoj GRUB 2 en tiuj ĉi diskoj, kaj finigi la konverton al "
+"GRUB 2 forigante malnovajn malaktualajn dosierojn GRUB. Se vi ne aktualigos "
+"tiujn ĉi bildojn GRUB 2, tiel ili povos esti malkongruaj al la novaj pakoj "
+"igante ke via sistemo ĉesu ekÅargi senprobleme."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Vi devos ordinare finigi la konverton al GRUB 2, malkondiĉe ke tiuj ĉi "
+"ekÅarg-registroj estu kreitaj de sistemo kun GRUB 2 instalita, en alia "
+"operaciuma sistemo."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linuksa komand-linio:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La jena linuksa komand-linio estas elprenita el /etc/default/grub aÅ­ el la "
+"parametro 'kopt' en la menu.lst de malaktuala GRUB. Bonvolu kontroli ĉu Äi "
+"estas korekta, kaj modifu Äin laÅ­ neceso. Estas permesate ke la komand-linio "
+"estu malplena."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linuksa implicita komand-linio:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"La jena ĉeno estos uzata kiel linuksajn parametrojn por la ordinara menuero "
+"sed ne por la restariga reÄimo."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Ĉu perforti kroma instalo al la vojo de demetebla datumportilo EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Kelkaj sistemoj surbazitaj je EFI estas problemplenaj kaj ne traktas Äuste "
+"novajn ekÅargilojn. Se vi perfortos kroman instalon de GRUB al la vojo de "
+"demetebla datumportilo EFI, tio povos sekurigi ke tiu ĉi sistemo ekÅargos "
+"Debian perfekte malgraÅ­ tia problemo. Tamen, tio povos mortigi la kapablon "
+"ekÅargi iun ajn alian operaciuman sistemon kiu ankaŭ dependas de tiu vojo. "
+"Tiaokaze, vi devas certigi ke GRUB estas sukcese agordita tiel ke Äi "
+"kapablos ekÅargi iun ajn alian OS-instalon Äuste."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Ĉu Äisdatigi variablojn NVRAM por aÅ­tomate ekÅargi al Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB povas agordi la variablojn NVRAM de via platformo por ke Äi ekÅargu al "
+"Debian aÅ­tomate post ÅaltiÄo. Tamen, eble vi preferos malpermesi tiun ĉi "
+"konduton kaj eviti ÅanÄojn al la ekÅarga agordo. Ekzemple, se viaj variabloj "
+"NVRAM estis agordita por ke via sistemo kontaktu servilon PXE ĉe ĉiu "
+"ekÅargo, ne ÅanÄu ilin por teni la konduton."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr "Ĉu aÅ­tomate lanĉi os-prober por detekti kaj ekÅargi aliajn OS-ojn?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB povas uzi la ilon os-prober por provi detekti aliajn operaciumajn "
+"sistemojn en via komputilo kaj aldoni ilin al Äia listo de ekÅargaj ebloj "
+"aÅ­tomate."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Se via komputilo havas plurajn operaciumajn sistemojn instalitajn, do tio ĉi "
+"probable estas la dezirata konduto. Tamen, se via komputilo estas gastiganto "
+"de OS-oj instalitaj per aparatoj LVM aŭ krudaj diskoj, lanĉo de os-prober "
+"povas difektigi tiujn gastigitajn OS-ojn, ĉar Äi muntas dosiersistemojn por "
+"serĉi aĵojn."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Ordon-linio de kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La jena linuksa komand-linio de kFreeBSD estas elprenita el /etc/default/"
+"grub aÅ­ el la parametro 'kopt' en la menu.lst de malaktuala GRUB. Bonvolu "
+"kontroli ĉu Äi estas korekta, kaj modifu Äin laÅ­ neceso. Estas permesate ke "
+"la komand-linio estu malplena."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Implicita komand-linio de kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"La jena ĉeno estos uzata kiel parametrojn de kFreeBSD por la ordinara "
+"menuero sed ne por la restariga reÄimo."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map estas regenerita"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "La dosiero /boot/grub/device.map estas reskribita por uzi stabilajn "
+#~ "aparat-nomojn. En la plejparto de la situacioj, tio devus multe malpliigi "
+#~ "la bezonon ÅanÄi Äin estonte, kaj ekÅarg-menueroj kreitaj de GRUB ne "
+#~ "devos esti influataj."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Tamen, ĉar vi havas pli ol unu disko en via sistemo, eblas ke la sistemo "
+#~ "dependas de malnova aparat-mapo. Bonvolu kontroli ĉu ekzistas iun "
+#~ "personigitan ekÅarg-menueron, kiu surbaziÄas en disk-numerigo de GRUB "
+#~ "(hdN), kaj Äisdatigu Äin se necese."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Se vi ne komprenas tiun ĉi mesaÄon, aÅ­ se vi havas neniun personigitan "
+#~ "ekÅargan menueron, vi povas preteratenti ĉi tiun mesaÄon."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Ĉiukondiĉe, kiam vi volos ke GRUB 2 estu rekte Åargata el MBR, vi povos "
+#~ "fari tion per lanĉado (kie root) de la jena komando:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "La instalado de GRUB malsukcesis. Ĉu daŭrigi?"
diff --git a/debian/po/es.po b/debian/po/es.po
new file mode 100644
index 0000000..0f910ef
--- /dev/null
+++ b/debian/po/es.po
@@ -0,0 +1,561 @@
+# grub2 po-debconf translation to Spanish
+# Copyright (C) 2007, 2009, 2010, 2011 Software in the Public Interest
+# This file is distributed under the same license as the grub2 package.
+#
+# Changes:
+# - Initial translation
+# Maria Germana Oliveira Blazetic<germanaoliveirab@gmail.com>, 2007
+#
+# - Updates
+# Gary Ariel Sandi Vigabriel <gary.gsv@gmail.com>, 2009
+# Francisco Javier Cuadrado <fcocuadrado@gmail.com>, 2009, 2010, 2011
+# Manuel "Venturi" Porras Peralta <venturi@openmailbox.org>, 2014, 2017
+#
+# - Revisions
+# Innocent De Marchi <tangram.peces@gmail.com>, 2010
+#
+# Traductores, si no conocen el formato PO, merece la pena leer la
+# documentación de gettext, especialmente las secciones dedicadas a este
+# formato, por ejemplo ejecutando:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Equipo de traducción al español, por favor lean antes de traducir
+# los siguientes documentos:
+#
+# - El proyecto de traducción de Debian al español
+# http://www.debian.org/intl/spanish/
+# especialmente las notas y normas de traducción en
+# http://www.debian.org/intl/spanish/notas
+#
+# - La guía de traducción de po's de debconf:
+# /usr/share/doc/po-debconf/README-trans
+# o http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 1.99-5\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-28 17:07+0100\n"
+"Last-Translator: Manuel \"Venturi\" Porras Peralta <venturi@openmailbox."
+"org>\n"
+"Language-Team: Español; Castellano <debian-l10n-spanish@lists.debian.org>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.8.11\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "¿Desea cargar secuencialmente desde el fichero «menu.lst»?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Los ficheros de órdenes han detectado durante la actualización una "
+"configuración heredada de una versión anterior de GRUB en «/boot/grub»."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Con el fin de reemplazar la versión anterior de GRUB en el sistema, se "
+"recomienda configurar «/boot/grub/menu.lst» para que cargue GRUB 2 a partir "
+"de la configuración heredada de GRUB. Este paso se puede hacer de forma "
+"automática."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Se recomienda que acepte cargarlo secuencialmente desde el fichero «menu."
+"lst» y que compruebe el buen funcionamiento del nuevo GRUB 2, antes de "
+"instalarlo en el MBR («Master Boot Record»)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Sea cual sea su decisión, puede reemplazar más tarde la imagen del MBR "
+"anterior con GRUB 2 ejecutando como administrador («root») la orden "
+"siguiente:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Dispositivos donde puede instalar GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Se está actualizando el paquete grub-pc. Si lo desea, este menú le permite "
+"escoger en qué dispositivos quiere ejecutar automáticamente grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Se recomienda ejecutar automáticamente grub-install en la mayoría de las "
+"situaciones, para evitar que la imagen del núcleo de GRUB instalada no esté "
+"sincronizada con los módulos GRUB o con el fichero «grub.cfg»."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Si no está seguro cuál es la unidad de inicio de la BIOS, a menudo es una "
+"buena idea instalar GRUB en todas ellas."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: también es posible instalar GRUB en los registros de inicio de "
+"particiones, aquí se ofrecen algunas particiones apropiadas. Sin embargo, "
+"esto obliga a GRUB a utilizar el mecanismo de la lista de bloqueo, que lo "
+"hace menos fiable, y por tanto no es recomendable."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"El gestor de inicio GRUB se instaló previamente en un disco que ya no está "
+"presente o cuyo identificador único ha cambiado por alguna razón. Es "
+"importante asegurarse de que la imagen del núcleo de GRUB instalada se "
+"mantiene sincronizada con los módulos de GRUB y el fichero «grub.cfg». "
+"Asegúrese que GRUB se instala en los dispositivos de inicio adecuados."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+"La instalación de GRUB en el dispositivo de inicio ha fallado, ¿desea "
+"continuar?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "No se pudo instalar GRUB en los siguientes dispositivos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"¿Desea continuar de todos modos? Si lo hace, puede que su equipo no se "
+"inicie apropiadamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"La instalación de GRUB en el dispositivo de inicio ha fallado, ¿desea "
+"intentarlo de nuevo?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Puede instalar GRUB en otro dispositivo, aunque debería comprobar que su "
+"sistema podrá iniciar desde ese dispositivo. En caso contrario, se cancelará "
+"la actualización de la versión anterior de GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "¿Desea continuar sin instalar GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Ha escogido no instalar GRUB en ningún dispositivo. Si continúa, puede que "
+"el cargador de inicio no se configure correctamente, y cuando este equipo se "
+"vuelva a iniciar se utilizará lo que hubiera anteriormente en el sector de "
+"inicio. Si hay una versión previa de GRUB 2 en el sector de inicio, puede "
+"que sea imposible cargar los módulos o manejar el fichero de configuración "
+"actual."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Si está ejecutando un cargador de inicio diferente y quiere seguir "
+"haciéndolo o si es un entorno especial en el que no necesita un cargador de "
+"inicio, entonces debería continuar. De otro modo, debería instalar GRUB en "
+"otra ubicación."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "¿Desea eliminar GRUB 2 de «/boot/grub»?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "¿Desea eliminar todos los ficheros de GRUB 2 de «/boot/grub»?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Esto hará que el sistema no inicie a menos que otro gestor de inicio esté "
+"instalado."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "¿Desea terminar la conversión a GRUB 2 ahora?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Este sistema todavía tiene ficheros del cargador de inicio de la versión "
+"anterior de GRUB instalados, pero ahora también tiene registros de inicio de "
+"GRUB 2 instalados en estos discos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Parece que la versión anterior de GRUB ya no se utiliza, por lo que usted "
+"debería actualizar las imágenes de GRUB 2 en estos discos y terminar la "
+"conversión a GRUB 2 borrando los ficheros de la versión anterior de GRUB. Si "
+"no actualiza estas imágenes de GRUB 2, puede que sean incompatibles con los "
+"nuevos paquetes y que provoquen que su sistema no inicie correctamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Debería terminar la conversión a GRUB 2 a menos que estos registros de "
+"inicio los crease una instalación de GRUB 2 en algún otro sistema operativo."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Línea de órdenes de Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La siguiente línea de órdenes de Linux se extrajo del fichero «/etc/default/"
+"grub» o del parámetro «kopt» en el fichero «menu.lst» de la versión anterior "
+"de GRUB. Compruebe que es correcta y modifíquela si es necesario. La línea "
+"de órdenes se puede dejar en blanco."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Línea de órdenes predeterminada de Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"La siguiente cadena se utilizará como parámetros de Linux para la entrada "
+"predeterminada del menú pero no para el modo de recuperación."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "¿Desea forzar la instalación extra a la ruta del medio extraíble EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Algunos sistemas basados en EFI son defectuosos y no manejan los nuevos "
+"cargadores de inicio correctamente. Si fuerza la instalación extra de GRUB "
+"en la ruta del medio extraíble EFI, debería asegurarse de que este sistema "
+"iniciará Debian correctamente a pesar de semejante problema. Sin embargo, "
+"esto puede eliminar la capacidad de iniciar cualquier otro sistema operativo "
+"que dependa de esta ruta. Si fuera así, necesitará asegurarse que GRUB se ha "
+"configurado correctamente para ser capaz de iniciar sin problemas cualquier "
+"otro sistema operativo instalado."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+"¿Desea actualizar las variables NVRAM para que se carguen automáticamente en "
+"Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB puede configurar las variables NVRAM de su plataforma para que se "
+"carguen automáticamente en Debian cuando se enciende. Aún así, puede "
+"preferir desactivar este comportamiento y no realizar cambios a su "
+"configuración de arranque. Por ejemplo, si las variables NVRAM se han "
+"configurado de forma que su sistema contacta con un servidor PXE en cada "
+"arranque, esto conservaría ese comportamiento."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Línea de órdenes de kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La siguiente línea de órdenes de kFreeBSD se extrajo del fichero «/etc/"
+"default/grub» o del parámetro «kopt» en el fichero «menu.lst» de la versión "
+"anterior de GRUB. Compruebe que es correcta y modifíquela si es necesario. "
+"La línea de órdenes se puede dejar en blanco."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Línea de órdenes predeterminada de kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"La siguiente cadena se utilizará como parámetros de kFreeBSD para la entrada "
+"predeterminada del menú pero no para el modo de recuperación."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "Se ha regenerado el fichero «/boot/grub/device.map»"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "El fichero «/boot/grub/device.map» se ha rescrito para utilizar los "
+#~ "nombres de dispositivos estables. En la mayoría de los casos, esto "
+#~ "debería reducir significativamente la necesidad de cambiarlo en el "
+#~ "futuro, y las entradas del menú que generó GRUB no se verán afectadas."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Sin embargo, ya que hay más de un disco en el sistema, es posible que el "
+#~ "sistema dependa de un mapa de dispositivos antiguo. Compruebe si tiene "
+#~ "entradas personalizadas en el menú de inicio que dependan de la "
+#~ "numeración de los dispositivos de GRUB (hdN) y actualícela si es "
+#~ "necesario."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Puede ignorar este mensaje si no lo entiende o si no tiene entradas "
+#~ "personalizadas en el menú de inicio."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "En cualquier caso, cuando quiera que GRUB 2 se cargue directamente desde "
+#~ "el MBR, puede hacerlo ejecutando (como usuario «root») la siguiente orden:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "La instalación de GRUB ha fallado. ¿Desea continuar?"
+
+#~ msgid "GRUB 1.95 numbering scheme transition"
+#~ msgstr "Esquema de transición numérica de GRUB 1.95"
+
+#~ msgid ""
+#~ "As of version 1.95, GRUB 2 has changed its numbering scheme. Partitions "
+#~ "are now counted starting from 1 rather than 0. This is to make it "
+#~ "consistent with device names of Linux and the other kernels used in "
+#~ "Debian. For example, when using Linux as the kernel, \"(hd0,1)\" refers "
+#~ "to the same partition as the /dev/sda1 device node."
+#~ msgstr ""
+#~ "GRUB 2 ha cambiado el esquema de numeración, como en la versión 1.95. "
+#~ "Ahora las particiones comienzan en el número 1 en vez de en el número 0. "
+#~ "Esto sirve para hacerlo consistente con los nombres de dispositivos de "
+#~ "Linux y otros núcleos que se usan en Debian. Por ejemplo, cuando se usa "
+#~ "Linux como núcleo, «(hd0, 1)» se refiere a la misma partición que el "
+#~ "dispositivo «/dev/sda1»."
+
+#~ msgid ""
+#~ "Because of this, there's a chance your system becomes unbootable if "
+#~ "update-grub(8) is run before GRUB is updated, generating a grub.cfg file "
+#~ "that your installed GRUB won't yet be able to parse correctly. To ensure "
+#~ "your system will be able to boot, you have to:"
+#~ msgstr ""
+#~ "Por este motivo, existe la posibilidad de que su sistema no sea capaz de "
+#~ "arrancar si se ejecuta update-grub(8) antes de actualizar GRUB, ya que se "
+#~ "generaría un archivo «grub.cfg» que la versión instalada de GRUB no "
+#~ "podría leer correctamente. Para asegurarse de que el sistema arrancará, "
+#~ "debe:"
+
+#~ msgid ""
+#~ " - Reinstall GRUB (typically, by running grub-install).\n"
+#~ " - Rerun update-grub to generate a new grub.cfg."
+#~ msgstr ""
+#~ " - Reinstalar GRUB (normalmente, ejecutando grub-install).\n"
+#~ "- Volver a ejecutar update-grub para generar un nuevo archivo «grub.cfg»."
diff --git a/debian/po/eu.po b/debian/po/eu.po
new file mode 100644
index 0000000..0b6763f
--- /dev/null
+++ b/debian/po/eu.po
@@ -0,0 +1,474 @@
+# Basque translation for grub2
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Piarres Beobide <pi@beobide.net>, 2008.
+# Iñaki Larrañaga Murgoitio <dooteo@zundan.com>, 2008, 2009, 2010, 2011, 2014, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2_2.02~beta2-18\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-20 15:48+0100\n"
+"Last-Translator: Iñaki Larrañaga Murgoitio <dooteo@zundan.com>\n"
+"Language-Team: Basque <debian-l10n-basque@lists.debian.org>\n"
+"Language: eu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.5\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Kargatu menu.lst fitxategitik?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB eguneratzeko script-ek GRUB zahar baten konfigurazioa aurkitu dute /"
+"boot/grub-en."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Sistemako GRUB zaharraren bertsioa behar bezala ordezkatzeko, gomendagarria "
+"da /boot/grub/menu.lst doitzea GRUB 2 dagoeneko instalatuta duzun GRUB "
+"zaharraren bidez kargatzeko. Urrats hau automatikoki egin daiteke orain."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Gomendagarria da GRUB 2 menu.lst bidez kargatzea onartzea, eta GRUB 2-ren "
+"konfigurazioak zure beharrak betetzen dituela egiaztatzea MBRan (Master Boot "
+"Record) idatzi aurretik."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Berdin dio zer erabakitzen duzun, MBRren irudi zaharra GRUB 2rekin ordeztu "
+"dezakezu supererabiltzaile (root) gisa honako komandoa exekutatuz:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB instalatzeko gailuak:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc paketea eguneratzen ari da. Menu honek zer gailuentzako automatikoki "
+"grub-install exekutatzea nahi duzun hautatzea (hautatzen baduzu) uzten dizu."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Egoera gehienetan grub-install automatikoki exekutatzea gomendatzen da, "
+"instalatutako GRUBaren bihotzaren irudia GRUBaren modulu edo grub.cfg "
+"fitxategiarekin sinkronizatzetik kanpo gelditzea saihesteko."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ez badakizu BIOSak zer gailu izendatuta daukan abioko gailu gisa, burutazio "
+"ona izan ohi da GRUB guztietan instalatzea."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Oharra: GRUB, partizio bateko abioko erregistroan instala daiteke baita ere, "
+"hori dela eta, partizio egoki batzuk eskaintzen dira hemen. Hala ere, honek "
+"GRUBek bloke-zerrenden mekanismoa erabiltzera derrigortzen du, ondorioz "
+"fidagarritasuna jaitsiz, eta gauzak horrela ez da bat ere gomendagarria."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Lehenago GRUB abioko kargatzailea agertzen ez den disko batean instalatu "
+"zen, edo edozer arrazoirengatik identifikatzaile esklusiboa aldatuta dauka. "
+"Garrantzitsua da instalatutako GRUBaren bihotzaren irudia sinkronizatuta "
+"egotea GRUBaren modulu eta grub.cfg fitxategiarekin. Egiaztatu ezazu berriro "
+"GRUB abioko gailu egokian idatzi dela."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Huts egin du GRUB abioko gailuan idaztean - jarraitu?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUBek huts egin du honako gailuetan instalatzean:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Jarraitzea nahi duzu dena den? Jarraituz gero, baliteke ordenagailua ongi ez "
+"abiaraztea."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Huts egin du GRUB abioko gailuan idaztean - saiatu berriro?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"GRUB beste gailu batean instalatzeko aukera duzu, hala ere, sistema beste "
+"gailu horretatik abiatzeko ahalmena duela egiaztatu behar duzu. Bestela, "
+"'GRUB Legacy' eguneratzea bertan behera utz daiteke."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Jarraitu GRUB instalatu gabe?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"GRUB inolako gailuetan ez instalatzea aukeratu duzu. Jarraitzen baduzu, "
+"baliteke abioko kargatzailea ongi konfiguratuta ez egotea, eta abioko "
+"sektorean aurretik zegoena erabiliko da ordenagailua hurrengo batean "
+"abiatzean. Abioko sektorean GRUB 2ren aurreko bertsio bat egonez gero, agian "
+"ezin izango du moduluak kargatu edo uneko konfigurazioko fitxategia kudeatu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Unean bestelako abioko kargatzaile bat erabiltzean ari bazara, eta horrela "
+"jarraitzea nahi baduzu, edo hau abioko kargatzailearen beharrik ez duen "
+"ingurune berezi bat bada, aurrera jarrai dezakezu. Bestela, GRUB nonbaiten "
+"instalatu beharko zenuke."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Kendu 'GRUB 2' /boot/grub direktoriotik?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Nahi duzu GRUB 2ren fitxategi guztiak /boot/grub-etik kentzea?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Honek sistema ezin abiaraztea eragingo du bestelako abioko kargatzaile bat "
+"instalatzen ez bada."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Amaitu GRUB 2-rako bihurketa orain?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Sistemak oraindik 'GRUB Legacy' abioko kargatzailearen fitxategiak ditu "
+"oraindik, baina orain GRUB 2 bertsioko abioko erregistroak ere baditu honako "
+"diskoetan:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Badirudi 'GRUB Legacy' ez denez aurrerantzean erabiliko, disko hauetako GRUB "
+"2 bertsioko irudiak eguneratu eta 'GRUB Legacy'-ko fitxategiak kenduz GRUB 2-"
+"ren eguneraketa amaitu beharko zenuke. GRUB 2-ko irudi hauek ez badituzu "
+"eguneratzen, pakete berriekin ez dira bateragarriak izango eta sistema ongi "
+"abiatzea galaraz dezake."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"GRUB 2-rako bihurketa amaitu beharko zenuke, abioko erregistro hauek beste "
+"sistema eragile batzuetako GRUB 2 bertsioaren instalazioan ez badira sortuak "
+"izan."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux-eko komando-lerroa:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Linux-eko komando-lerro hau /etc/default/grub edo GRUB zaharraren menu.lst "
+"fitxategiko 'kopt' parametrotik atera da. Egiaztatu zuzena dela, eta "
+"eraldatu behar izanez gero. Komando-lerroa hutsik egotea baimenduta dago."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux-eko komando-lerro lehenetsia:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Honako katea menuko sarrera lehenetsiaren Linux-eko parametro gisa erabiliko "
+"da, baina ez berreskuratzeko moduan."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Behartu instalazio gehigarria EFI euskarri aldagarriaren bide-izenean?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"EFIn oinarritutako sistema batzuk akastunak dira, eta ez dituzte abioko "
+"kargatzaile berriak ongi kudeatzen. EFI euskarri aldagarriaren bide-izenean "
+"GRUBen instalazio gehigarria behartzen baduzu, ziurtatu beharko luke sistema "
+"honek Debian ongi abiatuko duela arazo horrez gain. Hala ere, honek bide-"
+"izen honen mende dauden beste edozer sistema eragile abiatzeko gaitasuna ken "
+"dezake. Horrela bada, ziurtatu zaitez GRUB ongi konfiguratuta dagoela beste "
+"edozer SE-ren instalazioak ongi abiatzeko."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Eguneratu NVRAM-eko aldagaiak automatikoki Debian abiarazteko?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB-ek ordenagailuaren NVRAM-eko aldagaiak konfigura ditzake piztean Debian "
+"batera automatikoki abiarazteko. Hala ere, portaera hau desgaitzea nahi izan "
+"dezakezu, eta abioaren konfigurazioaren aldaketak saihestu. Adibidez, NVRAM-"
+"eko aldagaiak konfiguratu egin badira abio bakoitzean sistemak PXE "
+"zerbitzari batekin konektatzeko, honek portaera hori mantenduko luke."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "KFreeBSD-ko komando-lerroa:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"KFreeBSD-ko komando-lerro hau /etc/default/grub edo GRUB zaharraren menu.lst "
+"fitxategiko 'kopt' parametrotik atera da. Egiaztatu zuzena dela, eta "
+"eraldatu behar izanez gero. Komando-lerroa hutsik egotea baimenduta dago."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "KFreeBSD-ko komando-lerro lehenetsia:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Honako katea menuko sarrera lehenetsiaren KFreeBSD-ko parametro gisa "
+"erabiliko da, baina ez berreskuratzeko moduan."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map berriro sortu da"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "/boot/grub/device.map fitxategia berriro idatzi da gailuen izen "
+#~ "egonkorrak erabiltzeko. Gehienetan, etorkizunean hau aldatzeko beharra "
+#~ "asko murriztu beharko luke, eta GRUBek sortutako menuko sarrerei ez die "
+#~ "eragingo."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Hala ere, sisteman disko bat baino gehiago dagoenez, baliteke sistema "
+#~ "gailuen mapa zaharrean mende egotea. Egiaztatu ezazu GRUBen unitateko "
+#~ "zenbaketan oinarrituta abioaren menuko sarrera pertsonalizaturen bat "
+#~ "duzun edo ez, eta egunera itzazu beharrezkoa izanez gero."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Mezu hau ez baduzu ulertzen, edo abioaren menuko sarrera "
+#~ "pertsonalizaturik ez baduzu, ezikusi egin diezaiokezu mezu honi."
diff --git a/debian/po/fa.po b/debian/po/fa.po
new file mode 100644
index 0000000..f836c01
--- /dev/null
+++ b/debian/po/fa.po
@@ -0,0 +1,460 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: fa\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: \n"
+"Last-Translator: Behrad Eslamifar <behrad_es@yahoo.com>\n"
+"Language-Team: debian-l10n-persian <debian-l10n-persian@lists.debian.org>\n"
+"Language: fa\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Persian\n"
+"X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "بارگزاری به صورت Chainload از menu.lst؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"اسکریپت ارتقاء GRUB, نسخه قدیمی GRUB‌ نصب شده در /boot/grub را پیدا کرده است."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"برای جایگزینی نسخه قدیمی GRUB در سیستم شما، پیشنهاد می‌شود /boot/grub/menu."
+"lst تنظیم گردد تا یک تصویر بوت‌ GRUB 2 از چینش قدیمی GRUB کنونی بارگذاری "
+"شود . اکنون این مرحله به صورت خودکار انجام می شود."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"توصیه می‌شود که chainloading گراب۲ از menu.lst را بپذیرید، و بازبینی کنید که "
+"چینش جدید GRUB 2 قبل از اینکه بر روی MBR (Master Boot Record) نوشته شود کار "
+"می‌کند."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"تصمیم شما هر Ú†Ù‡ باشد، می‌توانید بعداً تصویر قدیم MBR را با GRUB 2 با Ùرمان زیر "
+"توسط کاربر ریشه جایگزین کنید:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "دستگاه‌های نصب گراب:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"بستهٔ grub-pc در حال ارتقاء است. این منو به شما اجازه می‌دهد که هر یک از "
+"دستگاه‌ها را، در صورت وجود، که مایلید grub-install به صورت خودکار برایش اجرا "
+"گردد را انتخاب کنید."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"اجرای خودکار grub-install در بیشتر مواقع، برای جلوگیری خارج‌شدن هستهٔ تصویر "
+"گراب از sync با ماژولهای گراب یا grub.cfg توصیه‌شده است."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"اگر مطمئن نیستید کدام درایو به عنوان درایو بوت توسط BIOS تعیین شده است، اغلب "
+"ایدهٔ خوبی است که گراب را بر روی همهٔ آنها نصب کنید."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"توجه: امکان دارد که گراب را در رکوردهای بوت پارتیشن نیز نصب کنید، و برخی از "
+"پارتیشن‌های مناسب نیز اینجا پیشنهاد شده است. اگرچه، این گراب را مجبور می‌کند "
+"Ú©Ù‡ از مکانیزم blocklist استÙاده کند Ú©Ù‡ قابل اطمینان بودن آنرا کاهش می‌دهد Ùˆ "
+"بنابراین توصیه نمی‌گردد."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"بارگذار بوت گراب قبلاً در دیسکی نصب شده است که دیگر در دسترس نیست، یا unique "
+"identifier آن بنا به دلیلی تغییر کرده است. مهم است که اطمینان حاصل کنید که "
+"نصویر هستهٔ گراب نصب شده در sync با ماژول‌های گراب Ùˆ grub.cfg باقی بماند. لطÙاً "
+"دوباره بررسی کنید تا مطمئن گردید که گراب در دستگاه‌های بوت مناسب نوشته شده "
+"است."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "نصب GRUB روی ابزار بوت با شکست مواجه شد - ادامه می‌دهید؟"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB نتوانست که تجهیزات مورد نظر را نصب کند."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"آیا شما می‌خواهید در هر حال ادامه دهید ؟ اگر ادامه دهید، ممکن است که کامپیوتر "
+"شما به طور مناسب باید بالا نیاید."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "نصب GRUB روی دستگاه بوت با شکست مواجه شد - دوباره امتحان می‌کنید؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"شما ممکن است قادر باشید که GRUB را بر روی بعضی از ابزارهای دیگر نیز نصب "
+"کنید ، هرچند که شما باید چک کنید که سیستم شما قادر به راه‌اندازی شدن با آن "
+"ابزار هست یا خیر. وگرنه ، ارتقا گراب قدیمی متوق٠خواهد شد."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "آیا بدون نصب کردن GRUB ، ادامه می دهید ؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"شما نصب GRUB را برای هیچ ابزاری انتخاب نکرده‌اید. اگر ادامه دهید، ممکن است که "
+"راه‌انداز به درستی تنظیم نشده باشد، و هنگام بالا آمدن بعدی این کامپیوتر، از "
+"آن Ú†Ù‡ Ú©Ù‡ قبلاً بر روی بوت سکتور بوده است استÙاده می‌کند. اگر نسخهٔ قدیمی‌تری از "
+"گراب۲ بر روی بوت سکتور وجود دارد، ممکن است که قادر نباشد ماژول‌ها را بارگذاری "
+"کند Ùˆ یا پیکربندی کنونی Ùایل را به کار بندد."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"اگر شما از راه‌انداز بوت دیگری استÙاده می‌کنید Ùˆ می‌خواهید Ú©Ù‡ با همان ادامه "
+"دهید، یا اگر اینجا یک محیط خاص است که شما به راه‌انداز بوت نیاز ندارید، پس "
+"می‌بایست به هر ترتیب ادامه دهید. در غیر این‌صورت، باید GRUB را در جایی نصب "
+"کنید."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "GRUB 2 از /boot/grub برداشته شود؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "آیا می‌خواهید همهٔ Ùایل‌های GRUB 2 از /boot/grub برداشته شود؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"این باعث غیر قابل بوت‌شدن سیستم می‌شود مگر آنکه بارگذار بوت دیگری نصب است."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "ارتباط با GRUB۲ اکنون پایان یابد؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"این سیستم هنوز Ùایل هایی مربوط به GRUB قدیمی را به صورت نصب شده دارد ØŒ اما "
+"اکنون بوت رکورد های GRUB2 بر روی این دیسک ها نصب شده است :"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"به نظر می‌آید Ú©Ù‡ احتمالاً GRUB قدیمی دیگر در استÙاده نیست، Ùˆ شما می‌بایست "
+"تصاویر GRUB2 را بر روی این دیسک‌ها ارتقاء دهید Ùˆ با پاک کردن Ùایل‌های گراب "
+"قدیمی تبدیل به GRUB2 را به اتمام برسانید. اگر شما این تصاویر GRUB2 را ارتقا "
+"ندهید، ممکن است این تصاویر با بسته‌های جدید ناسازگار باشند و باعث جلوگیری از "
+"راه‌اندازی مناسب سیستم شوند."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"شما باید معمولاً به ارتباط GRUB2 پایان دهید، مگر آنکه این رکورد های بوت ساخته "
+"شده توسط GRUB2 مربوط به سیستم عامل های دیگر باشد."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "خط Ùرمان لینوکس:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"خط Ùرمان لینوکس ذیل از /etc/default/grub یا پارامتر های `kopt' در Ùایل menu."
+"lst از گراب قدیمی استخراج شده است. لطÙاً صحت آن را بررسی کنید، Ùˆ در صورت لزوم "
+"آن را تغییردهید. این خط Ùرمان می‌تواند خالی باشد."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "خط Ùرمان پیش Ùرض لینوکس:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"این رشته به عنوان یکی از پارامتر های لینوکس برای منوی پیش Ùرض استÙاده خواهد "
+"شد و نه برای حالت بازیابی."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "خط Ùرمان kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"خط Ùرمان kFreeBSD ذیل از /etc/default/grub یا پارامتر های `kopt' در Ùایل "
+"menu.lst از گراب قدیمی استخراج شده است. لطÙاً صحت آن را بررسی کنید، Ùˆ در صورت "
+"لزوم آن را تغییردهید. این خط Ùرمان می‌تواند خالی باشد."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "خط Ùرمان پیش Ùرض kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"این رشته به عنوان یکی از پارامتر های kFreeBSD برای منوی پیش Ùرض استÙاده "
+"خواهد شد و نه برای حالت بازیابی."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map بازسازی شده است."
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Ùایل /boot/grub/device.map به منظور استÙاده از نام تجهیزات دائمی Ùˆ "
+#~ "پایدار، بازنویسی شده است. در بیشتر موارد، این می‌بایست به شدت نیاز به "
+#~ "تغییر درآینده را کاهش دهد، و مدخل‌های منوی بوت ایجاد شده توسط GRUB نبایست "
+#~ "تحت تأثیر قرار گرÙته باشد."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "اگرچه، از آنجا که بیش از یک دیسک در سیستم موجود است، ممکن است سیستم به "
+#~ "device map قدیمی وابسته باشد. لطÙاً بررسی کنید اگر مدخل‌های سÙارشی بوت Ú©Ù‡ "
+#~ "روی نام‌گذاری درایو (hdN) گراب تکیه دارند وجود داشته باشند، و در صورت نیاز "
+#~ "آنها را به روز نمائید."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "اگر این پیام را متوجه نمی‌شوید، یا اگر هیچ مدخل سÙارشی منوی بوت وجود "
+#~ "ندارد، می‌توانید این پیام را نادیده بگیرید."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "در هر صورت, هر زمان که شما بخواهید مستقیماً GRUB 2 را از MBR بارگزاری "
+#~ "کنید, می توانید این کار را با اجرای دستوری که در ادامه آمده, تحت کاربر "
+#~ "ریشه, انجام دهید:"
diff --git a/debian/po/fi.po b/debian/po/fi.po
new file mode 100644
index 0000000..f3e2cf7
--- /dev/null
+++ b/debian/po/fi.po
@@ -0,0 +1,479 @@
+# Esko Arajärvi <edu@iki.fi>, 2009, 2010.
+# Timo Jyrinki <timo.jyrinki@iki.fi>, 2012, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2014-12-27 18:53+0200\n"
+"Last-Translator: Timo Jyrinki <timo.jyrinki@iki.fi>\n"
+"Language-Team: Finnish <debian-l10n-finnish@lists.debian.org>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Finnish\n"
+"X-Poedit-Country: FINLAND\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Ladataanko ketjutettuna tiedostosta menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUBin päivityskomentosarjat ovat löytäneet vanhoja GRUB-asetuksia "
+"tiedostosta /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Järjestelmässä olevan vanhan GRUB-version korvaamiseksi on suositeltavaa "
+"muokata tiedostoa /boot/grub/menu.lst siten, että GRUB 2 ladataan olemassa "
+"olevista vanhoista GRUB-asetuksista. Tämä voidaan tehdä automaattisesti nyt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"On suositeltavaa, että hyväksyt GRUB 2:n ketjutetun lataamisen tiedostosta "
+"menu.lst ja varmistat uusien GRUB 2 -asetusten toimivuuden ennen kuin "
+"asennat ne pääkäynnistyslohkoon (MBR)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Riippumatta valinnasta vanha MBR voidaan korvata GRUB 2:lla myöhemmin "
+"suorittamalla seuraava komento pääkäyttäjänä:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Laitteet joille GRUB asennetaan:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc-pakettia päivitetään. Tästä valikosta voit valita, mille laitteille "
+"grub-install suoritetaan automaattisesti."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"grub-install:n suorittaminen automaattisesti on suositeltavaa useimmissa "
+"tilanteissa, jotta asennettu GRUB-ydin ei tulisi epäyhteensopivaksi GRUB-"
+"moduulien tai grub.cfg:n kanssa."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Jos et ole varma, mikä asema on määritelty käynnistysasemaksi koneen BIOS-"
+"asetuksissa, on usein hyvä ajatus asentaa GRUB kaikille asemille."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Huomaa: GRUB voidaan asentaa myöt osion käynnistystietoihin, ja joitain "
+"sopivia osioita on ohessa tarjolla. Tämä kuitenkin pakottaa GRUBin "
+"käyttämään lohkoluettelomekanisia, mikä tekee siitä vähemmän luotettavan "
+"eikä ole suositeltavaa."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB-käynnistyslatain oli aiemmin asennettuna levylle, jota ei ole enää "
+"käytössä tai jonka yksilöllinen tunniste on muuttunut jostain syystä. On "
+"tärkeää varmistaa, että asennettu GRUB-ydinkuva pysyy ajan tasalla GRUB-"
+"moduulien ja grub-cfg:n kanssa. Tarkista vielä uudelleen varmistaaksesi, "
+"että GRUB kirjoitetaan oikeille käynnistyslaitteille."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUBin kirjoittaminen käynnistyslaitteelle epäonnistui. Jatketaanko?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUBia ei voitu asentaa seuraaville laitteille:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Valitse haluatko jatkaa tästä huolimatta. Jos jatkat, järjestelmä ei "
+"välttämättä käynnisty kunnolla."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"GRUBin kirjoittaminen käynnistyslaitteelle epäonnistui. Yritetäänkö "
+"uudelleen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Voit ehkä asentaa GRUBin jollekin toiselle levylle. Varmista tällöin, että "
+"järjestelmäsi voidaan käynnistää kyseiseltä levyltä. Muussa tapauksessa "
+"GRUBin aiemman version päivitys perutaan."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Jatketaanko asentamatta GRUBia?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Päätit olla asentamatta GRUBia millekään laitteelle. Jos jatkat, "
+"alkulatausohjelman asetukset saattavat olla väärät ja kun kone käynnistetään "
+"uudelleen seuraavan kerran, se käyttää käynnistyslohkon aiempia asetuksia. "
+"Jos käynnistyslohkossa on GRUB 2:n aiempi versio, se ei välttämättä pysty "
+"lataamaan moduuleja tai käsittelemään nykyistä asetustiedostoa."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Jos käytät jo muuta alkulatausohjelmaa ja haluat jatkaa sen käyttöä tai jos "
+"käytössäsi on erityinen ympäristö, jossa et tarvitse alkulatausohjelmaa, "
+"voit jatkaa asennusta. Muussa tapauksessa sinun tulisi asentaa GRUB johonkin."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Poistetaanko GRUB 2 kohteesta /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Haluat poistaa kaikki GRUB 2 -tiedostot kohteesta /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Tämä tekee järjestelmästä käynnistyskelvottoman, ellei toista "
+"käynnistyslatainta ole asennettu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Saatetaanko siirtyminen GRUB 2:een loppuun nyt?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Järjestelmässä on edelleen GRUBin aiemman version tiedostoja, mutta myös "
+"GRUB 2:n käynnistystiedot on asennettu seuraaville levyille:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"GRUBin aiempi versio ei luultavasti ole enää käytössä ja näillä levyillä "
+"olevat GRUB 2:n levykuvat tulisi päivittää ja siirtyminen GRUB 2:een saattaa "
+"loppuun poistamalla vanhat GRUB-tiedostot. Jos et päivitä GRUB 2:n kuvia, "
+"uusien pakettien kanssa voi tulla yhteensopivuusongelmia ja järjestelmän "
+"käynnistys ei ehkä toimi oikein."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Yleisesti ottaen siirtyminen GRUB 2:een tulisi saattaa loppuun ellei näitä "
+"käynnistystietoja luotu johonkin toiseen käyttöjärjestelmään asennetulla "
+"GRUB 2:lla."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linuxin komentorivi:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"GRUBin aiemman version tiedostosta menu.lst parametrista â€kopt†tai "
+"tiedostosta /etc/default/grub löydettiin seuraava Linuxin komentorivi. "
+"Varmista, että se on kunnossa ja muuta sitä tarvittaessa. Komentorivin on "
+"sallittua myös olla tyhjä."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linuxin oletuskomentorivi:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Seuraavaa merkkijonoa käytetään Linuxin käynnistysvalikon oletusvalinnan "
+"parametreina, mutta ei toipumistilassa."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Pakotetaanko lisäasennus irrotettavissa olevan median EFI-polkuun?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Jotkin EFI-järjestelmät sisältävät ohjelmavirheitä joidenka takia ne eivät "
+"käsittele alkulatausohjelmia oikein. Jos pakotat GRUB:n lisäasentamisen "
+"irrotettavissa olevan median EFI-polkuun, järjestelmän pitäisi kyetä "
+"käynnistämään Debian riippumatta kyseisenkaltaisista ongelmista. Tämä "
+"kuitenkin saattaa poistaa mahdollisuuden muiden käyttöjärjestelmien "
+"käynnistämiseen, mikäli ne riippuvat samasta polusta. Tässä tapauksessa "
+"tulee varmistaa, että GRUBin asetukset on tehty niin, että GRUBista voidaan "
+"käynnistää nämä muut käyttöjärjestelmät oikein."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD:n komentorivi:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"GRUBin aiemman version tiedostosta menu.lst parametrista â€kopt†tai "
+"tiedostosta /etc/default/grub löydettiin seuraava kFreeBSD:n komentorivi. "
+"Varmista, että se on kunnossa ja muuta sitä tarvittaessa. Komentorivin on "
+"sallittua myös olla tyhjä."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD:n oletuskomentorivi:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Seuraavaa merkkijonoa käytetään kFreeBSD:n käynnistysvalikon oletusvalinnan "
+"parametreina, mutta ei toipumistilassa."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map on luotu uudelleen"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Tiedosto /boot/grub/device.map on kirjoitettu uudelleen käyttäen pysyviä "
+#~ "laitenimiä. Useimmissa tapauksissa tämän pitäisi huomattavasti vähentää "
+#~ "tarvetta sen muuttamiseen ja GRUBin luomien käynnistysvalikon rivien "
+#~ "pitäisi toimia edelleen."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Koska järjestelmässä kuitenkin on useampia levyjä, on mahdollista, että "
+#~ "järjestelmä on riippuvainen vanhasta laitekartasta. Tarkista onko "
+#~ "käynnistysvalikossa rivejä, joissa käytetään GRUBin laitenumerointia "
+#~ "(hdN), ja päivitä ne tarvittaessa."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Jos et ymmärrä tätä viestiä tai käynnistysvalikossa ei ole erityisiä "
+#~ "rivejä, voit jättää tämän viestin huomiotta."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Kun haluat asentaa GRUB 2:n latautumaan suoraan pääkäynnistyslohkosta, "
+#~ "voit joka tapauksessa tehdä sen ajamalla pääkäyttäjänä seuraavan komennon:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "GRUBin asennus epäonnistui. Jatketaanko?"
diff --git a/debian/po/fr.po b/debian/po/fr.po
new file mode 100644
index 0000000..95621a9
--- /dev/null
+++ b/debian/po/fr.po
@@ -0,0 +1,516 @@
+# translation of fr.po to French
+# Translation of grub2 debconf templates to French
+# Copyright (C) 2008-2010 Debian French l10n <debian-l10n-french@lists.debian.org>
+# This file is distributed under the same license as the grub2 package.
+#
+# Christian Perrier <bubulle@debian.org>, 2007, 2008, 2009, 2010, 2011, 2014.
+# Baptiste Jammet <baptiste@mailoo.org>, 2017, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: fr\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-26 19:30+0200\n"
+"Last-Translator: Baptiste Jammet <baptiste@mailoo.org>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 20.12.0\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Faut-il enchaîner le chargement depuis menu.lst ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "Une installation ancienne de GRUB a été détectée dans /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Afin de remplacer cette installation, il est recommandé de modifier /boot/"
+"grub/menu.lst pour charger GRUB 2 depuis l'installation standard de GRUB "
+"(« chainload »). Veuillez choisir si vous souhaitez effectuer cette "
+"modification."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Il est recommandé de choisir cette option pour pouvoir confirmer le bon "
+"fonctionnement de GRUB 2 avant de l'installer directement sur le secteur "
+"d'amorçage (MBR : « Master Boot Record »)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Quel que soit votre choix, vous pourrez, plus tard, remplacer l'ancien "
+"secteur d'amorçage par GRUB 2 avec la commande suivante, exécutée avec les "
+"privilèges du superutilisateur :"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Périphériques sur lesquels installer GRUB :"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Le paquet grub-pc est en cours de mise à jour. Ce menu permet de choisir "
+"pour quels périphériques vous souhaitez exécuter la commande grub-install "
+"automatiquement."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Il est en général recommandé d'exécuter grub-install automatiquement, afin "
+"d'éviter la situation où l'image de GRUB est désynchronisée avec les modules "
+"de GRUB ou le fichier grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Si vous n'avez pas la certitude du périphérique utilisé comme périphérique "
+"d'amorçage par le BIOS, il est en général conseillé d'installer GRUB sur "
+"l'ensemble des périphériques."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Veuillez noter que GRUB peut également être installé sur les secteurs "
+"d'amorçage des partitions. Certaines partitions où cela pourrait être "
+"nécessaire sont indiquées ici. Cependant, cela impose que GRUB utilise le "
+"mécanisme « blocklist », ce qui le rend moins fiable et n'est donc pas "
+"recommandé."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Le chargeur d'amorçage GRUB était précédemment installé sur un disque qui "
+"n'est plus présent ou dont l'identifiant unique a changé pour une raison ou "
+"une autre. Il est important de vous assurer que l'image de GRUB qui est "
+"installée reste synchronisée avec les modules de GRUB et grub.cfg. Veuillez "
+"vérifier à nouveau que GRUB sera bien installé sur les périphériques "
+"d'amorçage pertinents."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} Mo; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} Mo; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+"Échec de l'installation de GRUB sur le périphérique d'amorçage. Faut-il continuer ?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB n'a pas pu être installé sur les périphériques suivants :"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Veuillez confirmer si vous souhaitez continuer malgré le risque d'un "
+"démarrage incorrect de la machine."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Échec de l'installation de GRUB sur le périphérique d'amorçage. Faut-il essayer à "
+"nouveau ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Il est peut-être possible d'installer GRUB sur un autre périphérique après "
+"avoir vérifié que le système pourra démarrer sur ce périphérique. Dans le "
+"cas contraire, la mise à jour depuis l'ancienne version de GRUB va échouer."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Faut-il poursuivre sans installer GRUB ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Vous avez choisi de n'installer GRUB sur aucun périphérique. Si vous "
+"poursuivez, il est possible que le chargeur d'amorçage ne soit pas "
+"configuré correctement et que la machine démarre avec ce qui était "
+"précédemment installé sur le secteur d'amorçage. Si une ancienne version de "
+"GRUB 2 s'y trouve, il est possible qu'elle ne puisse pas charger certains "
+"modules ou lire le fichier de configuration actuel."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Si vous utilisez déjà un autre chargeur d'amorçage et souhaitez "
+"poursuivre ou si, en raison d'un environnement particulier, vous n'avez pas "
+"besoin de chargeur d'amorçage, vous pouvez continuer malgré tout. Dans le "
+"cas contraire, il est nécessaire d'installer GRUB quelque part."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Faut-il supprimer GRUB 2 de /boot/grub ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+"Veuillez choisir si vous voulez vraiment supprimer tous les fichiers de "
+"GRUB 2 de /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Cela peut rendre le système impossible à démarrer tant qu'un autre chargeur "
+"d'amorçage ne sera pas installé."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Faut-il terminer la migration vers GRUB 2 maintenant ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ce système comporte encore des fichiers de la version précédente du "
+"chargeur d'amorçage GRUB mais comporte également des secteurs d'amorçage "
+"de GRUB 2 sur les disques suivants :"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Il est très probable que la version précédente de GRUB ne soit plus utilisée "
+"et il est donc conseillé de mettre à jour les images de GRUB 2 sur ces "
+"disques, puis terminer la migration vers GRUB 2 en supprimant les anciens "
+"fichiers de la version précédente. Si vous ne mettez pas ces images de "
+"GRUB 2 à jour, elles pourraient être incompatibles avec de nouvelles "
+"versions, ce qui pourrait empêcher un démarrage normal."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Il est donc très probablement nécessaire de terminer la migration vers "
+"GRUB 2 à moins que ces secteurs d'amorçage n'aient été créés par une "
+"installation de GRUB 2 d'un autre système d'exploitation."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Ligne de commande de Linux :"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La ligne de commande de Linux suivante a été récupérée via le fichier /etc/"
+"default/grub ou le paramètre « kopt » du fichier menu.lst utilisé par la "
+"version originelle de GRUB. Veuillez contrôler qu'elle est correcte et la "
+"modifier si nécessaire. Cette ligne de commande peut être vide."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Ligne de commande par défaut de Linux :"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Les paramètres indiqués seront utilisés pour le noyau Linux de l'entrée de "
+"menu par défaut mais pas pour le mode de secours."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+"Faut-il forcer une installation supplémentaire sur le chemin des supports "
+"amovibles EFI ?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Certains systèmes EFI ne gèrent pas correctement les nouveaux chargeurs "
+"d'amorçage. Si vous forcez l'installation de GRUB sur le chemin des supports "
+"amovibles EFI, cela garantira que ce système pourra malgré tout démarrer "
+"Debian. Par contre, cela interdira le démarrage de tout autre système "
+"d'exploitation qui dépendrait aussi de ce chemin. Si c'est le cas, vous "
+"devez vous assurer que GRUB lui-même est configuré pour démarrer les autres "
+"systèmes d'exploitation."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+"Faut-il mettre à jour les variables dans la mémoire non volatile pour "
+"démarrer Debian automatiquement ?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB peut configurer les variables dans la mémoire non volatile (NVRAM) pour "
+"démarrer Debian automatiquement à l'allumage. Cependant, vous pourriez avoir "
+"envie de désactiver cette possibilité et ainsi éviter les changements dans "
+"la configuration de l'amorçage. Par exemple, si les variables de votre NVRAM "
+"ont été configurées pour que le système se connecte à un serveur PXE à "
+"chaque démarrage, cela conserverait ce comportement."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Faut-il exécuter os-prober automatiquement pour détecter et amorcer d'autres "
+"systèmes ?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB peut utiliser os-prober pour essayer de détecter d'autres systèmes "
+"d'exploitation sur votre ordinateur et les ajouter automatiquement à la "
+"liste des options d'amorçage."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"S'il y a plusieurs systèmes d'exploitation installés, vous devriez accepter "
+"cette option. En revanche, si ce système est un hôte pour des systèmes "
+"invités installés grâce à LVM ou des périphériques bruts, exécuter os-prober "
+"peut causer des dégâts à ces systèmes invités. En effet, les systèmes de "
+"fichiers seront montés pour être analysés."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Ligne de commande de kFreeBSD :"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La ligne de commande de kFreeBSD suivante a été récupérée via le fichier /"
+"etc/default/grub ou le paramètre « kopt » du fichier menu.lst utilisé par la "
+"version originelle de GRUB. Veuillez contrôler qu'elle est correcte et la "
+"modifier si nécessaire. Cette ligne de commande peut être vide."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Ligne de commande par défaut de kFreeBSD :"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Les paramètres indiqués seront utilisés pour le noyau kFreeBSD de l'entrée "
+"de menu par défaut mais pas pour le mode de secours."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "Recréation de /boot/grub/device.map"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Le fichier /boot/grub/device.map a été réécrit afin d'utiliser des noms "
+#~ "de périphériques stables. Dans la majorité des cas, cela devrait éviter "
+#~ "d'avoir à le modifier dans le futur et les entrées de menu créées par "
+#~ "GRUB ne devraient pas être affectées par ce changement."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Cependant, si la machine comporte plus d'un disque, il est possible que "
+#~ "le démarrage dépende de l'ancien système de cartographie des "
+#~ "périphériques (« device map »). Vous devriez vérifier s'il existe des "
+#~ "entrées de menu de démarrage personnalisées qui se servent encore de la "
+#~ "numérotation de disques de GRUB (hdN), puis les mettre à jour si "
+#~ "nécessaire."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Si vous ne comprenez pas ces explications ou n'utilisez pas d'entrées "
+#~ "personnalisées dans le menu de démarrage, vous pouvez ignorer cet "
+#~ "avertissement. "
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Dans tous les cas, pour charger GRUB 2 directement depuis le secteur "
+#~ "d'amorçage, vous devrez utiliser la commande suivante avec les privilèges "
+#~ "du superutilisateur :"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Échec de l'installation de GRUB. Continuer ?"
diff --git a/debian/po/gl.po b/debian/po/gl.po
new file mode 100644
index 0000000..93afc20
--- /dev/null
+++ b/debian/po/gl.po
@@ -0,0 +1,478 @@
+# translation of grub2_1.98+20100804-2_gl.po to Galician
+# Galician translation of grub2's debconf templates
+# This file is distributed under the same license as the grub2 package.
+#
+# Jacobo Tarrio <jtarrio@debian.org>, 2007, 2008.
+# Jorge Barreiro <yortx.barry@gmail.com>, 2010, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2_1.98+20100804-2_gl\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-06-13 16:13+0200\n"
+"Last-Translator: Jorge Barreiro <yortx.barry@gmail.com>\n"
+"Language-Team: Galician <proxecto@trasno.net>\n"
+"Language: gl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Cargar en cadea desde menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Os scripts de actualización de GRUB detectaron unha configuración do GRUB "
+"antigo en /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Para substituír a versión antiga de GRUB do sistema, recoméndase axustar /"
+"boot/grub/menu.lst para cargar unha imaxe de arranque de GRUB 2 desde a "
+"configuración existente do GRUB antigo. Pódese realizar este paso "
+"automaticamente agora."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Recoméndase que acepte cargar GRUB 2 en cadea desde menu.lst, e que "
+"verifique que a nova configuración de GRUB 2 funciona para vostede, antes de "
+"instalalo directamente no MBR (rexistro mestre de inicio)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Decida o que decida, poderá substituír a vella imaxe do MBR con GRUB 2 máis "
+"tarde, usando a seguinte orde como «root»:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Dispositivos onde instalar GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"O paquete «grub-pc» estase actualizando. Este menú permítelle escoller os "
+"dispositivos onde queira que se execute «grub-install» automaticamente, se "
+"quere facelo en algún."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Recoméndase executar «grub-install» automaticamente na maioría dos casos, "
+"para evitar que a imaxe do núcleo de GRUB se desincronice cos módulos de "
+"GRUB ou co ficheiro «grub.cfg»."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Se non está seguro de que dispositivo se escolle na BIOS como dispositivo de "
+"arranque, normalmente é unha boa idea instalar GRUB en todos eles."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: tamén se pode instalar GRUB en rexistros de particións de arranque, e "
+"aquí ofrécense algunhas particións apropiadas. Sen embargo, isto obriga a "
+"GRUB a usar o mecanismo «blocklist», que o fai menos fiábel, polo que non se "
+"recomenda."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"O cargador de arranque GRUB foi anteriormente instalado en un disco que xa "
+"non está presente, ou que mudou o seu identificador único por algunha razón. "
+"É importante asegurarse de que a imaxe do núcleo de GRUB se manteña "
+"sincronizada cos módulos de GRUB e co ficheiro «grub.cfg». Comprobe de novo "
+"para asegurarse de que GRUB se escribiu no dispositivo de arranque apropiado."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+"Produciuse un erro ao escribir GRUB no dispositivo de arranque. Quere "
+"continuar?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Non se puido instalar GRUB nos seguintes dispositivos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Quere continuar de todas maneiras? Se o fai, pode que a súa computadora non "
+"poida iniciar correctamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Produciuse un erro ao escribir GRUB no dispositivo de arranque. Quere "
+"tentalo de novo?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Ao mellor pode instalar GRUB en outro dispositivo, pero debería comprobar "
+"que o seu sistema pode iniciar desde él. Se non, a instalación desde GRUB "
+"Legacy cancelarase."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Quere continuar sen instalar GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Escolleu non instalar GRUB en ningún dispositivo. De continuar,pode que o "
+"cargador de arranque non quede adecuadamente configurado, e a próxima vez "
+"que arranque o sistema usarase o que houbese antes no sector de arranque. Se "
+"nel hai unha versión antiga de GRUB 2 pode que esta sexa incapaz de cargar "
+"os módulos ou de manexar o ficheiro de configuración actual."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Se xa está usando un cargador de arranque diferente e quere continuar "
+"usandoo, ou se este é un ambiente especial onde non necesita un cargador de "
+"arranque, debería continuar. En caso contrario debería instalar GRUB en "
+"algún lugar."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Quere eliminar GRUB 2 de /boot/grub ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Quere que todos os ficheiros de GRUB 2 se eliminen de /boot/grub ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Isto fará que o sistema non poida arrancar, a menos que teña outro cargador "
+"de arranque instalado."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Rematar a conversión a GRUB 2 agora?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Este sistema aínda ten instalados ficheiros do cargador de arranque GRUB "
+"Legacy, pero agora tamén ten rexistros de arranque de GRUB 2 nestes discos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Asemella que GRUB Legacy xa non se usa, e que debería actualizar as imaxes "
+"de GRUB 2 nestes discos e rematar a conversión a GRUB 2 eliminando os "
+"ficheiros vellos de GRUB Legacy. Se non actualiza estas imaxes de GRUB 2, "
+"poderían ser incompatíbeis cos novos paquetes e provocar que sistema non "
+"arranque correctamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"En xeral, debería rematar a conversión a GRUB 2 a menos que estos rexistros "
+"de inicio fosen creatos por unha instalación de GRUB 2 en outro sistema "
+"operativo."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Liña de comando de Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A seguinte liña de comando de Linux sacouse de /etc/default/grub ou do "
+"parámetro «kopt» no ficheiro menu.lst de GRUB Legacy. Verifique que sexa "
+"correcta e modifíquea de ser preciso. A liña de comando pódese deixar "
+"baleira."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Liña de comando por defecto para Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"A seguinte liña será usada como parámetros para Linux na entrada por defecto "
+"do menú, pero non no modo de recuperación."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Liña de comando de kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A seguinte liña de comando de kFreeBSD sacouse de /etc/default/grub, ou do "
+"parámetro «kopt» no ficheiro menu.lst de GRUB Legacy. Verifique que sexa "
+"correcta e modifíquea de ser preciso. A liña de comando pódese deixar "
+"baleira."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Liña de comando por defecto para kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"A seguinte cadea usarase como parámetros para kFreeBSD para a entrada por "
+"defecto do menú, pero non para o modo de recuperación."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map foi rexenerado."
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "O ficheiro /boot/grub/device.map foi reescrito para usar nomes de "
+#~ "dispositivos estábeis. Na maioría dos casos isto debería reducir "
+#~ "significativamente a necesidade de cambialos en un futuro, e as entradas "
+#~ "no menú de GRUB non se verían afectadas."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Porén, como ten máis de un disco no seu sistema, pode que dependa do "
+#~ "vello «device map». Comprobe se ten algunha entrada personalizada no menú "
+#~ "de arranque que use a numeración de unidades de GRUB (hdN) e actualícea "
+#~ "de ser necesario."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Se non comprende esta mensaxe, ou se non ten ningunha entrada "
+#~ "personalizada no menú de arranque, pode ignorala."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "En calquera caso, cando queira cargar GRUB 2 directamente desde o MBR, "
+#~ "pode facelo executando (coma administrador) a seguinte orde:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "A instalación de GRUB fallou. Quere continuar?"
diff --git a/debian/po/gu.po b/debian/po/gu.po
new file mode 100644
index 0000000..46af226
--- /dev/null
+++ b/debian/po/gu.po
@@ -0,0 +1,442 @@
+# Gujarati translation of grub2.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Kartik Mistry <kartik@debian.org>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub-gu\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-03-04 09:56+0530\n"
+"Last-Translator: Kartik Mistry <kartik@debian.org>\n"
+"Language-Team: Gujarati <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst માંથી ચેઈનલોડ કરશો?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "GRUB સà«àª§àª¾àª°àª¾àª¨à«€ સà«àª•à«àª°àª¿àªªà«àªŸàª /boot/grub માં પરંપરાગત GRUB ગોઠવણીની જાણ મેળવી છે."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"તમારી સિસà«àªŸàª®àª®àª¾àª‚થી પરંપરાગત GRUB ને બદલવા માટે, ઠસલાહભરà«àª¯à«àª‚ છે કે /boot/grub/menu.lst "
+"ઠGRUB 2 બૂટ ઈમેજ લાવવા માટે તમારી હાલના પરંપરાગત GRUB ગોઠવણીમાંથી ગોઠવેલ હોય. આ "
+"ગોઠવણી હવે પછી આપમેળે રજૂ કરવામાં આવશે."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"ઠસલાહભરà«àª¯à«àª‚ છે કે તમે menu.lst માંથી GRUB 2 ચેઈનલોડિંગ સà«àªµàª¿àª•àª¾àª°à«‹, અને ચકાસો કે નવી GRUB "
+"2 ગોઠવણી MBR (માસà«àªŸàª° બૂટ રેકોરà«àª¡) માં લખાય તે પહેલાં કામ કરી રહી છે."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"તમારો નિરà«àª£àª¯ કંઈ પણ હોય, તમે પાછળથી નીચેના આદેશનો રà«àªŸ તરીકે ઉપયોગ કરીને જૂની MBR ઈમેજને "
+"GRUB 2 વડે બદલી શકો છો."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB સà«àª¥àª¾àªªàª¨ ઉપકરણો:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc પેકેજ સà«àª§àª¾àª°àª¾àªˆ રહà«àª¯à«àª‚ છે. આ મેનૠતમને કયા ઉપકરણોમાં તમે grub-install આપમેળે સà«àª¥àª¾àªªàª¿àª¤ "
+"કરવા માટે ચલાવવા માંગો છો તે પસંદગી કરવા દે છે, જો કોઈ હોય તો."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"સà«àª¥àª¾àªªàª¿àª¤ GRUB મà«àª–à«àª¯ ઈમેજને GRUB મોડà«àª¯à«àª²à«àª¸ અથવા grub.cfg સાથે અસંગત ન થવા દેવા માટે, grub-"
+"install આપમેળે ચલાવવà«àª‚ ઠમોટાભાગની પરિસà«àª¥àª¿àª¤àª¿àª“માં સલાહભરà«àª¯à«àª‚ છે."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"જો તમે અચોકà«àª•àª¸ હોવ કે તમારા BIOS વડે કયà«àª‚ ડà«àª°àª¾àªˆàªµ ઠબૂટ ડà«àª°àª¾àªˆàªµ તરીકે ગોઠવેલ છે, ઠસારો "
+"વિચાર છે કે તે દરેક ઉપર GRUB સà«àª¥àª¾àªªàª¿àª¤ કરવામાં આવે."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"નોંધ: GRUB ને પારà«àªŸàª¿àª¶àª¨ બૂટ રેકોરà«àª¡ પર સà«àª¥àª¾àªªàª¿àª¤ કરવાનà«àª‚ પણ શકà«àª¯ છે, અને કેટલાક સંબંધિત "
+"પારà«àªŸàª¿àª¶àª¨à«àª¸ અહીં આપવામાં આવે છે. તેમ છતાં, આ GRUB ને બà«àª²à«‹àª•àª²àª¿àª¸à«àªŸ પધà«àª§àª¤àª¿ વાપરવા માટે મજબૂર કરે "
+"છે, જે તેને ઓછà«àª‚ ભરોસાપાતà«àª° બનાવે છે, અને તેથી, આ સલાહભરà«àª¯à«àª‚ નથી."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"ડિસà«àª• પર પહેલાં સà«àª¥àª¾àªªàª¨ કરેલ GRUB બૂટ લોડર હવે હાજર નથી, અથવા તેની àªàª•à«àª¯ ઓળખ કોઈ "
+"કારણોસર બદલાઈ ગઈ છે. ઠમહતà«àªµàª¨à«àª‚ છે કે સà«àª¥àª¾àªªàª¿àª¤ GRUB મà«àª–à«àª¯ ઈમેજ GRUB મોડà«àª¯à«àª²à«àª¸ અને grub.cfg "
+"જોડે સંગત રહે તેની ખાતરી કરાઈ હોય. મહેરબાની કરી ફરીથી ખાતરી કરી ચકાસો કે GRUB ઠ"
+"યોગà«àª¯ બૂટ ઉપકરણોમાં લખાયેલ છે."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} àªàª®àª¬à«€; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} àªàª®àª¬à«€; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUB ને બૂટ ઉપકરણમાં લખવાનà«àª‚ નિષà«àª«àª³ ગયà«àª‚ - ચાલૠરાખશો?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB નીચેના ઉપકરણોમાં સà«àª¥àª¾àªªàª¿àª¤ થવામાં નિષà«àª«àª³ ગયà«àª‚:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"તમે તેમ છતાં આગળ વધવા માંગો છો? જો તમે તેમ કરશો તો, તમારà«àª‚ કોમà«àªªà«àª¯à«àªŸàª° કદાચ યોગà«àª¯ રીતે "
+"શરà«àª¥àª¶à«‡ નહી."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "GRUB ને બૂટ ઉપકરણમાં લખવાનà«àª‚ નિષà«àª«àª³ ગયà«àª‚ - ફરી પà«àª°àª¯àª¤à«àª¨ કરશો?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"તમે કદાચ GRUB બીજા ઉપકરણમાં સà«àª¥àª¾àªªàª¿àª¤ કરી શકો છો, તેમ છતાં ચકાસો કે તમારી સિસà«àªŸàª® આ "
+"ઉપકરણમાંથી બૂટ થઈ શકશે. અથવા તો, GRUB પરંપરાગતમાંથી સà«àª§àª¾àª°à«‹ રદ કરવામાં આવશે."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB સà«àª¥àª¾àªªàª¨ કરà«àª¯àª¾ વગર આગળ વધશો?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"તમે GRUB ને કોઈપણ ઉપકરણમાં સà«àª¥àª¾àªªàª¿àª¤ કરવાનà«àª‚ પસંદ કરેલ નથી, જો તમે ચાલૠરાખશો તો, બૂટ "
+"લોડર કદાચ યોગà«àª¯ રીતે ગોઠવાયેલ નહી હોય, અને આ કોમà«àªªà«àª¯à«àªŸàª° હવે ફરી શરૠથાય તà«àª¯àª¾àª°à«‡ તે પહેલાંનà«àª‚ "
+"જે હોય તે બૂટ વિભાગ ઉપયોગ કરશે. જો તેમાં પહેલાની GRUB 2 આવૃતà«àª¤àª¿ બૂટ સેકà«àªŸàª° પર હશે તો, "
+"કદાચ તે મોડà«àª¯à«àª² લાવવા અથવા હાલનાં રà«àªªàª°à«‡àª–ાંકન ફાઈલને સંભાળવામાં અસમરà«àª¥ બનશે."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"જો તમે પહેલાથી બીજà«àª‚ બૂટ લોડર વાપરી રહà«àª¯àª¾ હોવ અને તેમ કરવાનà«àª‚ ચાલૠરાખવા માંગતા હોય તો, "
+"અથવા આ ખાસ પરà«àª¯àª¾àªµàª°àª£ હોય જà«àª¯àª¾àª‚ તમારે બૂટ લોડરની જરà«àª° ન હોય તો તમે આગળ વધી શકો છો. "
+"નહીતર, તમારે કà«àª¯àª¾àª‚ક GRUB સà«àª¥àª¾àªªàª¿àª¤ કરવà«àª‚ જોઈàª."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "/boot/grub માંથી GRUB ૨ દૂર કરશો?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "તમે /boot/grub માંથી બધી GRUB 2 ફાઈલà«àª¸ દૂર કરવા માંગો છો?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "આ તમારી સિસà«àªŸàª®àª¨à«‡ શરૠન કરવા જેવી બનાવશે જà«àª¯àª¾àª‚ સà«àª§à«€ બીજà«àª‚ બૂટ લોડર સà«àª¥àª¾àªªàª¿àª¤ નહી હોય."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "GRUB ૨ માં રà«àªªàª¾àª‚તર હવે પૂરà«àª£ થયà«àª‚?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"આ સિસà«àªŸàª®àª®àª¾àª‚ સà«àª¥àª¾àªªàª¿àª¤ કરેલ GRUB પરંપરાગત બૂટ લોડરમાંથી ફાઈલà«àª¸ હાજર રહેલ છે, પણ તેમાં નીચેની "
+"ડિસà«àª•à«àª¸ પર GRUB 2 બૂટ રેકોરà«àª¡à«àª¸ સà«àª¥àª¾àªªàª¿àª¤ કરેલ છે:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"àªàªµà«àª‚ જણાય છે કે GRUB પરંપરાગત હવે વપરાશમાં નથી, અને તમારે આ ડિસà«àª•à«àª¸ પર GRUB 2 ઈમેજ સà«àª§àª¾àª°à«€ "
+"અને GRUB 2 માં રà«àªªàª¾àª‚તરણ GRUB પરંપરાગત ફાઈલà«àª¸ દૂર કરીને પà«àª°à«àª‚ કરવà«àª‚ જોઈàª. જો તમે આ GRUB 2 "
+"ઈમેજ સà«àª§àª¾àª°àª¶à«‹ નહી તો, તે નવાં પેકેજીસ સાથે અસંગત હશે અને તમારી સિસà«àªŸàª®àª¨à«‡ યોગà«àª¯ રીતે શરૠથતા "
+"અટકાવી શકે છે."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"તમે સામાનà«àª¯ રીતે GRUB 2 માં રà«àªªàª¾àª‚તર કરી લીધà«àª‚ છે સિવાય કે આ બૂટ રેકોરà«àª¡ GRUB 2 સà«àª¥àª¾àªªàª¨ વડે "
+"કોઈ બીજી ઓપરેટિંગ સિસà«àªŸàª®àª®àª¾àª‚ બનાવવામાં આવà«àª¯àª¾ હોય."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "લિનકà«àª¸ આદેશ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"નીચેનાં લિનકà«àª¸ આદેશ /etc/default/grub અથવા GRUB પરંપરાગત menu.lst ના `kopt' "
+"પરિમાણમાંથી નીકાળવામાં આવà«àª¯àª¾ છે. મહેરબાની કરી ખાતરી કરો કે ઠસાચા છે, અને જરà«àª°à«€ હોય "
+"તો તેને બદલો. આદેશ ખાલી રાખવાનà«àª‚ માનà«àª¯ છે."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "લિનકà«àª¸ મૂળભૂત આદેશ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"નીચેનà«àª‚ વાકà«àª¯ મૂળભૂત મેનૠરીત માટે લિનકà«àª¸ પરિમાણો માટે વાપરવામાં આવશે પણ રીકવરી સà«àª¥àª¿àª¤àª¿ માટે "
+"નહી."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD આદેશ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"નીચેનાં kFreeBSD આદેશ /etc/default/grub અથવા GRUB પરંપરાગત menu.lst ના `kopt' "
+"પરિમાણમાંથી નીકાળવામાં આવà«àª¯àª¾ છે. મહેરબાની કરી ખાતરી કરો કે ઠસાચા છે, અને જરà«àª°à«€ હોય "
+"તો તેને બદલો. આદેશ ખાલી રાખવાનà«àª‚ માનà«àª¯ છે."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD મૂળભૂત આદેશ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"નીચેનà«àª‚ વાકà«àª¯ મૂળભૂત મેનૠરીત માટે kFreeBSD પરિમાણો માટે વાપરવામાં આવશે પણ રીકવરી સà«àª¥àª¿àª¤àª¿ "
+"માટે નહી."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map ફરી બનાવવામાં આવી છે"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "ફાઈલ /boot/grub/device.map સà«àª¥àª¿àª¤ ઉપકરણ નામો ઉપયોગ કરવા માટે ફરી લખાઈ છે. "
+#~ "મોટાભાગનાં કિસà«àª¸àª¾àª“માં, આ ભવિષà«àª¯àª®àª¾àª‚ મોટાભાગે તેને બદલવાની જરà«àª°àª¿àª¯àª¾àª¤ ઓછી કરી દેશે, અને "
+#~ "GRUB વડે બનાવેલ દાખલાઓ પર અસર નહી કરે."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "તેમ છતાં, સિસà«àªŸàª®àª®àª¾àª‚ àªàª• કરતાં વધૠડિસà«àª• હાજર હોવાથી, ઠશકà«àª¯ છે કે સિસà«àªŸàª® જૂનાં ઉપકરણ "
+#~ "નકશા પર આધાર રાખતી હોય. મહેરબાની કરી ચકાસો કે અહીં કોઈ પોતાની મેનૠયાદી છે જે "
+#~ "GRUB ના (hdN) ડà«àª°àª¾àªˆàªµ આંકડાઓ પર આધાર રાખતી હોય, અને તેને જરà«àª°à«€ હોય તો સà«àª§àª¾àª°à«‹."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "જો તમને આ સંદેશ સમજવામાં ન આવે, અથવા કોઈ પોતાની બૂટ મેનૠરીત ન હોય તો, તમે આ સંદેશ "
+#~ "અવગણી શકો છો."
diff --git a/debian/po/he.po b/debian/po/he.po
new file mode 100644
index 0000000..5bb67b9
--- /dev/null
+++ b/debian/po/he.po
@@ -0,0 +1,449 @@
+# translation of grub_debian_po_he.po to Hebrew
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+#
+# Omer Zak <w1@zak.co.il>, 2010, 2012.
+# Lior Kaplan <kaplan@debian.org>, 2010, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub_debian_po_he\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2014-12-17 18:35+0200\n"
+"Last-Translator: Omer Zak\n"
+"Language-Team: Hebrew <kde-i18n-doc@kde.org>\n"
+"Language: he\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.5\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "הטענה בשרשור מ-menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "תסריטי העדכון של GRUB גילו הגדרות GRUB ישנות ב-‎‎/boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"כדי להחליף ×ת גירסת GRUB הישנה במערכת שלך, מומלץ לשנות ×ת ‎/boot/grub/menu."
+"lst כך שיבצע הטענה משורשרת של קוד ×”×יתחול של GRUB 2 מהגדרות GRUB הישנות שלך. "
+"ניתן לבצע פעולה זו ב×ופן ×וטומטי עכשיו."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"מומלץ ×©×ª×¡×›×™× ×œ×”×˜×¢× ×” משורשרת של GRUB 2 מ-menu.lst ×•×ª×•×•×“× ×©×”×’×“×¨×•×ª GRUB 2 "
+"החדשות עובדות עבורך, לפני שקוד ×”×תחול נכתב ל-MBR (Master Boot Record)‎ שלך."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"×œ× ×ž×©× ×” מהי החלטתך, ביכולתך להחליף יותר מ×וחר ×ת קוד ×”×תחול הישן ב-MBR בקוד "
+"×”×תחול של GRUB 2 ×¢\"×™ מתן הפקודה הב××” כמשתמש-על:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "×”×ª×§× ×™× ×œ×”×ª×§× ×ª GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"חבילת grub-pc משתדרגת כעת. תפריט ×–×” מ×פשר לך לבחור ×‘×”×ª×§× ×™× ×©×‘×¨×¦×•× ×š ש-grub-"
+"install ירוץ ×¢×œ×™×”× ×וטומטית, ב×× ×™×© ×›×לה."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"בדרך כלל מומלץ להריץ ×וטומטית ×ת grub-install כדי למנוע מליבת קוד ×”×תחול "
+"המותקנת של GRUB מלהפסיק להיות מתו×מת ×¢× ×ž×•×“×•×œ×™ GRUB ×ו ×¢× grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"×× ×ינך בטוח ××™×–×” התקן הוגדר כהתקן ×”×תחול ×¢\"×™ ×”-BIOS שלך, ×œ×¢×ª×™× ×§×¨×•×‘×•×ª ×™×”× "
+"×–×” רעיון טוב להתקין GRUB בכול×."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"הערה: ניתן להתקין GRUB ×’× ×‘×¨×©×•×ž×•×ª ×”×תחול של המחיצות, וכמה מחיצות מת×ימות "
+"מוצעות להלן. ×¢× ×–×ת, התקנה כזו מכריחה ×ת GRUB להשתמש בשיטת רשימת הבלוקי×, "
+"שמורידה מ×מינותו, ולכן ×œ× ×ž×•×ž×œ×¥ להתקין בשיטה זו."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"המ×תחל של GRUB הותקן ×ž×§×•×“× ×‘×“×™×¡×§ שכבר ×ינו קיי×, ×ו שהמזהה הייחודי שלו השתנה "
+"מסיבה כלשהי. חשוב ×œ×•×•×“× ×©×§×•×“ ×”×תחול של ליבת GRUB נש×ר מתו×× ×¢× ×ž×•×“×•×œ×™ GRUB "
+"ו-grub.cfg. ×× × ×‘×“×•×§ שוב כדי ×œ×•×•×“× ×©-GRUB נכתב להתקני ×”×תחול המת×ימי×."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "כשלון בכתיבת GRUB להתקן ×”×תחול - להמשיך?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "כשלון בהתקנת GRUB ×‘×”×ª×§× ×™× ×”×‘××™×:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr "×”×× ×‘×¨×¦×•× ×š להמשיך בכל ×–×ת? ×× ×›×Ÿ, מחשבך עלול ×œ× ×œ×תחל כהלכה."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "כשלון בכתיבת GRUB להתקן ×”×תחול - לנסות שוב?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"ייתכן שתוכל להתקין GRUB בהתקן ×חר, למרות שעליך ×œ×•×•×“× ×©×ž×—×©×‘×š ×™×תחל מההתקן "
+"ההו×. ×חרת, השדרוג מ-GRUB ישן יבוטל."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "להמשיך בלי להתקין GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"בחרת ×œ× ×œ×”×ª×§×™×Ÿ GRUB ב××£ התקן. ×× ×ª×ž×©×™×š, ייתכן שמנהל ×”×תחול ×œ× ×™×”×™×” מוגדר "
+"×›×™×ות, ×•×‘×¤×¢× ×”×‘××” שמחשבך ×™×ותחל, ×”×•× ×™×ותחל ממה שהיה ×§×•×“× ×‘-boot sector. ×× "
+"יש ×’×™×¨×¡× ×ž×•×§×“×ž×ª יותר של GRUB 2 ב-boot sector, ייתכן ×©×œ× ×™×”×™×” ביכולתה להטעין "
+"×ž×•×“×•×œ×™× ×ו להתמודד ×¢× ×§×•×‘×¥ ההגדרות הנוכחי."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"×× ×”×™× ×š כבר משתמש במנהל ×תחול ×חר ומעוניין להמשיך להשתמש בו, ×ו ×× ×–×• סביבה "
+"מיוחדת שבה ×œ× ×“×¨×•×© לך מנהל ×תחול, עליך להמשיך בכל ×–×ת. ×חרת, עליך להתקין "
+"GRUB ×‘×ž×§×•× ×›×œ×©×”×•."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "הסר GRUB 2 מ-/boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "×”×× ×‘×¨×¦×•× ×š להסיר ×ת כל קבצי GRUB 2 מ-/boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "פעולה זו תמנע מהמערכת מל×תחל ××œ× ×× ×ª×ª×§×™×Ÿ מנהל ×תחול ×חר."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "×œ×¡×™×™× ×¢×›×©×™×• המרה ל-GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"יש במערכת זו עדיין ×§×‘×¦×™× ×ž×”×”×ª×§× ×” הישנה של מנהל ×”×תחול GRUB, ×בל יש ×’× ×¨×©×•×ž×•×ª "
+"×תחול GRUB 2 מותקנות ×‘×“×™×¡×§×™× ×”×‘××™×:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"סביר שהתקנת GRUB הישנה כבר ××™× ×” בשימוש, ושעליך ×‘×ž×§×•× ×–×ת לשדרג ×ת תמונות "
+"GRUB 2 ×‘×“×™×¡×§×™× ×לה ×•×œ×¡×™×™× ×ת ההמרה ל-GRUB 2 על ידי הסרת קבצי GRUB הישני×. ×× "
+"×ינך משדרג תמונות GRUB 2 ×לה, הן עלולות להיות בלתי תו×מות ×ת החבילות החדשות "
+"ולמנוע מהמערכת שלך מל×תחל כהלכה."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"בדרך כלל עליך ×œ×¡×™×™× ×ת ההמרה ל-GRUB 2 ××œ× ×× ×¨×©×•×ž×•×ª ×תחול ×לה נוצרו על ידי "
+"התקנת GRUB 2 במערכת הפעלה ×חרת."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "שורת הפקודה של Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"שורת פקודת Linux הב××” נשלפה מ-‎/etc/default/grub ×ו מפרמטר 'kopt' ב-menu.lst "
+"הישן של GRUB. × × ×œ×•×•×“× ×©×©×•×¨×ª פקודה זו נכונה ועדכן ×ותה ×× ×¦×¨×™×š. ניתן להש×יר "
+"שורת פקודה זו ריקה."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "ברירת מחדל לשורת הפקודה של Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"המחרוזת הב××” תשמש כפרמטרי Linux עבור ברירת המחדל בתפריט ×בל ×œ× ×¢×‘×•×¨ מצב "
+"recovery."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "ל×לץ התקנה נוספת לנתיב מדיה EFI הניתן להסרה?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"כמה מערכות מבוססות EFI מכילות ×‘×’×™× ×•×ינן מתמודדות נכונות ×¢× ×ž××ª×—×œ×™× ×—×“×©×™×. "
+"×× ×”×™× ×š מ×לץ התקנה נוספת של GRUB לנתיב מדיה EFI הניתן להסרה, הדבר ×מור "
+"להבטיח שהמערכת ת×תחל נכון ×ת Debian למרות בעיה כזו. ×¢× ×–×ת, הדבר עלול למנוע "
+"×תחול כל מערכת הפעלה ×חרת שתלויה ×’× ×›×Ÿ בנתיב ×–×”. ×× ×–×” המצב, תצטרך ×œ×•×•×“× "
+"ש-GRUB הוגדר בהצלחה כדי שתוכל ל×תחל נכון כל מערכת הפעלה מותקנת ×חרת."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "שורת הפקודה של kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"שורת פקודת kFreeBSD הב××” נשלפה מ-‎/etc/default/grub ×ו מפרמטר'kopt' ב-menu."
+"lst הישן של GRUB. בבקשה ×œ×•×•×“× ×©×©×•×¨×ª פקודה זו נכונה ועדכן ×ותה ×× ×¦×¨×™×š. ניתן "
+"להש×יר שורת פקודה זו ריקה."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "ברירת מחדל לשורת הפקודה של kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"המחרוזת הב××” תשמש כפרמטרי kFreeBSD עבור ברירת המחדל בתפריט ×בל ×œ× ×¢×‘×•×¨ מצב "
+"recovery."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "הקובץ ‎/boot/grub/device.map נוצר מחדש"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "הקובץ ‎/boot/grub/device.map נכתב מחדש כדי להשתמש בשמות ×”×ª×§× ×™× ×™×¦×™×‘×™×. "
+#~ "ברוב המקרי×, הדבר ×מור ×œ×¦×ž×¦× ×‘×¦×•×¨×” משמעותית ×ת הצורך לשנותו בעתיד, "
+#~ "והבחירות בתפריט ×”×תחול הנוצר על ידי GRUB ×œ× ×מורות להיות מושפעות משינוי "
+#~ "×–×”."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "×בל, מכיוון שיש במערכת שלך יותר מדיסק ×חד, ייתכן שהמערכת מסתמכת על קובץ "
+#~ "מיפוי ×”×”×ª×§× ×™× ×”×™×©×Ÿ. ×× × ×‘×“×•×§ ×× ×™×© לך בחירות מות×מות ×ישית בתפריט ×”×תחול, "
+#~ "שמשתמשות בשיטת מספור ×”×”×ª×§× ×™× (hdN) של GRUB, ועדכן ×ותן ×× ×¦×¨×™×š."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "×× ×ינך מבין הודעה זו, ×ו ×× ×ין לך ברירות מות×מות ×ישית בתפריט ×”×תחול, "
+#~ "××–×™ ניתן ×œ×”×ª×¢×œ× ×ž×”×•×“×¢×” זו."
diff --git a/debian/po/hr.po b/debian/po/hr.po
new file mode 100644
index 0000000..18c1314
--- /dev/null
+++ b/debian/po/hr.po
@@ -0,0 +1,491 @@
+# Translation of grub2 debconf templates to Croatian
+# Copyright (C) 2010 Josip Rodin
+# This file is distributed under the same license as the grub2 package.
+# Josip Rodin <joy+ditrans@linux.hr>, 2010.
+# Tomislav Krznar <tomislav.krznar@gmail.com>, 2012, 2017, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 1.97-2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 13:07+0200\n"
+"Last-Translator: Tomislav Krznar <tomislav.krznar@gmail.com>\n"
+"Language-Team: hrvatski <lokalizacija@linux.hr>\n"
+"Language: hr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Poedit 2.3.1\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "UÄitaj ulanÄano preko menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Skripte za nadogradnju GRUB-a su pronašle GRUB Legacy postavke u /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Kako bi zamijenili Legacy verziju GRUB-a na vaÅ¡em sustavu, preporuÄuje se "
+"prilagodba /boot/grub/menu.lst kako bi se ulanÄano uÄitao GRUB 2 iz vaÅ¡ih "
+"postojećih GRUB Legacy postavki. Ovaj korak se sada može automatski izvršiti."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"PreporuÄuje se da prihvatite ulanÄano uÄitavanje GRUB 2 iz menu.lst, tako da "
+"možete provjeriti da vam nove GRUB 2 postavke funkcioniraju, prije nego što "
+"izravno instalirate GRUB2 u MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Å to god odluÄite, možete zamijeniti stari sadržaj MBR-a sa GRUB 2 kasnije "
+"pokretanjem sljedeće naredbe kao root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB uređaji za instalaciju:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Paket grub-pc se nadograđuje. Ovaj izbornik omogućava biranje uređaja za "
+"koje želite automatski pokrenuti grub-install, ako postoje."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Automatsko pokretanje grub-install je preporuÄeno u većini sluÄajeva kako bi "
+"instalirana GRUB osnovna slika bila sinkronizirana s GRUB modulima ili grub."
+"cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ako niste sigurni koji je ureÄ‘aj u BIOS-u odreÄ‘en za uÄitavanje, obiÄno je "
+"dobra ideja instalirati GRUB na svaki."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Napomena: moguće je instalirati GRUB u particijski boot zapis, ovdje su "
+"navedene neke odgovarajuće particije. Međutim, to prisiljava GRUB na "
+"korištenje mehanizma blokiranja, što može biti manje pouzdano i zato se ne "
+"preporuÄuje."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB boot uÄitavaÄ je prethodno instaliran na disk koji viÅ¡e nije prisutan, "
+"ili se njegov jedinstveni identifikator iz nekog razloga promijenio. Važno "
+"je osigurati da instalirana GRUB osnovna slika ostane sikronizirana s GRUB "
+"modulima i grub.cfg. Molim ponovo provjerite je li GRUB instaliran na "
+"odgovarajuće boot uređaje."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Instalacija GRUB-a nije uspjela - želite li nastaviti?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB nije uspješno instaliran na sljedeće uređaje:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Želite li ipak nastaviti? Ako to napravite, vaÅ¡e raÄunalo se možda neće moći "
+"uredno pokrenuti."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Instalacija GRUB-a nije uspjela. Pokušati ponovo?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Možda možete instalirati GRUB na neki drugi uređaj, iako biste morali "
+"provjeriti da se vaš sustav može podizati s tog uređaja. U suprotnom, "
+"nadogradnja s GRUB Legacy će biti prekinuta."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Nastaviti bez instalacije GRUB-a?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Odabrali ste da ne instalirate GRUB ni na jedan uređaj. Ako nastavite, boot "
+"uÄitavaÄ neće biti ispravno podeÅ¡en, a kada se vaÅ¡e raÄunalo idući put "
+"upali, koristit će što god je prethodno bilo u boot sektoru. Ako se tamo "
+"nalazi ranija verzija GRUB 2, možda će doći do problema s uÄitavanjem modula "
+"ili Äitanjem trenutne datoteke postavki."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ako već imate neki drugi boot uÄitavaÄ i želite ga zadržati, ili ako je ovo "
+"neko posebno okruženje gdje ne trebate boot uÄitavaÄ, trebate nastaviti. "
+"InaÄe biste morali negdje instalirati GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Želite li ukloniti GRUB 2 iz /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Želite li ukloniti sve GRUB 2 datoteke iz /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Ovo će onemogućiti uÄitavanje sustava ako nije instaliran drugi boot "
+"uÄitavaÄ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Završiti prebacivanje na GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ovaj sustav joÅ¡ uvijek ima instalirane datoteke GRUB Legacy boot uÄitavaÄa, "
+"ali sada ima i GRUB 2 boot zapise instalirane na ovim diskovima:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Vjerojatno je GRUB Legacy izbaÄen iz uporabe i trebali biste nadograditi na "
+"GRUB 2 snimke na ovim diskovima te završiti prebacivanje brisanjem starih "
+"GRUB Legacy datoteka. Ako niste nadogradili ove GRUB 2 snimke, onda bi one "
+"mogle biti nekompatibilne s novim verzijama paketa, Å¡to bi moglo uzrokovati "
+"nemogućnost ispravnog pokretanja sustava."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Općenito, trebali biste dovršiti nadogradnju na GRUB 2, osim ako su navedeni "
+"boot zapisi napravljeni instalacijom GRUB 2 na nekom drugom operacijskom "
+"sustavu."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux naredbeni redak:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ovaj naredbeni redak za sam Linux kernel je preuzet iz /etc/default/grub ili "
+"iz parametra 'kopt' u GRUB Legacy datoteci menu.lst. Molim provjerite je li "
+"ispravan i, ako je potrebno, uredite ga. Naredbeni redak smije biti prazan."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Pretpostavljeni Linux naredbeni redak:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Sljedeći izraz će se koristiti kao parametar za Linux stavke u izborniku, "
+"osim za spasonosni naÄin rada."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Prisilno dodatno instalirati u EFI direktorij prijenosnog medija?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Neki EFI sustavi imaju bugove i ne rade ispravno s novim boot uÄitavaÄima. "
+"Ako prisilno dodatno instalirate GRUB u EFI direktorij prijenosnog medija, "
+"sustav bi trebao ispravno uÄitati Debian unatoÄ navedenom problemu. MeÄ‘utim, "
+"to može onemogućiti uÄitavanje ostalih operacijskih sustava koji takoÄ‘er "
+"ovise o ovom direktoriju. Ako je tako, morat ćete osigurati da je GRUB "
+"uspjeÅ¡no postavljen za ispravno uÄitavanje ostalih instaliranih operacijskih "
+"sustava."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Ažurirati NVRAM varijable za automatsko uÄitavanje Debiana?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB može postaviti NVRAM varijable vaÅ¡e platforme da se automatski uÄita "
+"Debian pri ukljuÄivanju. MeÄ‘utim, možda će vam biti praktiÄnije onemogućiti "
+"ovakvo ponašanje i izbjeći promjene vaših postavki. Na primjer, ako su vaše "
+"NVRAM varijable postavljene tako da se vaš sustav povezuje s PXE "
+"poslužiteljem pri svakom uÄitavanju, ovo će oÄuvati takvo ponaÅ¡anje."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Pokrenuti os-prober za automatsko traženje i uÄitavanje drugih operacijskih "
+"sustava?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB može alatom os-prober pokušati pronaći druge operacijske sustave na "
+"VaÅ¡em raÄunalu i automatski ih dodati na popis za uÄitavanje."
+
+# TK: TODO: find if we translated 'LVM' in other files.
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Ovo vjerojatno želite ako je na VaÅ¡em raÄunalu instalirano viÅ¡e operacijskih "
+"sustava. MeÄ‘utim, budući da alat pokuÅ¡ava montirati datoteÄne sustave kako "
+"bi pronaÅ¡ao druge operacijske sustave, u sluÄaju kada su na raÄunalu "
+"instalirani virtualni operacijski sustavi na LVM ili 'neobrađene' diskove, "
+"može doći do njihovog oštećenja."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD naredbeni redak:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ovaj naredbeni redak za kFreeBSD kernel je preuzet iz /etc/default/grub ili "
+"iz parametra 'kopt' u GRUB Legacy datoteci menu.lst. Molim provjerite je li "
+"ispravan i, ako je potrebno, uredite ga. Naredbeni redak smije biti prazan."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Pretpostavljeni kFreeBSD naredbeni redak:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Sljedeći izraz će se koristiti kao parametar za kFreeBSD stavke u izborniku, "
+"osim za spasonosni naÄin rada."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map je regeneriran"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Datoteka /boot/grub/device.map je prepisana kako bi se u njoj koristila "
+#~ "stabilna imena ureÄ‘aja. U većini sluÄajeva, to bi trebalo znaÄajno "
+#~ "smanjiti potrebu za njenim budućim mijenjanjem, a boot stavke koje "
+#~ "generira GRUB ne bi trebale biti pod utjecajem ove promjene."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ipak, budući da imate više od jednog diska u vašem sustavu, moguće je da "
+#~ "ste ovisili o staroj mapi uređaja. Molim provjerite imate li nekih "
+#~ "prilagoÄ‘enih boot zapisa koji ovise o GRUB-ovom (hdN) oznaÄavanju "
+#~ "uređaja, i ažurirajte ih ako je potrebno."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ako ne razumijete ovu poruku, ili ako nemate prilagođenih boot zapisa, "
+#~ "ovu poruku možete zanemariti."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "U oba sluÄaja ako želite da se GRUB 2 uÄitava izravno iz MBR-a, možete to "
+#~ "napraviti ako (kao root korisnik) pokrenete sljedeću naredbu:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Instalacija GRUB-a nije uspjela. Nastaviti?"
diff --git a/debian/po/hu.po b/debian/po/hu.po
new file mode 100644
index 0000000..fa34e77
--- /dev/null
+++ b/debian/po/hu.po
@@ -0,0 +1,460 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# Dr. Nagy Elemér Károly <eknagy@omikk.bme.hu>, 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2013-05-18 15:44+0200\n"
+"Last-Translator: Dr. Nagy Elemér Károly <eknagy@omikk.bme.hu>\n"
+"Language-Team: Hungarian <debian-l10n-hungarian@lists.d.o>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: UTF-8\n"
+"Plural-Forms: ???\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Továbbtöltsünk a menu.lst-ből?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"A GRUB frissítő program észlelte, hogy régi GRUB beállítás van a /boot/grub-"
+"ban."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"A régi GRUB lecserélése érdekében javasolt, hogy a /boot/grub/menu.lst fájlt "
+"úgy módosítsuk, hogy egy GRUB2 betöltőképet töltsön be a régi GRUB. Ezt "
+"automatikusan elvégezhetjük most."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Javaslom, hogy a menu.lst-ből töltsük tovább a GRUB 2-t, és ellenőrizzük, "
+"hogy működik-e az új GRUB 2 beállítása, mielőtt az MBR-be (Master Boot "
+"Record) írnánk"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Bárhogy is döntesz most, a régi MBR képet kicserélheted a GRUB2 "
+"betöltőképével, ha rendszergazdaként (root) kiadod a következő parancsot:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB telepítési eszközök:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"A grub-pc csomagot frissítjük. Ebben a menüben kiválaszthatod, hogy melyik "
+"egységekre szeretnéd automatikusan futtatni a grub-install parancsot, ha van "
+"ilyen."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"A grub-install automatikus futtatása erősen javasolt a legtöbb esetben, mert "
+"megakadályozza, hogy a GRUB töltőkép más verziójú legyen, mint a GRUB "
+"modulok vagy a grub.cfg fájl."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ha nem vagy benne biztos, hogy melyik meghajtó van rendszerlemeznek "
+"beállítva a BIOS-ban, jó ötlet lehet mindegyikre feltelepíteni a GRUB-ot."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Megjegyzés: A GRUB-ot nemcsak lemez, de partíció rendszerbetöltő részére is "
+"lehet telepíteni, és ha van erre alkalmas partíció, azt is felkínáljuk itt. "
+"Mivel azonban így a GRUB kénytelen a blokklista módszert (blocklist) "
+"alkalmazni, amely kevésbé megbízható, így ez nem javasolt."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"A GRUB rendszerbetöltő korábban egy olyan lemezre volt telepítve, amely "
+"hiányzik vagy amelynek megváltozott az egyedi azonosítója. Fontos, hogy "
+"biztosítsuk, hogy a GRUB töltőkép ugyanolyan verziójú legyen, mint a GRUB "
+"modulok és a grub.cfg. Kérlek ellenőrizd még egyszer hogy biztosan a "
+"megfelelő eszközre írjuk a GRUB-ot."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Nem sikerül a GRUB-ot a rendszerlemezre írni - folytassuk?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Nem sikerült a GRUB-ot a következő eszközökre telepíteni:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ennek ellenére folytatni akarod? Ha folytatod, lehet, hogy a számítógéped "
+"nem fog elindulni."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Nem sikerül a GRUB-ot a rendszerlemezre írni - megpróbáljuk újra?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Megpróbálhatod egy másik eszközre telepíteni a GRUB-ot, de ehhez célszerű "
+"ellenőrizni, hogy az adott eszközről el tud-e indulni a rendszer. Egyébként "
+"a régi GRUB frissítését visszavonjuk."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB telepítése nélkül folytassuk:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Úgy döntöttél, hogy ne telepítsük a GRUB-ot egyetlen eszközre sem. Ha "
+"folytatod, lehet, hogy nem lesz jól beállítva a rendszerbetöltőd és a "
+"számítógéped következő indulásakor az fog elindulni, ami korábban a "
+"rendszerbetöltő szektorban volt. Ha ebben a GRUB 2 egy régebbi verziója van, "
+"lehet, hogy nem tudja majd betölteni a moduljait vagy nem lesz képes "
+"értelmezni a jelenlegi konfigurációs fájlt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ha már egy másik rendszerbetöltőt használsz és annál maradnál, vagy ha olyan "
+"különleges környezetben dolgozol, ahol nincs szükséged rendszerbetöltőre, "
+"folytathatod. Minden más esetben valahová telepítened kellene a GRUB-ot."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Kiszedjem a GRUB 2-t a /boot/grub-ból?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Azt szeretnéd, hogy minden GRUB 2 fájlt kiszedjek a /boot/grub-ból?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Ezzel a rendszert indulásra képtelen állapotba hozod, hacsak nem telepítesz "
+"másik rendszerbetöltőt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Befejezed most az átállást a GRUB 2-re?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ezen a rendszeren még mindig vannak a régi GRUB rendszerbetöltőhöz tartozó "
+"fájlok, de a következő lemezeken már a GRUB 2 rendszerbetöltő van telepítve:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Úgy tűnik, hogy a régi GRUB már nincs használatban és hogy jobb lenne, ha a "
+"GRUB 2 betöltőképekre frissítenénk ezeket a lemezeket és ha a régi GRUB "
+"fájlok eltávolításával befejeznénk az áttérést a GRUB 2-re. Ha nem frissíted "
+"ezeket a GRUB2 betöltőképeket, akkor inkompatibilisek lehetnek az új "
+"csomagokkal és lehet, hogy nem fog elindulni a rendszer."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Ãltalában célszerű befejezni a GRUB 2-re áttérést, kivéve ha ezek a "
+"rendszerbetöltő rekordok egy másik operációs rendszeren futó GRUB 2 "
+"telepítéssel készültek."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux parancssor:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A következő Linux parancssor az /etc/default/grub vagy a régi GRUB menu.lst "
+"fájljában lévő `kopt' paraméterből származik. Kérlek ellenőrizd, hogy helyes-"
+"e, és módosítsd, ha szükséges. A parancssor lehet üres is."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Az alapértelmezett Linux parancssor:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"A következő sort fogjuk Linux paraméternek használni az alapértelmezett "
+"(default) menüben, de a rendszervisszaállító (recovery) módban nem."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD parancssor:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A következő kFreeBSD parancssor az /etc/default/grub vagy a régi GRUB menu."
+"lst fájljában lévő `kopt' paraméterből származik. Kérlek ellenőrizd, hogy "
+"helyes-e, és módosítsd, ha szükséges. A parancssor lehet üres is."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Az alapértelmezett kFreeBSD parancssor:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"A következő sort fogjuk kFreeBSD paraméternek használni az alapértelmezett "
+"(default) menüben, de a rendszervisszaállító (recovery) módban nem."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "A /boot/grub/device.map fájlt újraépítettem."
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "A /boot/grub/device.map fájlt újraírtam, így már stabil eszköznevek "
+#~ "szerepelnek benn. A legtöbb esetben ez jelentősen csökkenti a szükséges "
+#~ "változtatások számát a jövőben, és a GRUB által készített menüpontoknak "
+#~ "ettől nem kéne megváltozniuk változniuk."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Mivel azonban egynél több lemez van a rendszervben, lehetséges, hogy a "
+#~ "rendszernek szüksége van a régi eszköztérképre. Kérelk ellenőrizd, hogy "
+#~ "van-e olyan saját készítésű rendszerbetöltő menüpontod amelyik a GRUB "
+#~ "(hdN) eszközszámozását használja, és frissítsd, ha szükséges."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ha nem érted ezt az üzenetet, vagy ha nem csináltal saját készítésű "
+#~ "rendszerbetöltő menüpontot, ne is törődj vele, lépj tovább."
diff --git a/debian/po/id.po b/debian/po/id.po
new file mode 100644
index 0000000..2d58116
--- /dev/null
+++ b/debian/po/id.po
@@ -0,0 +1,443 @@
+# Grub2 translation to Bahasa Indonesia.
+# Copyright (C) Grub2 Developer
+# This file is distributed under the same license as the Grub2 package.
+# Arief S Fitrianto <arief@gurame.fisika.ui.ac.id>, 2010.
+# Andika Triwidada <andika@gmail.com>, 2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2022-03-15 17:45+0700\n"
+"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
+"Language-Team: Debian Indonesian Translation Team <debian-l10n-id@gurame."
+"fisika.ui.ac.id>\n"
+"Language: id\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Generator: Poedit 3.0\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Chainload dari menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Skrip peningkatan GRUB telah mendeteksi setup GRUB Warisan di /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Untuk mengganti GRUB versi Warisan pada sistem Anda, sangat disarankan "
+"menyesuaikan /boot/grub/menu.lst agar memuat citra boot GRUB2 dari "
+"konfigurasi GRUB Warisan. Langkah ini sekarang dapat dilakukan secara "
+"otomatis."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Sangat disarankan Anda menerima chainloading GRUB 2 dari menu.lst, dan "
+"memastikan bahwa setup GRUB 2 yang baru bekerja sebelum Anda memasangnya "
+"pada MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Apapun pilihan Anda, Anda dapat mengganti citra MBR lama dengan GRUB 2 nanti "
+"dengan menjalankan perintah berikut sebagai root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Piranti pemasangan GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Paket grub-pc sedang ditingkatkan. Menu ini memungkinkan Anda memilih "
+"piranti yang Anda inginkan untuk menjalankan grub-install secara otomatis, "
+"bila ada."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Menjalankan grub-install secara otomatis sangat disarankan dalam kebanyakan "
+"kasus, untuk mencegah citra inti GRUB yang terpasang tidak selaras dengan "
+"modul GRUB atau grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Jika Anda tidak yakin piranti yang dijadikan piranti boot oleh BIOS, ide "
+"yang baik untuk memasang GRUB di semua piranti itu."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Catatan: sangat mungkin memasang GRUB di partisi boot dan beberapa partisi "
+"yang sesuai disajikan di sini. Tetapi, hal ini akan memaksa GRUB menggunakan "
+"mekanisme blocklist, yang membuatnya kurang handal dan oleh karenanya tidak "
+"disarankan."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Pemuat boot GRUB sebelumnya telah dipasang di harddisk yang sekarang sudah "
+"lenyap atau identifikasi unik telah berubah karena suatu hal. Sangat penting "
+"memastikan citra inti GRUB yang terpasang selalu sesuai dengan modul GRUB "
+"dan grub.cfg. Mohon periksa kembali untuk memastikan GRUB ditulis di piranti "
+"boot yang sesuai."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Gagal menulis GRUB ke piranti boot - lanjutkan?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Gagal memasang GRUB pada piranti berikut ini:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Anda yakin akan lanjut terus? Jika ya, komputer Anda mungkin tidak dapat "
+"dijalankan dengan benar."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Gagal menulis GRUB ke piranti boot - coba lagi?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Anda dapat memasang GRUB pada piranti lainnya. Tetapi, Anda harus memastikan "
+"komputer dapat boot dari piranti tersebut. Jika tidak, peningkatan dari GRUB "
+"Warisan akan dibatalkan."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Lanjutkan tanpa memasang GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Anda memilih tidak memasang GRUB di piranti apapun. Jika Anda lanjutkan, "
+"pemuat boot mungkin tidak terkonfigurasi dengan benar, dan ketika komputer "
+"ini dinyalakan kembali, maka apapun yang sebelumnya ada di bootsector akan "
+"digunakan. Jika ada versi lebih lama GRUB 2 di bootsector, mungkin tidak "
+"dapat memuat modul-modul atau menangani berkas konfigurasi mutakhir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Jika Anda telah menggunakan pemuat boot yang berbeda dan ingin tetap seperti "
+"itu, atau ada kebutuhan khusus yang membuat Anda tidak memerlukan pemuat "
+"boot, maka Anda bisa melanjutkan terus. Jika tidak, Anda harus memasang GRUB "
+"di tempat lain."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Hapus GRUB 2 dari /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Yakinkah Anda ingin menghapus semua berkas GRUB 2 dari /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Hal ini akan membuat sistem tidak dapat boot kecuali Anda memasang pemuat "
+"boot lainnya."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Selesaikan proses konversi ke GRUB 2 sekarang?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Sistem ini masih memiliki berkas-berkas dari pemuat boot GRUB Warisan, tapi "
+"sekarang juga memiliki rekam boot GRUB 2 di piranti berikut:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Tampaknya GRUB Warisan sudah tidak terpakai, dan Anda sebaiknya memasang "
+"citra GRUB 2 pada harddisk ini, lalu menyelesaikan proses konversi ke GRUB 2 "
+"dengan menghapus berkas-berkas GRUB Warisan. Jika Anda tidak memutakhirkan "
+"citra GRUB 2, maka mungkin akan ada masalah inkompatibilitas dengan paket-"
+"paket baru dan membuat sistem Anda tidak dapat boot dengan benar."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Anda sebaiknya menyelesaikan konversi ke GRUB 2 kecuali jika rekam boot ini "
+"dibuat melalui pemasangan GRUB 2 pada sistem operasi lain."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Baris perintah Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Baris perintah Linux berikut ini disadur dari /etc/default/grub atau "
+"parameter 'kopt' di menu.lst pada GRUB Warisan. Pastikan kebenarannya dan "
+"suntinglah bila perlu. Baris perintahnya diperbolehkan kosong."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Baris perintah baku Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"String berikut ini akan digunakan sebagai parameter Linux untuk menu baku "
+"tetapi tidak digunakan untuk modus pemulihan."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Paksakan instalasi ekstra ke path media lepasan EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Beberapa sistem berbasis EFI memiliki bug dan tidak menangani bootloader "
+"baru dengan benar. Jika Anda memaksa instalasi tambahan GRUB ke path media "
+"lepasan EFI, ini harus memastikan bahwa sistem ini akan mem-boot Debian "
+"dengan benar meskipun ada masalah seperti itu. Namun, itu dapat "
+"menghilangkan kemampuan untuk mem-boot sistem operasi lain yang juga "
+"bergantung pada path ini. Jika demikian, Anda perlu memastikan bahwa GRUB "
+"dikonfigurasi dengan sukses untuk dapat mem-boot instalasi OS lainnya dengan "
+"benar."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Perbarui variabel NVRAM untuk boot secara otomatis ke Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB dapat mengonfigurasi variabel NVRAM platform Anda sehingga boot ke "
+"Debian secara otomatis saat dinyalakan. Namun, Anda mungkin lebih suka "
+"menonaktifkan perilaku ini dan menghindari perubahan pada konfigurasi boot "
+"Anda. Misalnya, jika variabel NVRAM Anda telah diatur sedemikian rupa "
+"sehingga sistem Anda menghubungi server PXE pada setiap boot, ini akan "
+"mempertahankan perilaku itu."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Baris perintah kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Baris perintah kFreeBSD berikut ini disadur dari /etc/default/grub atau "
+"parameter 'kopt' di menu.lst pada GRUB Warisan. Pastikan kebenarannya dan "
+"suntinglah bila perlu. Baris perintahnya diperbolehkan kosong."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Baris perintah baku kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"String berikut ini digunakan sebagai parameter kFreeBSD untuk menu baku, "
+"tetapi tidak digunakan untuk modus pemulihan."
diff --git a/debian/po/is.po b/debian/po/is.po
new file mode 100644
index 0000000..c46b925
--- /dev/null
+++ b/debian/po/is.po
@@ -0,0 +1,466 @@
+# translation of grub_debian_po_is.po to Icelandic
+# Copyright (C) 2010 Free Software Foundation
+# This file is distributed under the same license as the GRUB package.
+#
+# Sveinn í Felli <sveinki@nett.is>, 2010, 2011, 2012, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub_debian_po_is\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2014-12-13 23:20+0000\n"
+"Last-Translator: Sveinn í Felli <sv1@fellsnet.is>\n"
+"Language-Team: Icelandic <translation-team-is@lists.sourceforge.net>\n"
+"Language: is\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+">\n"
+"X-Generator: Lokalize 1.5\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Raðhlaða (chainload) úr menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Uppfærsluskriftur GRUB hafa fundið eldri uppsetningu GRUB í /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Til að skipta eldri uppsetningu GRUB út af kerfinu, þá er mælt með því að /"
+"boot/grub/menu.lst sé stillt til að raðhlaða (chainload) GRUB 2 ræsidiskmynd "
+"frá þessari eldri uppsetningu á GRUB. Hægt er að framkvæma þetta skref "
+"sjálfvirkt núna."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Mælt með því að þú samþykkir að raðhlaða GRUB 2 úr menu.lst, auk þess að þú "
+"skoðir hvort nýja GRUB 2 uppsetningin virki fyrir þig, áður en þetta er "
+"skrifað á MBR ræsigeirann (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Hvað svosem þú ákveður, þá getur þú síðar skipt gömlu MBR myndinni út fyrir "
+"GRUB2 með því að gefa eftirfarandi skipun (sem kerfisstjóri/root):"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB uppsetningartæki:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Verið er að uppfæra grub-pc pakkann. Þessi valmynd gerir þér kleift að velja "
+"af hvaða tækjum hægt er að keyra grub-install sjálfvirkt, ef þá nokkrum."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Mælt er með í flestum tilfellum að keyra grub-install sjálfvirkt, til þess "
+"að koma í veg fyrir að uppsetta GRUB aðalmyndin hætti að vera samstillt við "
+"GRUB-einingar eða grub.cfg stilliskrána."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ef þú ert ekki viss um hvaða diskur er skilgreindur sem ræsidrif í BIOS, þá "
+"er oft góð hugmynd að setja GRUB upp á alla diskana."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Athugasemd: Það er líka hægt að setja GRUB upp á ræsigeira disksneiða, hér "
+"eru nokkrar viðeigandi disksneiðar í boði. à móti kemur að þetta þvingar "
+"GRUB til að nota blokklista (blocklist mechanism), sem gerir GRUB ekki eins "
+"áreiðanlegt; því er ekki mælt með þessu."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB ræsistjórinn vað áður uppsettur á disk sem ekki er lengur til staðar "
+"eða sem hefur af einhverjum ástæðum fengið nýtt auðkenni/tilvísun. Það er "
+"mikilvægt að ganga úr skugga um að uppsetta GRUB aðalmyndin sé samstillt við "
+"GRUB-einingar og grub.cfg stilliskrána.. Athugaðu aftur hvort GRUB sé "
+"skrifað á viðeigandi ræsitæki."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Uppsetning GRUB á ræsitæki mistókst. Halda áfram?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Uppsetning GRUB mistókst á eftirfarandi tækjum:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Viltu samt halda áfram? Ef þú gerir það er ekki víst að tölvan þín ræsist "
+"aftur eðlilega."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Uppsetning GRUB á ræsitæki mistókst. Reyna aftur?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Þú gætir hugsanlega sett GRUB upp á eitthvað annað tæki, samt ættirðu að "
+"skoða vel hvort kerfið þitt sé fært um að ræsa upp af því tæki. Að öðrum "
+"kosti verður hætt við uppfærslu gamla GRUB ræsistjórans."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Halda áfram án þess að setja upp GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Þú valdir að setja GRUB ekki upp á neitt tæki. Ef þú heldur áfram verður "
+"ræsistjórinn ekki rétt stilltur, og þegar tölvan þín ræsist næst mun hún "
+"nota hvað það sem fyrir er núna á ræsigeiranum. Ef á ræsigeiranum er til "
+"dæmis eldri útgáfa af GRUB 2, er möguleiki á að hún ráði ekki við að hlaða "
+"inn ákveðnum kjarnaeiningum eða nái ekki að lesa stillingaskrána fyrir þetta "
+"stýrikerfi."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ef þú ert þegar að nota einhvern annan ræsistjóra og ætlar að halda því "
+"áfram, eða ef þetta er eitthvað sérhannað kerfi sem ekki þarfnast "
+"ræsistjóra; þá ættirðu að halda samt áfram. Ef ekki, ættirðu að setja GRUB "
+"upp einhversstaðar."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Fjarlægja GRUB 2 úr /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Viltu láta fjarlægja allar GRUB 2 skrár úr /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Þetta mun gera kerfið óræsanlegt nema einhver annar ræsistjóri sé settur upp."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Ljúka núna umbreytingu í GRUB 2 ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Þetta kerfi er ennþá með uppsettar skrár frá eldri uppsetningu GRUB, en er "
+"núna einnig með GRUB 2 ræsifærslur uppsettar á þessum diskum:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Það lítur út fyrir að eldra GRUB sé ekki lengur í notkun og að þú ættir þá "
+"að uppfæra GRUB 2 myndirnar á þessum diskum og ljúka svo yfirfærslunni í "
+"GRUB 2 með því að fjarlægja gömlu GRUB skrárnar. Ef þú uppfærir ekki þessar "
+"GRUB 2 myndir gætu þær orðið ósamhæfðar við nýju pakkana og koma í veg fyrir "
+"að kerfið ræsist eðlilega."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Almennt ættirðu að ljúka umbreytingu í GRUB 2 nema ef þessar ræsifærslur "
+"hafi verið útbúnar af GRUB 2 uppsetningu í einhverju öðru stýrikerfi."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux skipanalína:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Eftirfarandi Linux skipanalína fannst í /etc/default/grub eða í `kopt' "
+"viðfanginu í eldri GRUB menu.lst. Gakktu úr skugga um að þetta sé rétt og "
+"breyttu því ef það er nauðsynlegt. Skipanalínan má vera auð."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Sjálfgefin Linux skipanalína:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Eftirfarandi strengur verður notaður sem Linux viðfang í sjálfgefnu "
+"valmyndarfærslunni en ekki í viðgerðarham."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Þvinga aukauppsetningu inn á EFI-slóðina fyrir útskiptanlega miðla?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Sum EFI-kerfi eru ekki villulaus og meðhöndla nýja ræsistjóra (bootloaders) "
+"ekki rétt. Ef þú þvingar aukauppsetningu af GRUB inn á EFI-slóðina fyrir "
+"útskiptanlega miðla, ætti það að tryggja að Debian ræsist rétt þrátt fyrir "
+"slíka galla. Hinsvegar, þetta gæti líka skemmt hæfnina til að ræsa önnur "
+"stýrikerfi sem einnig eru háð notkun á þessari slóð. Ef sú er raunin, þá "
+"verður þú að ganga úr skugga um að GRUB sé sett upp á fullnægjandi máta til "
+"þess að geta ræst rétt öll önnur stýrikerfi."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD skipanalína:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Eftirfarandi kFreeBSD skipanalína fannst í /etc/default/grub eða í `kopt' "
+"viðfanginu í eldri GRUB menu.lst. Gakktu úr skugga um að þetta sé rétt og "
+"breyttu því ef það er nauðsynlegt. Skipanalínan má vera auð."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Sjálfgefin kFreeBSD skipanalína:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Eftirfarandi strengur verður notaður sem kFreeBSD viðfang í sjálfgefnu "
+"valmyndarfærslunni en ekki í viðgerðarham."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map var endurskrifað"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Skráin /boot/grub/device.map hefur verið endurskrifuð til að nota föst "
+#~ "tækjaheiti. à flestum tilfellum þýðir þetta að færri ástæður geta komið "
+#~ "upp til að breyta þeim í framtíðinni og að færslur í GRUB ræsivalmyndinni "
+#~ "ættu síður að verða fyrir breytingum."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Aftur á móti, þar sem fleiri en einn diskur eru til staðar í kerfinu, þá "
+#~ "er alveg hugsanlegt að kerfið reiði sig á gömlu tækjaskrána (device map). "
+#~ "Athugaðu hvort það séu einhverjar sérsniðnar ræsifærslur sem nota eldri "
+#~ "GRUB (hdN) diskaskilgreiningar, og uppfærðu þær þá ef nauðsyn krefur."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ef þú skilur ekki þessi skilaboð, eða ef þú hefur engar sérsniðnar "
+#~ "ræsifærslur, þá geturðu hunsað skilaboðin."
diff --git a/debian/po/it.po b/debian/po/it.po
new file mode 100644
index 0000000..5f771f4
--- /dev/null
+++ b/debian/po/it.po
@@ -0,0 +1,491 @@
+# Italian (it) translation of debconf templates for grub2
+# This file is distributed under the same license as the grub2 package.
+# Luca Monducci <luca.mo@tiscali.it>, 2007-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.02~beta3-4 italian debconf templates\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-29 21:20+0200\n"
+"Last-Translator: Luca Monducci <luca.mo@tiscali.it>\n"
+"Language-Team: Italian <debian-l10n-italian@lists.debian.org>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Effettuare il caricamento in cascata da menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Gli script di aggiornamento hanno rilevato una installazione di GRUB Legacy "
+"in /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Per sostituire la versione Legacy di GRUB sul proprio sistema si raccomanda "
+"di modificare il file /boot/grub/menu.lst in modo da caricare l'immagine di "
+"avvio di GRUB 2 dall'attuale installazione di GRUB Legacy. Questa modifica "
+"può essere effettuata automaticamente adesso."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Si raccomanda di accettare il caricamento in cascata di GRUB 2 da menu.lst e "
+"di verificare che la nuova installazione di GRUB 2 funzioni prima di "
+"procedere con l'installazione diretta sul MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Qualsiasi sia la decisione, in seguito sarà possibile sostituire la vecchia "
+"immagine sul MBR con GRUB 2 eseguendo da root il seguente comando:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Installare GRUB sui device:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"È in corso l'aggiornamento del pacchetto grub-pc. Questo menu permette di "
+"scegliere su quali device, se specificati, si vuole eseguire automaticamente "
+"grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Nella maggioranza dei casi si raccomanda l'esecuzione automatica di grub-"
+"install in modo da prevenire la perdita di sincronia dell'immagine "
+"principale di GRUB con i moduli di GRUB o con grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Se non si è sicuri di quale sia il disco impostato come disco di avvio nel "
+"BIOS, è consigliabile installare GRUB su tutti i device."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: è possibile installare GRUB anche nei boot record delle partizioni e "
+"qui sono elencate alcune partizioni appropriate. Però questo obbliga GRUB a "
+"usare il meccanismo del \"blocklist\", che lo rende meno affidabile e di "
+"conseguenza non è raccomandato."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"In precedenza il boot loader GRUB era installato su un disco non più "
+"presente o che per qualche motivo ha cambiato identificatore univoco. È "
+"importante assicurare che l'immagine principale di GRUB rimanga in sincronia "
+"con i moduli di GRUB e con grub.cfg. Controllare nuovamente per essere "
+"sicuri che GRUB sia scritto sui corretti device di avvio."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Scrittura di GRUB sul device di avvio non riuscita. Continuare?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "L'installazione di GRUB sui seguenti device non è riuscita:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Si vuole continuare? Continuando, il computer potrebbe non avviarsi più "
+"correttamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Scrittura di GRUB sul device di avvio non riuscita. Riprovare?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"È possibile installare GRUB su un altro device, dopo aver verificato che il "
+"proprio sistema si possa avviare da quel device. Altrimenti, l'aggiornamento "
+"da GRUB Legacy verrà annullato."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Continuare senza installare GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Si è scelto di non installare GRUB su alcun device. Continuando, il boot "
+"loader potrebbe non essere configurato correttamente e al prossimo avvio del "
+"computer verrà usato il vecchio contenuto del settore di boot. Se nel "
+"settore di boot è presente una versione precedente di GRUB 2, questa "
+"potrebbe non essere in grado di caricare i moduli o di gestire l'attuale "
+"file di configurazione."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Continuare solo se già si usa un boot loader diverso oppure se non si ha "
+"necessità di un boot loader per questa macchina. Altrimenti è necessario "
+"installare GRUB da qualche parte."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Rimuovere GRUB 2 da /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Rimuovere tutti i file di GRUB 2 da /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Questo potrebbe rendere il sistema non avviabile a meno che non sia "
+"installato un altro boot loader."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Completare la conversione a GRUB 2 adesso?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Su questo sistema sono ancora presenti i file del boot loader GRUB Legacy ma "
+"adesso sui seguenti dischi sono installati anche i boot record di GRUB 2:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Sembra che GRUB Legacy non sia più usato, per cui è consigliabile aggiornare "
+"le immagini sui dischi con GRUB 2 e completare la conversione a GRUB 2 "
+"eliminando i vecchi file di GRUB Legacy. Se non si aggiornano le immagini "
+"con GRUB 2, in futuro potrebbero non essere più compatibili con i nuovi "
+"pacchetti e potrebbero impedire il corretto avvio del sistema."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Si dovrebbe completare la conversione a GRUB 2 a meno che i boot record non "
+"siano stati creati da un'altra installazione di GRUB 2 su un altro sistema "
+"operativo."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Riga di comando Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La seguente riga di comando Linux è stata estratta da /etc/default/grub "
+"oppure dal parametro \"kopt\" presente nel file menu.lst di GRUB Legacy. "
+"Controllare che sia corretta e modificarla se necessario. La riga di comando "
+"può essere vuota."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Riga di comando Linux predefinita:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Questa stringa verrà usata come parametri per Linux nella voce di menu "
+"predefinita, ma non nella modalità di ripristino."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Forzare l'installazione sul percorso dei supporti removibili EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Alcuni sistemi EFI hanno degli errori e non gestiscono correttamente i nuovi "
+"bootloader. Forzando un'installazione aggiuntiva di GRUB sul percorso dei "
+"supporti removibili, si garantisce che il sistema avvierà Debian nonostante "
+"questo tipo di problemi. Tuttavia ciò potrebbe impedire l'avvio di qualsiasi "
+"altro sistema operativo che dipende dallo stesso percorso; in tal caso "
+"occorre accertarsi che GRUB sia configurato in modo che possa avviare "
+"correttamente qualsiasi altro SO installato."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Aggiornare le variabili NVRAM per avviare automaticamente Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB può configurare le variabili NVRAM della propria piattaforma in modo da "
+"avviare automaticamente Debian all'accensione. Tuttavia, si potrebbe non "
+"volere questo comportamento ed evitare modifiche alla propria configurazione "
+"d'avvio. Per esempio, se le variabili NVRAM sono state impostate in modo che "
+"il sistema contatti un server PXE a ogni avvio, è possibile preservare tale "
+"impostazione."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr "Eseguire automaticamente os-prober per rilevare e avviare altri OS?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB può usare il programma os-prober per provare a individuare altri "
+"sistemi operativi presenti sul computer e aggiungerli automaticamente "
+"all'elenco delle scelte all'avvio."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Se sul proprio computer sono installati più sistemi operativi, probabilmente "
+"questo è ciò che si desidera. Tuttavia, se il computer fa da host per più SO "
+"ospiti installati tramite device LVM o dischi raw, l'uso di os-prober "
+"potrebbe danneggiare i SO ospiti dato che per fare la ricerca monta i "
+"filesystem."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Riga di comando kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"La seguente riga di comando kFreeBSD è stata estratta da /etc/default/grub "
+"oppure dal parametro \"kopt\" presente nel file menu.lst di GRUB Legacy. "
+"Controllare che sia corretta e modificarla se necessario. La riga di comando "
+"può essere vuota."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Riga di comando kFreeBSD predefinita:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Questa stringa verrà usata come parametri per kFreeBSD nella voce di menu "
+"predefinita, ma non nella modalità di ripristino."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map è stato rigenerato"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Il file /boot/grub/device.map è stato riscritto in modo da usare i nomi "
+#~ "stabili dei device. In molti casi questo dovrebbe ridurre in modo "
+#~ "significativo la necessità di cambiarli in futuro e le voci nel menu di "
+#~ "GRUB non dovrebbero essere influenzate."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Tuttavia, visto che sul sistema ci sono più dischi, è possibile che il "
+#~ "sistema sia dipendente dalla vecchia mappa dei device. Controllare se nel "
+#~ "menu di GRUB ci sono delle voci personalizzate che usano la numerazione "
+#~ "dei dischi di GRUB (hdN) e, se necessario, aggiornarle."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Se non si capisce questo messaggio oppure se non ci sono voci di menu "
+#~ "personalizzate, ignorare questo messaggio."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "In ogni caso, per caricare GRUB 2 direttamente dal MBR, è necessario "
+#~ "eseguire (da root) il seguente comando:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Installazione di GRUB non riuscita. Continuare?"
diff --git a/debian/po/ja.po b/debian/po/ja.po
new file mode 100644
index 0000000..1084472
--- /dev/null
+++ b/debian/po/ja.po
@@ -0,0 +1,464 @@
+# Copyright (C) 2008-2010 GRUB Maintainers <pkg-grub-devel@lists.alioth.debian.org>
+# This file is distributed under the same license as the grub2 package.
+# Hideki Yamane <henrich@debian.or.jp>, <henrich@debian.org>, 2008-2011.
+# Takuma Yamada <tyamada@takumayamada.com>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 1.99-5\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2016-03-03 09:57+0900\n"
+"Last-Translator: Takuma Yamada <tyamada@takumayamada.com>\n"
+"Language-Team: Japanese <debian-japanese@lists.debian.org>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Gtranslator 2.91.6\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst 経由ã§èµ·å‹• (ãƒã‚§ãƒ¼ãƒ³ãƒ­ãƒ¼ãƒ‰) ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB ã®ã‚¢ãƒƒãƒ—グレードプログラムã¯ã€/boot/grub ã« GRUB Legacy ã®è¨­å®šãŒã‚ã‚‹ã®ã‚’"
+"検出ã—ã¾ã—ãŸã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"システム中ã«å­˜åœ¨ã—ã¦ã„ã‚‹å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® GRUB ã‚’ç½®ãæ›ãˆã‚‹ã«ã¯ã€/boot/grub/"
+"menu.lst ã«ã‚ã‚‹ GRUB Legacy ã®è¨­å®šã‚’使ã£ã¦ GRUB2 ã®èµ·å‹•ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’読ã¿è¾¼ã‚€ã‚ˆã†"
+"ã«è¨­å®šã™ã‚‹ã®ãŒãŠå‹§ã‚ã§ã™ã€‚ã“ã®ä½œæ¥­ã¯ã“ã“ã§è‡ªå‹•çš„ã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"MBR (マスターブートレコード) ã«ç›´æŽ¥ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å‰ã«ã€GRUB 2 ㌠menu.lst "
+"ã‹ã‚‰ãƒã‚§ãƒ¼ãƒ³ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã‚ˆã†ã«è¨­å®šã—ã€æ–°ã—ã„ GRUB 2 ã®è¨­å®šãŒå‹•ä½œã™ã‚‹ã‹ã©ã†ã‹ã‚’"
+"確èªã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"ã©ã®è¨­å®šã‚’é¸ã¶ã«ã›ã‚ˆã€root ã¨ã—ã¦ä»¥ä¸‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€å¾Œã‹ã‚‰"
+"ã§ã‚‚å¤ã„ MBR イメージを GRUB 2 ã«ç½®ãæ›ãˆã‚‰ã‚Œã¾ã™ã€‚"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB をインストールã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc パッケージã®ã‚¢ãƒƒãƒ—グレード中ã§ã™ã€‚ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã§ã¯ã€ã‚‚ã—デãƒã‚¤ã‚¹ãŒã‚"
+"ã‚Œã°ã€ã©ã®ãƒ‡ãƒã‚¤ã‚¹ã«è‡ªå‹•çš„ã« grub-install を実行ã™ã‚‹ã‹ã‚’é¸ã¹ã¾ã™ã€‚"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"インストール済ã¿ã® GRUB コアイメージ㌠GRUB モジュールや grub.cfg ã¨ã®åŒæœŸãŒ"
+"ãšã‚Œã‚‹ã®ã‚’防ããŸã‚ã€ã»ã¨ã‚“ã©ã®å ´åˆã€è‡ªå‹•çš„ã« grub-instsall を実行ã™ã‚‹ã®ãŒãŠå‹§"
+"ã‚ã§ã™ã€‚"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"BIOS ã§ã©ã®ãƒ‰ãƒ©ã‚¤ãƒ–ãŒèµ·å‹•ãƒ‰ãƒ©ã‚¤ãƒ–ã¨ã—ã¦è¨­å®šã•ã‚Œã¦ã„ã‚‹ã®ã‹ã‚ã‹ã‚‰ãªã„ã®ã§ã‚ã‚Œ"
+"ã°ã€ã™ã¹ã¦ã« GRUB をインストールã™ã‚‹ã®ãŒãŸã„ã¦ã„ã®å ´åˆè‰¯ã„考ãˆã§ã™ã€‚"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"注æ„: パーティションブートレコード㫠GRUB をインストールã™ã‚‹ã®ã‚‚å¯èƒ½ã§ã™ã€‚ã"
+"ã—ã¦ã€ã“ã“ã§ã¯é©åˆ‡ãªãƒ‘ーティションãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã—ã‹ã—ã€ã“ã‚Œã«ã‚ˆã£ã¦ GRUB "
+"ãŒãƒ–ロックリストã®ä»•çµ„ã¿ã‚’強制的ã«ä½¿ã†ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ã“ã®ä»•çµ„ã¿ã¯ä¿¡é ¼æ€§ã«æ¬ "
+"ã‘ã‚‹ãŸã‚ã€ãŠå‹§ã‚ã¯ã—ã¾ã›ã‚“。"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"以å‰ã€GRUB ブートローダーã¯ã€ã™ã§ã«å­˜åœ¨ã—ãªã„ã€ã‚ã‚‹ã„ã¯ä½•ã‚‰ã‹ã®ç†ç”±ã§å›ºæœ‰ã®è­˜"
+"別å­ãŒå¤‰æ›´ã•ã‚ŒãŸãƒ‡ã‚£ã‚¹ã‚¯ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã—ãŸã€‚インストールã•ã‚Œã¦ã„ã‚‹ "
+"GRUB コアイメージ㌠GRUB モジュールや grub.cfg ã¨ä¸€è‡´ã—ã¦ã„ã‚‹ã®ã‚’確èªã™ã‚‹ã®ã¯"
+"é‡è¦ã§ã™ã€‚ã‚‚ã†ä¸€åº¦ã€GRUB ãŒé©åˆ‡ãªèµ·å‹•ãƒ‡ãƒã‚¤ã‚¹ã«æ›¸ãè¾¼ã¾ã‚Œã¦ã„ã‚‹ã‹ç¢ºã‹ã‚ã¦ãã "
+"ã•ã„。"
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "起動デãƒã‚¤ã‚¹ã¸ã® GRUB ã®æ›¸ãè¾¼ã¿ãŒå¤±æ•—ã—ã¾ã—㟠- 続行ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB ã¯ä»¥ä¸‹ã®ãƒ‡ãƒã‚¤ã‚¹ã¸ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸ:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"ã¨ã«ã‹ã続行ã—ã¾ã™ã‹? ãã®å ´åˆã€ã‚³ãƒ³ãƒ”ュータãŒæ­£å¸¸ã«èµ·å‹•ã—ãªã„ã‹ã‚‚ã—ã‚Œã¾ã›"
+"ん。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"ブートデãƒã‚¤ã‚¹ã¸ã® GRUB ã®æ›¸ãè¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"別ã®ãƒ‡ãƒã‚¤ã‚¹ã« GRUB をインストールã§ãã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“ãŒã€ãã®ãƒ‡ãƒã‚¤ã‚¹ã‹ã‚‰ã‚·"
+"ステムãŒèµ·å‹•ã™ã‚‹ã‹ã©ã†ã‹ã‚’確èªã—ã¦ãŠãå¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã©ã®ãƒ‡ãƒã‚¤ã‚¹ã«ã‚‚インス"
+"トールを行ã‚ãªã„å ´åˆã¯ã€GRUB Legacy ã‹ã‚‰ã®ã‚¢ãƒƒãƒ—グレードã¯ä¸­æ­¢ã•ã‚Œã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB をインストールã›ãšã«ãƒ‘ッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"ã©ã®ãƒ‡ãƒã‚¤ã‚¹ã«å¯¾ã—ã¦ã‚‚ GRUB をインストールã—ãªã„ã“ã¨ãŒé¸æŠžã•ã‚Œã¾ã—ãŸã€‚ブート"
+"ローダーãŒæ­£ã—ã設定ã•ã‚Œã¦ã„ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã€ã“ã®ã¾ã¾ç¶šè¡Œã™ã‚‹ã¨ã“ã®ã‚³ãƒ³"
+"ピュータã®æ¬¡å›žèµ·å‹•æ™‚ã«ã¯ã€ä»¥å‰ã«èµ·å‹•ã‚»ã‚¯ã‚¿ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ãŸã‚‚ã®ã‚’何ã§"
+"ã‚ã‚ã†ã¨ã‚‚利用ã—よã†ã¨ã—ã¾ã™ã€‚以å‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® GRUB 2 ãŒèµ·å‹•ã‚»ã‚¯ã‚¿ã«ã‚ã‚‹å ´"
+"åˆã¯ã€ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®èª­ã¿è¾¼ã¿ã‚„ç¾åœ¨ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã®å–り扱ã„ãŒã§ããªããªã‚‹å¯èƒ½æ€§"
+"ãŒã‚ã‚Šã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ã™ã§ã«åˆ¥ã®ãƒ–ートローダーを利用ã—ã¦ã„ã¦ãれを使ã„続ã‘ãŸã„å ´åˆã€ã‚ã‚‹ã„ã¯ãƒ–ート"
+"ローダーを必è¦ã¨ã—ãªã„特殊ãªç’°å¢ƒã®å ´åˆã¯ã€ã¨ã«ã‹ã続行ã—ã¦ã—ã¾ã£ã¦æ§‹ã„ã¾ã›"
+"ん。ãã†ã§ãªã„å ´åˆã¯ã€ã©ã“ã‹ã« GRUB をインストールã—ã¦ãã ã•ã„。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "/boot/grub ã‹ã‚‰ GRUB 2 を削除ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "/boot/grub ã‹ã‚‰ GRUB 2 ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"ã“ã®ä½œæ¥­ã¯ã€åˆ¥ã®ãƒ–ートローダーãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ãªã„ã¨ã‚·ã‚¹ãƒ†ãƒ ãŒèµ·å‹•ã§ã"
+"ãªããªã‚Šã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "ã“ã“㧠GRUB 2 ã¸ã®ã‚³ãƒ³ãƒãƒ¼ãƒˆã‚’終了ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ GRUB Legacy ã®ãƒ–ートローダーãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚Š"
+"ã¾ã™ãŒã€GRUB 2 ã®ãƒ–ートレコードも以下ã®ãƒ‡ã‚£ã‚¹ã‚¯ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã¾ã™:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"GRUB Legacy ã¯ã‚‚ã¯ã‚„使ã‚ã‚Œã¦ã¯ã„ãªã„よã†ãªã®ã§ã€ä»£ã‚ã‚Šã«ã“れらã®ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã® "
+"GRUB 2 イメージをアップグレードã—ã¦ã€å¤ã„ GRUB Legacy ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’削除ã™ã‚‹ã“"
+"ã¨ã§ GRUB 2 ã¸ã®ã‚³ãƒ³ãƒãƒ¼ãƒˆã‚’完了ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“れら㮠GRUB 2 イメージ"
+"をアップグレードã—ã¦ã„ãªã„å ´åˆã¯ã€æ–°ã—ã„パッケージã¨ã®äº’æ›æ€§ãŒãªã„ãŸã‚ã«ã‚·ã‚¹"
+"テムãŒæ­£å¸¸ã«èµ·å‹•ã—ãªã„å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"ä»–ã® OS 上ã§ã® GRUB 2 ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¦ã„ãŸãƒ–ートレコードを除"
+"ãã€GRUB 2 ã¸ã®ã‚³ãƒ³ãƒãƒ¼ãƒˆã¯ã»ã¼å®Œäº†ã—ã¾ã—ãŸã€‚"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux コマンドライン:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"以下㮠Linux ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã¯ /etc/default/grub ã‹ GRUB Legacy ã® menu.lst "
+"上ã®ã€Œkoptã€ãƒ‘ラメータã‹ã‚‰å–å¾—ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã‚ŒãŒæ­£ã—ã„ã‚‚ã®ã§ã‚ã‚‹ã‹ã‚’確èªã—"
+"ã¦ã€å¿…è¦ã§ã‚ã‚Œã°ä¿®æ­£ã—ã¦ãã ã•ã„。コマンドラインã¯ç©ºã§ã‚‚構ã„ã¾ã›ã‚“。"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux デフォルトコマンドライン:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"以下ã®æ–‡å­—列ã¯ã€ãƒªã‚«ãƒãƒªãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯ãªã„通常ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚¨ãƒ³ãƒˆãƒªã§ã® Linux パラ"
+"メータã¨ã—ã¦ä½¿ã‚ã‚Œã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "EFI リムーãƒãƒ–ルメディアパスã«ç‰¹åˆ¥ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’強制ã—ã¾ã™ã‹?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"一部㮠EFI ベースã®ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ãƒã‚°ãŒã‚ã‚Šã€æ­£ã—ãæ–°ã—ã„ブートローダーを扱ã†ã“"
+"ã¨ãŒã§ãã¾ã›ã‚“。EFI リムーãƒãƒ–ルメディアパス㫠GRUB ã®ç‰¹åˆ¥ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’強制"
+"ã™ã‚‹ã¨ã€ã“ã®å•é¡Œã«ã‚‚ã‹ã‹ã‚らãšã€ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã§æ­£å¸¸ã« Debian ãŒèµ·å‹•ã™ã‚‹ã§ã—ょ"
+"ã†ã€‚ã—ã‹ã—ã€ãã‚Œã¯ã¾ãŸã€ã“ã®ãƒ‘スã«ä¾å­˜ã™ã‚‹ã™ã¹ã¦ã®ã»ã‹ã®ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹"
+"テムを起動ã™ã‚‹æ©Ÿèƒ½ã‚’削除ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ãã®å ´åˆã¯ã€ã»ã‹ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•"
+"れ㟠OS ãŒæ­£å¸¸ã«èµ·å‹•ã™ã‚‹ã‚ˆã† GRUB ã‚’é©åˆ‡ã«è¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD コマンドライン:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"以下㮠kFreeBSD ã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã¯ã€/etc/default/grub ã‹ GRUB Legacy ã® menu."
+"lst 上ã®ã€Œkoptã€ãƒ‘ラメータã‹ã‚‰å–å¾—ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã‚ŒãŒæ­£ã—ã„ã‚‚ã®ã§ã‚ã‚‹ã‹ã‚’確"
+"èªã—ã¦ã€å¿…è¦ã§ã‚ã‚Œã°ä¿®æ­£ã—ã¦ãã ã•ã„。コマンドラインã¯ç©ºã§ã‚‚構ã„ã¾ã›ã‚“。"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD デフォルトコマンドライン:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"以下ã®æ–‡å­—列ã¯ãƒªã‚«ãƒãƒªãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§ã¯ãªã„通常ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚¨ãƒ³ãƒˆãƒªã§ã® kFreeBSD パ"
+"ラメータã¨ã—ã¦ä½¿ã‚ã‚Œã¾ã™ã€‚"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map ãŒå†ç”Ÿæˆã•ã‚Œã¾ã—ãŸ"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "/boot/grub/device.map ファイルã¯å›ºå®šã®ãƒ‡ãƒã‚¤ã‚¹åを使ã†ã‚ˆã†ã«æ›¸ãæ›ãˆã‚‰ã‚Œã¾"
+#~ "ã—ãŸã€‚多ãã®å ´åˆã¯ã€ä»Šå¾Œã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’変更ã™ã‚‹å¿…è¦ãŒå¤§å¹…ã«æ¸›ã£ã¦ãŠã‚Šã€"
+#~ "GRUB ã«ã‚ˆã£ã¦ç”Ÿæˆã•ã‚Œã‚‹èµ·å‹•ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®é …ç›®ã¯å½±éŸ¿ã‚’å—ã‘ãªã„ã¯ãšã§ã™ã€‚"
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "ã—ã‹ã—ã€ã‚·ã‚¹ãƒ†ãƒ ã« 2 個以上ディスクãŒã‚ã‚‹ã®ã§ã€èµ·å‹•ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®é …ç›®ãŒå¤ã„デ"
+#~ "ãƒã‚¤ã‚¹æƒ…å ±ã«ä¾å­˜ã—ã¦ã„ãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚起動メニューã®é …目㌠GRUB ã§ã®ãƒ‰"
+#~ "ライブã®é †ç•ª (hdN) ã«é–¢é€£ã—ã¦ã„ãªã„ã‹ã©ã†ã‹ã‚’確èªã—ã¦ã€å¿…è¦ã§ã‚ã‚Œã°æ›´æ–°ã—"
+#~ "ã¦ãã ã•ã„。"
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®æ„味ãŒã‚ã‹ã‚‰ãªã„ã€ã‚ã‚‹ã„ã¯å¤‰æ›´ã—ãŸèµ·å‹•ãƒ¡ãƒ‹ãƒ¥ãƒ¼é …ç›®ãŒãªã„å ´"
+#~ "åˆã¯ã€ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’無視ã—ã¦æ§‹ã„ã¾ã›ã‚“。"
diff --git a/debian/po/ka.po b/debian/po/ka.po
new file mode 100644
index 0000000..84b3c79
--- /dev/null
+++ b/debian/po/ka.po
@@ -0,0 +1,413 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2009-08-30 18:05+0400\n"
+"Last-Translator: Aiet Kolkhi <aietkolkhi@gmail.com>\n"
+"Language-Team: Georgian <aiet@gakartuleba.org>\n"
+"Language: ka\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: georgian\n"
+"X-Poedit-Country: GEORGIA\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "გსურთ Chainload ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვრmenu.lst-დáƒáƒœ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB-ის გáƒáƒœáƒáƒ®áƒšáƒ”ბის სკრიფტები GRUB-ის ძველ ინსტáƒáƒšáƒáƒªáƒ˜áƒáƒ¡ გáƒáƒ“áƒáƒáƒ¬áƒ§áƒ“რ/boot/grub "
+"მდებáƒáƒ áƒ”áƒáƒ‘áƒáƒ¨áƒ˜."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+#, fuzzy
+#| msgid ""
+#| "In order to replace the Legacy version of GRUB in your system, it is "
+#| "recommended that /boot/grub/menu.lst is adjusted to chainload GRUB 2 from "
+#| "your existing GRUB Legacy setup. This step may be automaticaly performed "
+#| "now."
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"იმისáƒáƒ—ვის, რáƒáƒ› თქვენს სისტემáƒáƒ–ე ჩáƒáƒœáƒáƒªáƒ•áƒšáƒ“ეს ძველი GRUB-ის ინსტáƒáƒšáƒáƒªáƒ˜áƒ, "
+"სáƒáƒ¡áƒ£áƒ áƒ•áƒ”ლირ/boot/grub/menu.lst ჩáƒáƒ¡áƒ¬áƒáƒ áƒ“ეს, რáƒáƒ› შეáƒáƒ¡áƒ áƒ£áƒšáƒáƒ¡ GRUB 2-ის chainload "
+"ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვრთქვენი áƒáƒ áƒ¡áƒ”ბული GRUB-ის ძველი ინსტáƒáƒšáƒáƒªáƒ˜áƒ˜áƒ“áƒáƒœ. ეს სáƒáƒ¤áƒ”ხური "
+"შესáƒáƒ«áƒšáƒ”ბელირáƒáƒ®áƒšáƒ შესრულდეს áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+#, fuzzy
+#| msgid ""
+#| "It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+#| "verify that your new GRUB 2 setup is functional for you, before you "
+#| "install it directly to your MBR (Master Boot Record)."
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"სáƒáƒ¡áƒ£áƒ áƒ•áƒ”ლირმიიღáƒáƒ— menu.lst-დáƒáƒœ GRUB 2-ის chainload მეთáƒáƒ“ით ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ, áƒáƒ¡áƒ”ვე "
+"გáƒáƒ“áƒáƒáƒ›áƒáƒ¬áƒ›áƒáƒ—, რáƒáƒ› თქვენი áƒáƒ®áƒáƒšáƒ˜ GRUB 2-ის ინსტáƒáƒšáƒáƒªáƒ˜áƒ ფუნქციáƒáƒœáƒ˜áƒ áƒ”ბდეს, სáƒáƒœáƒáƒ› "
+"მáƒáƒ¡ პირდáƒáƒžáƒ˜áƒ  Master Boot Record (MBR)-ში ჩáƒáƒ¬áƒ”რდეთ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr ""
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "ლინუქსის ბრძáƒáƒœáƒ”ბის სტრიქáƒáƒœáƒ˜:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+#, fuzzy
+#| msgid ""
+#| "The following Linux command line was extracted from /etc/default/grub or "
+#| "the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+#| "correct, and modify it if necessary."
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ლინუქსის შემდეგი ბრძáƒáƒœáƒ”ბრმáƒáƒ«áƒ˜áƒ”ბულ იქნრ/etc/default/grub-დáƒáƒœ áƒáƒœ `kopt' "
+"პáƒáƒ áƒáƒ›áƒ”ტრიდáƒáƒœ ძველი GRUB-ის menu.lst-ში. გáƒáƒ“áƒáƒáƒ›áƒáƒ¬áƒ›áƒ”თ, რáƒáƒ› იგი სწáƒáƒ áƒ˜áƒ, áƒáƒœ "
+"შეცვáƒáƒšáƒ”თ შესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒáƒ“."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "ლინუქსის სტáƒáƒœáƒ“áƒáƒ áƒ¢áƒ£áƒšáƒ˜ ბრძáƒáƒœáƒ”ბის სტრიქáƒáƒœáƒ˜:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"შემდეგი სტრიქáƒáƒœáƒ˜ გáƒáƒ›áƒáƒ§áƒ”ნებულ იქნებრრáƒáƒ’áƒáƒ áƒª ლინუქსის პáƒáƒ áƒáƒ›áƒ”ტრები მენიუს "
+"სტáƒáƒœáƒ“áƒáƒ áƒ¢áƒ£áƒšáƒ˜ შენáƒáƒ¢áƒáƒœáƒ˜áƒ¡áƒáƒ—ვის, მáƒáƒ’რáƒáƒ› áƒáƒ áƒ áƒáƒ¦áƒ“გენის რეჟიმისáƒáƒ—ვის."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD ბრძáƒáƒœáƒ”ბის სტრიქáƒáƒœáƒ˜:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+#, fuzzy
+#| msgid ""
+#| "The following kFreeBSD command line was extracted from /etc/default/grub "
+#| "or the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it "
+#| "is correct, and modify it if necessary."
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"შემდეგი kFreeBSD-ის ბრძáƒáƒœáƒ”ბის სტრიქáƒáƒœáƒ˜ áƒáƒ›áƒáƒ¦áƒ”ბულ იქნრ/etc/default/grub-დáƒáƒœ "
+"áƒáƒœ `kopt' პáƒáƒ áƒáƒ›áƒ”ტრიდáƒáƒœ ძველი GRUB-ის menu.lst-ში. გáƒáƒ“áƒáƒáƒ›áƒáƒ¬áƒ›áƒ”თ, რáƒáƒ› იგი "
+"სწáƒáƒ áƒ˜áƒ, áƒáƒœ შეცვáƒáƒšáƒ”თ შესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒáƒ“."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD-ის სტáƒáƒœáƒ“áƒáƒ áƒ¢áƒ£áƒšáƒ˜ ბრძáƒáƒœáƒ”ბის სტრიქáƒáƒœáƒ˜:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"შემდეგი სტრიქáƒáƒœáƒ˜ გáƒáƒ›áƒáƒ§áƒ”ნებულ იქნებრრáƒáƒ’áƒáƒ áƒª kFreeBSD-ს პáƒáƒ áƒáƒ›áƒ”ტრები მენიუს "
+"სტáƒáƒœáƒ“áƒáƒ áƒ¢áƒ£áƒšáƒ˜ შენáƒáƒ¢áƒáƒœáƒ˜áƒ¡áƒáƒ—ვის, მáƒáƒ’რáƒáƒ› áƒáƒ áƒ áƒáƒ¦áƒ“გენის რეჟიმისáƒáƒ—ვის."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "ნებისმიერ შემთხვევáƒáƒ¨áƒ˜, რáƒáƒ“ესáƒáƒª მáƒáƒ˜áƒ¡áƒ£áƒ áƒ•áƒ”ბთ GRUB 2 პირდáƒáƒžáƒ˜áƒ  MBR-დáƒáƒœ "
+#~ "ჩáƒáƒ˜áƒ¢áƒ•áƒ˜áƒ áƒ—áƒáƒ¡, áƒáƒ›áƒ˜áƒ¡áƒáƒ—ვის გáƒáƒ£áƒ¨áƒ•áƒ˜áƒ— შემდეგი ბრძáƒáƒœáƒ”ბრ(root პრივილეგიებით):"
diff --git a/debian/po/kk.po b/debian/po/kk.po
new file mode 100644
index 0000000..c8da6fa
--- /dev/null
+++ b/debian/po/kk.po
@@ -0,0 +1,481 @@
+# Kazakh translation for grub2.
+# Copyright (C) 2010 The Grub team
+# This file is distributed under the same license as the PACKAGE package.
+# Baurzhan Muftakhidinov <baurthefirst@gmail.com>, 2010-2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: master\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 21:51+0600\n"
+"Last-Translator: Baurzhan Muftakhidinov <baurthefirst@gmail.com>\n"
+"Language-Team: Kazakh <kk_KZ@googlegroups.com>\n"
+"Language: kk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst ішінен тізбектей жүктелу керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "GRUB жаңарту Ñкриптері /boot/grub ішінен орнатылған GRUB Legacy тапты."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"GRUB Legacy нұÑқаÑын алмаÑтыру үшін, Ñіздің бар болып тұрған GRUB Legacy "
+"орнатудың /boot/grub/menu.lst файлынан GRUB 2 жүктеушіÑін тізбектей жүктеуге "
+"баптауға Ò±Ñынылады. Бұл қадам қазір автоматты түрде жаÑалуы мүмкін."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"GRUB 2-ні menu.lst ішінен тізбектей жүктеуді қабылдау, және жаңа GRUB 2 "
+"орнатуы оны MBR (БаÑÑ‚Ñ‹ жүктелу жазбаÑына) ішіне Ð¶Ð°Ð·Ð±Ð°Ñ Ð±Ò±Ñ€Ñ‹Ð½ Ð¶Ò±Ð¼Ñ‹Ñ "
+"Ñ–Ñтейтінін текÑеру Ò±Ñынылады."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Шешіміңіз қандай болÑа да, кейін Ñіз әрқашан да еÑкі MBR бейнеÑін жаңа GRUB "
+"2-мен ауыÑтыра алаÑыз, ол үшін root атынан келеÑÑ– команда орындауыңыз керек:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB орнатылатын құрылғылар:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc деÑтеÑÑ– жаңартылуда. Бұл мәзір Ñізге қай құрылғылар үшін grub-"
+"install автожөнелту қалайтыныңызды көрÑетуге мүмкін қылады, егер ондай "
+"құрылғылар бар болÑа."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"grub-install автожөнелту көп жағдайда Ò±Ñынылады, орнатылған GRUB өзегі және "
+"модульдер немеÑе grub.cfg-мен үйлеÑімді болуы үшін."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Егер Ñіз BIOS-та қай диÑк жүктелетін етіп орнатылғанын нақты білмеÑеңіз, "
+"GRUB-Ñ‚Ñ‹ диÑктердің барлығына орнатуға да болады."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"ЕÑкерту: GRUB-Ñ‚Ñ‹ бөлімнің жүктелу жазбаÑына да орнатуға болады, ÑÓ™Ð¹ÐºÐµÑ "
+"келетін бөлімдер тізімі төменде көрÑетілген. Ðлайда, бұл әрекет GRUB-Ñ‚Ñ‹ "
+"блоктізімді қолдануға мәжбүрлетеді, Ñғни оның икемділігін төмендетеді, Ñол "
+"үшін Ò±Ñынылмайды."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB жүктеушіÑÑ– қазір жоқ болып тұрған, немеÑе қандай да бір Ñебептермен "
+"уникалды идентификаторы өзгерген диÑкіге бұрын орнатулы болған. Орнатылған "
+"GRUB өзегі және модульдер мен grub.cfg-мен үйлеÑімді болуын текÑеру маңызды. "
+"GRUB Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ò¯ÐºÑ‚ÐµÐ»Ñƒ құрылғыларына жазылғанын тағы да бір рет текÑеріңіз."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} МБ; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} МБ; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUB-Ñ‚Ñ‹ жүктелу құрылғыÑына жазу ÑәтÑіз - жалғаÑтыру керек пе?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB келеÑÑ– құрылғыларға орнату ÑәтÑіз аÑқталды:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Бәрібір жалғаÑтыруды қалайÑыз ба? ÐәтижеÑінде компьютеріңіз Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ò¯ÐºÑ‚ÐµÐ»Ð¼ÐµÑƒÑ– "
+"мүмкін."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "GRUB-Ñ‚Ñ‹ жүктелу құрылғыÑына жазу ÑәтÑіз - қайталау керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Сіз оған қоÑа GRUB-Ñ‚Ñ‹ баÑқа да құрылғыларға орната алаÑыз, бірақ жүйеңіз ол "
+"кезде жүктеле алатынына көз жеткізіңіз. БолмаÑа, GRUB Legacy нұÑқаÑынан "
+"жаңартудан Ð±Ð°Ñ Ñ‚Ð°Ñ€Ñ‚Ñ‹Ð»Ð°Ð´Ñ‹."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB орнатпай-ақ жалғаÑтыру керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Сіз GRUB-Ñ‚Ñ‹ ешбір құрылғыға орнатпауды қалағанÑыз. ЖалғаÑÑ‚Ñ‹Ñ€Ñаңыз, жүктеуші "
+"Ð´Ò±Ñ€Ñ‹Ñ Ð±Ð°Ð¿Ñ‚Ð°Ð»Ð¼Ð°ÑƒÑ‹ мүмкін, және компьютеріңіз келеÑÑ– рет жүктелген кезде, "
+"жүктелу жазбаÑында оған дейін болған нәрÑені қолданады. Егер ол жүктелу "
+"жазбаÑында GRUB 2 ертерек шыққан нұÑқаÑÑ‹ болÑа, ол модульдерді жүктей алмай, "
+"не ағымдағы баптаулар файлын талдай алмайтын болуы әдбен мүмкін."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Егер Ñіз баÑқа жүктеушіні қолданып, оны жалғаÑтыруды қалаÑаңыз, немеÑе бұл - "
+"жүктеушіні талап етпейтін ерекше жүйе болÑа, онда жалғаÑтырыңыз. БолмаÑа, "
+"қайда болÑа да, GRUB орнатуыңыз керек."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "GRUB 2 /boot/grub ішінен өшіру керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "GRUB 2 барлық файлдарын /boot/grub ішінен өшіруді шынымен қалайÑыз ба?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Бұл әрекет баÑқа жүктеуші орнатылмаған болÑа, жүйеңізді жүктелмейтін қылады."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "GRUB 2-ге айналдыруды қазір аÑқтау керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Жүйеде әлі де GRUB Legacy жүктеушіÑÑ– орнатылған, оған қоÑа GRUB 2 жүктелу "
+"жазбалары келеÑÑ– диÑкілерге орнатылған:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"GRUB Legacy енді қолданылмайтын ÑиÑқты, орнына GRUB 2 бейнелерін ол "
+"диÑкілерде жаңартып, еÑкі GRUB Legacy файлдарын өшіріңіз. GRUB 2 бейнелерін "
+"жаңартпаÑаңыз, олар жаңа деÑтелермен үйлеÑпей, жүйеңіз Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ò¯ÐºÑ‚ÐµÐ»Ð¼ÐµÑƒÑ– "
+"мүмкін."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"GRUB 2 дейін жаңартуды аÑқтауыңыз керек, егер оÑÑ‹ жүктелу жазбалары баÑқа "
+"жүйеде орнатылған GRUB 2 көмегімен жаÑалмаған болÑа."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux командалық жолы:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"КелеÑÑ– Linux командаÑÑ‹ /etc/default/grub ішінен не GRUB Legacy menu.lst "
+"ішіндегі `kopt' параметрінен алынды. Оның дұрыÑтығын текÑеріп, керек болÑа, "
+"өзгертіңіз. Бұл командалық жол Ð±Ð¾Ñ Ð±Ð¾Ð»Ñа да болады."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux баÑтапқы командалық жолы:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"КелеÑÑ– жол Linux параметрлері баÑтапқы мәзірі үшін, бірақ қалпына келтіру "
+"үшін емеÑ, қолданылатын болады."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "EFI ауыÑтырмалы таÑушыға қоÑымша орнатуды мәжбүрлету керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Кейбір EFI негізіндегі жүйелер толығымен Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ð°Ñамайды және жаңа "
+"жүктеушілерді Ð´Ò±Ñ€Ñ‹Ñ Ó©Ò£Ð´ÐµÐ¼ÐµÐ¹Ð´Ñ–. Егер Ñіз қоÑымша түрде GRUB-Ñ‚Ñ‹ EFI "
+"ауыÑтырмалы таÑушыға орнатÑаңыз, оÑÑ‹ мәÑелеге қарамаÑтан, бұл әрекет бұл "
+"жүйенің Debian-ды Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ò¯ÐºÑ‚ÐµÐ¹Ñ‚Ñ–Ð½Ñ–Ð½ қамтамаÑыз етуі тиіÑ. Ðлайда, ол "
+"таÑушыға тәуелді баÑқа операциÑлық жүйелердің жүктеле алмауына әкеп Ñоғуы "
+"мүмкін. Олай болÑа Ñізге GRUB барлық баÑқа ОЖ-ды жүктей алатындай етіп Ð´Ò±Ñ€Ñ‹Ñ "
+"бапталғанына көз жеткізу керек."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Debian ішіне автожүктелу үшін NVRAM айнымалыларын жаңарту керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB Ñіздің платформаңыз Ñ–Ñке қоÑылған кезде Debian ішіне автожүктелетіндей "
+"етіп NVRAM айнымалыларын баптай алады. Ðлайда, Ñіз бұл өзгеріÑÑ‚Ñ– Ñөндіріп, "
+"жүктелу баптауларын өзгертпеуді қалауыңыз мүмкін. МыÑалы, NVRAM айнымалылары "
+"жүйеңіз әр жүктелген кезде PXE Ñерверімен байланыÑатындай бапталған болÑа, "
+"онда оÑындай әрекет Ñақталады."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"БаÑқа ОЖ анықтау және жүктеу үшін os-prober автоматты түрде жөнелту керек пе?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB компьютеріңіздегі баÑқа операциÑлық жүйелерді анықтау үшін os-prober "
+"құралын пайдалана алады және оларды автоматты түрде жүктеу нұÑқаларының "
+"тізіміне қоÑа алады."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Егер компьютеріңізде бірнеше операциÑлық жүйелер орнатылған болÑа, онда бұл "
+"қалағаныңыз шығар. Дегенмен, егер компьютеріңіз LVM немеÑе шикі диÑкілік "
+"құрылғылар арқылы орнатылған қонақ оÑьтеріне арналған хоÑÑ‚ болÑа, os-prober "
+"іздеу кезінде файлдар жүйелерін тіркейтін Ñоң Ñол қонақ ОС-ге зиÑн келтіруі "
+"мүмкін."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD командалық жолы:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"КелеÑÑ– kFreeBSD командаÑÑ‹ /etc/default/grub ішінен не GRUB Legacy menu.lst "
+"ішіндегі `kopt' параметрінен алынды. Оның дұрыÑтығын текÑеріп, керек болÑа, "
+"өзгертіңіз. Бұл командалық жол Ð±Ð¾Ñ Ð±Ð¾Ð»Ñа да болады."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD баÑтапқы командалық жолы:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"КелеÑÑ– жол kFreeBSD параметрлері баÑтапқы мәзірі үшін, бірақ қалпына келтіру "
+"үшін емеÑ, қолданылатын болады."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map қайта құрылды"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "/boot/grub/device.map файлы құрылғылардың тұрақты аттарын қолданатындай "
+#~ "түзетілген. Көп жағдайда, болашақта өзгерту керек ÐµÐ¼ÐµÑ Ð±Ð¾Ð»Ð°Ð´Ñ‹, және GRUB "
+#~ "жаÑаған мәзір Ñлементтері өзгеріÑÑіз-ақ қалады."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ðлайда, жүйеңізде бірден көп диÑк болған Ñоң, еÑкі device map-қа тәуелді "
+#~ "болуыңыз мүмкін. GRUB-Ò£ (hdN) түріндегі диÑктер нөмірленуі мәзірде жоқ "
+#~ "болуына көз жеткізіңіз, керек болÑа, оларды жаңартыңыз."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Егер Ñіз оÑÑ‹ хабарламаны Ñ‚Ò¯ÑінбеÑеңіз, немеÑе Ñізде таңдауыңызша жүктелу "
+#~ "мәзірінің Ñлементтері жоқ болÑа, бұл хабарламаны елемеңіз."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Қалай болÑа да, GRUB 2 тура MBR ішінен жүктелуді қалайтын болÑаңыз, Ñол "
+#~ "кезде root атынан келеÑÑ– команданы орындаңыз:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "GRUB орнату ÑәтÑіз. ЖалғаÑтыру керек пе?"
diff --git a/debian/po/km.po b/debian/po/km.po
new file mode 100644
index 0000000..244ab73
--- /dev/null
+++ b/debian/po/km.po
@@ -0,0 +1,440 @@
+# translation of grub_debian_po.po to Khmer
+# Khoem Sokhem <khoemsokhem@khmeros.info>, 2012.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub_debian_po\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-04-05 15:38+0700\n"
+"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
+"Language-Team: Khmer <support@khmeros.info>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"X-Language: ki-KH\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "ផ្ទុក​ពី menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "GRUB ធ្វើ​ឲ្យ​ស្គ្រីប​ប្រសើរ​ឡើង បាន​រកឃើញ​ការ​រៀបចំ​ចាស់ៗ​របស់ GRUB នៅ​ក្នុង /boot/grub ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"ដើម្បី​ជំនួស​កំណែ​ចាស់ៗ​របស់ GRUB នៅ​ក្នុង​ប្រពáŸáž“្ធ​របស់​អ្នក វា​បានផ្ដល់​អនុសាសនáŸâ€‹áž²áŸ’យ​កែសម្រួល /boot/grub/"
+"menu.lst ដើម្បី​ផ្ទុក​រូប​ភាព​ចាប់ផ្ដើម GRUB 2 ពី​ការ​រៀបចំ​ចាស់ៗ​នៃ​ GRUB ដែល​មាន​ស្រាប់​របស់​អ្នក ។ "
+"ជំហាន​នáŸáŸ‡â€‹áž¢áž¶áž…​ážáŸ’រូវ​បាន​អនុវážáŸ’ážâ€‹ážŠáŸ„យ​ស្វáŸáž™â€‹áž”្រវážáŸ’ážâ€‹áž¥áž¡áž¼ážœ ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"វា​បានផ្ដល់​អនុសាសនáŸâ€‹áž²áŸ’យ​អ្នក​ទទួល​យក​​កា​រផ្ទុក​ GRUB 2 ពី menu.lst ហើយ​ផ្ទៀងផ្ទាážáŸ‹â€‹ážáž¶â€‹áž€áž¶ážšâ€‹ážšáŸ€áž”ចំ GRUB 2 "
+"ážáŸ’មី​ដំណើរការ​មុន​ពáŸáž›â€‹ážœáž¶â€‹ážáŸ’រូវ​បាន​សរសáŸážšâ€‹áž‘ៅ​កាន់ MBR (Master Boot Record) ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"មិន​ážáž¶â€‹áž¢áŸ’នក​សម្រáŸáž…áž…áž·ážáŸ’ážâ€‹ážáž¶â€‹áž˜áŸ‰áŸáž…​កáŸâ€‹ážŠáŸ„áž™ អ្នក​អាច​ជំនួស​រូបភាព MBR ចាស់​ដោយ​ GRUB 2 áž–áŸáž›â€‹â€‹áž€áŸ’រោយ ដោយ​ប្រើ​ពាក្យ​"
+"បញ្ជា​​ដូ​ចážáž¶â€‹áž„ក្រោម​ជា root ៖"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB ដំឡើង​ឧបករណ០៖"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"កញ្ចប់ grub-pc កំពុង​ážáŸ’រូវ​បាន​ធ្វើ​ឲ្យ​ប្រសើរឡើង ។ ម៉ឺនុយ​នáŸáŸ‡â€‹áž¢áž“ុញ្ញាážâ€‹áž²áŸ’យ​អ្នក​ជ្រើស​ឧបករណáŸâ€‹ážŽáž¶áž˜áž½áž™â€‹ ដែល​អ្នក​"
+"ចង់​ grub-install ដំណើរការ​ដោយ​ស្វáŸáž™â€‹áž”្រវážáŸ’ážáž· ប្រសិនបើ​មាន ។"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"ករណី​ភាគ​ច្រើន​កា​រដំណើរការ grub-install ដោយ​ស្វáŸáž™â€‹áž”្រវážáŸ’ážáž·â€‹ážáŸ’រូវ​បាន​ផ្ដល់​អនុសាសន០ដើម្បីការពារ​រូបភាព "
+"GRUB សំážáž¶áž“់​ដែល​បាន​ដំឡើង​ពី​ការ​ធ្វើ​សមកាលកម្ម​ជា​មួយ​ម៉ូឌុល GRUB ឬ grub.cfg ។"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ប្រសិនបើ​អ្នក​​មិន​ប្រាកដ​ážáž¶â€‹ážŠáŸ’រាយ​ណាមួយ​ážáŸ’រូវ​បាន​ផ្ដល់​ជា​ដ្រាយ​ចាប់ផ្ដើម ដោយ​ BIOS របស់​អ្នក វា​ជា​គំនិážâ€‹ážŠáŸâ€‹áž›áŸ’អ​គឺ​"
+"ážáŸ’រូវ​ដំឡើង​ GRUB ទៅ​កាន់​ពួក​វា​ទាំងអស់ ។"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"ចំណាំ ៖ អាច​ដំឡើង GRUB ទៅ​ភាគ​​ចាប់ផ្ដើម​បាន​ផង​ដែរ ភាគ​ដែលសមស្រប​មួយ​ចំនួន​ážáŸ’រូវ​បាន​ផ្ដល់​នៅ​ទីនáŸáŸ‡ ។ ទោះ​"
+"ជា​យ៉ាង​ណា​កáŸâ€‹ážŠáŸ„áž™ វា​បង្ážáŸ† GRUB ឲ្យ​ប្រើ​យន្ážáž€áž¶ážšâ€‹áž”ញ្ជី​ទប់ស្កាážáŸ‹ ដែល​ធ្វើ​ឲ្យ​វា​អាច​ទុកចិážáŸ’ážâ€‹áž”ាន​ážáž·áž…ážáž½áž… ហើយ​"
+"ដូច្នáŸáŸ‡â€‹áž˜áž·áž“​ážáŸ’រូវ​បាន​ផ្ដល់​អនុសាសនáŸâ€‹áž‘០។"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"កម្មវិធី​ចាប់ផ្ដើម​ប្រពáŸáž“្ធ GRUB ážáŸ’រូវ​បាន​ដំឡើង​ពី​មុន ទៅ​ážáž¶ážŸâ€‹ážŠáŸ‚ល​លែង​ប្រើ ឬ​អážáŸ’ážážŸáž‰áŸ’ញាណ​ážáŸ‚​មួយ​គážáŸ‹â€‹ážšáž”ស់​វា​បាន​"
+"ផ្លាស់ប្ដូរ​ដោយ​​មូលហáŸážáž»â€‹áž˜áž½áž™â€‹áž…ំនួន ។ វា​មាន​សារៈ​សំážáž¶áž“់​ážáŸ’រូវ​​ប្រាកដážáž¶ រូបភាព​ GRUB ដែល​បាន​ដំឡើង​ធ្វើ​"
+"សមកាលកម្ម​ជា​មួយ​ម៉ូឌុល GRUB áž“áž·áž„ grub.cfg ។ សូម​ពិនិážáŸ’យ​មើល​ម្ដង​ទៀហដើម្បី​ប្រាកដážáž¶ GRUB ážáŸ’រូវ​បាន​"
+"សរសáŸážšâ€‹áž‘ៅ​កាន់​ឧបករណáŸâ€‹áž…ាប់ផ្ដើម​ដែល​ážáŸ’រឹមážáŸ’រូវ ។"
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "បាន​បរាជáŸáž™â€‹áž€áŸ’នុង​ការ​សរសáŸážšâ€‹ GRUB ទៅ​​ឧបករណáŸâ€‹áž…ាប់ផ្ដើម បន្ហ?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB បាន​បរាជáŸáž™â€‹áž€áŸ’នុង​ការ​ដំឡើង​ឧបករណáŸâ€‹ážŠáž¼â€‹áž…ážáž¶áž„​ក្រោម ៖"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"អញ្ចឹង ážáž¾â€‹áž¢áŸ’នក​ចង់​បន្ážâ€‹ážŠáŸ‚រ​ឬទ០? ប្រសិន​បើ​អ្នក​បន្ហកុំព្យូទáŸážšâ€‹ážšáž”ស់​អ្នក​មិន​អាច​ចាប់ផ្ដើម​បាន​ážáŸ’រឹមážáŸ’រូវ​ទ០។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "បាន​បរាជáŸáž™â€‹áž€áŸ’នុង​ការ​សរសáŸážš GRUB ទៅ​ឧបករណáŸâ€‹áž…ាប់ផ្ដើម ព្យាយាម​ម្ដង​ទៀហ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"អ្នក​អាច​ដំឡើង GRUB ទៅ​ឧបករណáŸâ€‹áž˜áž½áž™â€‹áž…ំនួន​បាន ទោះ​បី​ជា​អ្នក​​ដឹង​ážáž¶ ប្រពáŸáž“្ធ​របស់​អ្នក​នឹង​ចាប់ផ្ដើម​ពី​ឧបករណáŸâ€‹áž“ោះ​កáŸâ€‹"
+"ដោយ ។ បើ​មិន​ដូច្នáŸáŸ‡â€‹áž‘០ការ​ធ្វើ​ឲ្យ​ប្រសើរ​ឡើង​ពី GRUB ចាស់ៗ​នឹង​ážáŸ’រូវ​បាន​បោះបង់ ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "បន្ážâ€‹ážŠáŸ„យ​មិន​ដំឡើង GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"អ្នក​បាន​ជ្រើសរើស​ážáž¶â€‹áž˜áž·áž“​ដំឡើង​ GRUB ក្នុង​ឧបករណáŸâ€‹ážŽáž¶áž˜áž½áž™â€‹áž‘០។ ប្រសិនបើ​អ្នក​បន្ហ​កម្មវិធី​ចាប់ផ្ដើម​ប្រពáŸáž“្ធ​អាច​"
+"មិន​​ážáŸ’រូវ​បាន​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​ážáŸ’រឹមážáŸ’រូវ​ទ០ហើយ​នៅ​ពáŸáž›â€‹áž€áž»áŸ†áž–្យូទáŸážšâ€‹áž“áŸáŸ‡â€‹áž…ាប់ផ្ដើម​ពáŸáž›â€‹áž€áŸ’រោយ វា​នឹង​ប្រើ​អ្វី​ដែល​មាន​"
+"ពីមុន​នៅ​ក្នុង​ផ្នែក​ចាប់ផ្ដើម ។ ប្រសិន​បើ​គ្មាន​កំណែ GRUB 2 ពី​មុន​នៅ​ក្នុង​ផ្នែក​ចាប់ផ្ដើម​ទ០វា​​មិន​អាច​ផ្ទុក​"
+"ម៉ូឌុល ឬ​ដោះស្រាយ​ឯកសារ​កំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​បច្ចុប្បន្ន​បាន​ទ០។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ប្រសិ​ន​បើ​អ្នក​កំពុង​ប្រើ​កម្មវិធី​ចាប់ផ្ដើម​ប្រពáŸáž“្ធ​ផ្សáŸáž„​ហើយ ហើយ​ចង់​បន្ážâ€‹áž”្រើ​វា​ទៀážâ€‹áž“ោះ ឬ​ប្រសិន​បើ​មាន​បរិស្ážáž¶áž“​"
+"ពិសáŸážŸâ€‹ážŠáŸ‚ល​អ្កន​មិន​ážáŸ’រូវ​ការ​កម្មវិធី​ចាប់ផ្ដើម​ប្រពáŸáž“្ធ នោះ​អ្នក​គួរ​បន្ហ។ បើ​មិន​ដូច្នáŸáŸ‡â€‹áž‘០អ្នក​គួរ​ដំឡោះង "
+"GRUB នៅ​កន្លែង​ណាមួយ ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "យក GRUB 2 áž…áŸáž‰ ពី /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "ážáž¾â€‹áž¢áŸ’នក​ចង់​​យក​ឯកសារ​របស់ GRUB 2 ទាំង​អស់​ចáŸáž‰â€‹áž–ី /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "វា​នឹង​ធ្វើ​ឲ្យ​ប្រពáŸáž“្ធ​មិន​អាច​ចាប់ផ្ដើម​បាន លុះážáŸ’រា​ážáŸ‚​​ដំឡើង​កម្មវិធី​ចាប់ផ្ដើម​ប្រពáŸáž“្ធ​ផ្សáŸáž„ ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "បញ្ចប់ការ​បម្លែងទៅ​ GRUB 2 ឥឡូវ ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"ប្រពáŸáž“្ធ​នáŸáŸ‡â€‹áž“ៅ​ážáŸ‚​មាន​ឯកសារ​ពី​កម្មវិធី​ចាប់ផ្ដើម​ប្រពáŸáž“្ធ​ចាស់​ៗ​របស់ GRUB ដែល​បាន​ដំឡើង ប៉ុន្ážáŸ‚​ឥឡូវ​កáŸâ€‹áž˜áž¶áž“​ផ្នែក​"
+"ចាប់ផ្ដើម GRUB 2 បាន​ដំឡើង​នៅ​ក្នុង​ážáž¶ážŸâ€‹áž‘ាំង​នáŸáŸ‡â€‹ážŠáŸ‚ážš ៖"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"វា​ហាក់បី​ដូចជា​ភាព​ចាស់ៗ​របស់​ GRUB លែង​ប្រើ​ហើយ ហើយ​អ្នក​គួរ​ជំនួស​ការ​ធ្វើ​ឲ្យ​រូបភាព GRUB 2 ប្រសើ​រឡើង​"
+"នៅ​លើ​ážáž¶ážŸâ€‹áž‘ាំង​នáŸáŸ‡ ហើយ​បញ្ចប់​ការ​បម្លែង​ទៅ GRUB 2 ដោយ​​យក​ឯកសារ​ចាស់ៗ​របស់ GRUB ចាស់​ចáŸáž‰ ។ ប្រសិន​បើ​"
+"អ្នក​មិន​ធ្វើ​ឲ្យ​រូបភាព GRUB 2 ទាំង​នáŸáŸ‡â€‹áž”្រសើ​រឡើង​ទ០នោះ​ពួក​វា​អាច​មិន​ážáŸ’រូវ​គ្នា​ជា​មួយ​នឹង​កញ្ចប់​ážáŸ’មីៗ ហើយ​"
+"ធ្វើ​ឲ្យ​ប្រពáŸáž“្ធ​របស់​អ្នក​បញ្ឈប់​ការ​ចាប់ផ្ដើម​ ។"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"ជា​ទូទៅ អ្នក​គួរ​ážáŸ‚​បញ្ចប់​ការ​បម្លែង​ទៅ GRUB 2 លុះážáŸ’រា​ážáŸ‚​ផ្នែក​ចាប់ផ្ដើម​ážáŸ’រូវ​បាន​បង្កើážâ€‹ážŠáŸ„យ​ការ​ដំឡើង "
+"GRUB 2 នៅ​លើ​ប្រពáŸáž“្ធ​ប្រážáž·áž”ážáŸ’ážáž·áž€áž¶ážšâ€‹áž•áŸ’សáŸáž„ ។"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "ពាក្យ​បញ្ជា​លីនុច ៖"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ពាក្យ​បញ្ជា​លីនុច​ដូច​ážáž¶áž„​ក្រោម​ážáŸ’រូវ​បាន​ដកស្រង់​ចáŸáž‰â€‹áž–ី /etc/default/grub ឬ​ប៉ារ៉ាម៉ែážáŸ’ážš `kopt' នៅ​ក្នុង "
+"menu.lst ចាស់​របស់​ GRUB ។ សូម​ផ្ទៀងផ្ទាážáŸ‹â€‹ážáž¶â€‹ážáž¾â€‹ážœáž¶â€‹ážáŸ’រឹមážáŸ’រូវ​ដែរឬទ០ហើយ​កែប្រែ​វា​ប្រសិន​បើ​ចាំបាច់ ។ "
+"ពាក្យ​បញ្ជា​ážáŸ’រូវ​បាន​អនុញ្ញាážâ€‹áž²áŸ’យ​ទទáŸážš ។"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "ពាក្យ​បញ្ជា​លំនាំ​ដើម​របស់​លីនុច ៖"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"ឃ្លា​ដូច​ážáž¶áž„​ក្រោម​នឹង​ážáŸ’រូវ​បាន​ប្រើ​ជា​ប៉ារ៉ាម៉ែážáŸ’រ​លីនុច​សម្រាប់​ធាážáž»â€‹áž˜áŸ‰ážºáž“ុយ​លំនាំដើម ប៉ុន្ážáŸ‚​មិន​សម្រាប់​របៀប​សង្គ្រោះ​"
+"ទ០។"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "ពាក្យ​បញ្ជា kFreeBSD ៖"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ពាក្យ​បញ្ជា kFreeBSD ដូច​ážáž¶áž„​ក្រោម​ážáŸ’រូវ​បាន​ដកស្រង់​ចáŸáž‰â€‹áž–ី /etc/default/grub ឬ menu.lst ចាស់ៗ​"
+"នៅ​ក្នុង GRUB ។ សូម​ផ្ទៀងផ្ទាážáŸ‹â€‹ážáž¶â€‹ážœáž¶â€‹ážáŸ’រឹមážáŸ’រូវ ។ ពាក្យ​បញ្ជា​ážáŸ’រូវ​បាន​អនុញ្ញាážâ€‹áž²áŸ’យ​ទទ០។"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "ពាក្យ​បញ្ជា​លំនាំដើម​របស់ kFreeBSD ៖"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"ឃ្លា​ដូច​ážáž¶áž„​ក្រោម​នឹង​ážáŸ’រូវ​បាន​ប្រើ​ជា​ប៉ារ៉ាម៉ែážáŸ’ážš kFreeBSD សម្រាប់​ធាážáž»â€‹áž˜áŸ‰ážºáž“ុយ​លំនាំដើម ប៉ុន្ážáŸ‚​មិន​សម្រាប់​របៀប​"
+"សង្គ្រោះ​ទ០។"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map ážáŸ’រូវ​បាន​បង្កើážâ€‹áž¡áž¾áž„​វិញ"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "ឯកសារ /boot/grub/device.map ážáŸ’រូវ​បាន​សរសáŸážšâ€‹áž¡áž¾áž„​វិញ ដើម្បី​ប្រើ​ឈ្មោះ​ឧបករណáŸâ€‹ážáŸážš ។ ក្នុង​ករណី​"
+#~ "ភាគ​ច្រើន វា​គួរ​កាážáŸ‹â€‹áž”ន្ážáž™â€‹ážáž˜áŸ’រូវការ ដើម្បី​ផ្លាស់ប្ដូរ​វា​​នា​ពáŸáž›â€‹áž¢áž“ាគážáŸ‹ ហើយ​ធាážáž»â€‹áž˜áŸ‰ážºáž˜áž»áž™â€‹áž…ាប់ផ្ដើម​ដែល​បាន​"
+#~ "បង្កើážâ€‹ážŠáŸ„áž™ GRUB មិន​គួរ​ប៉ះពាល់​ទ០។"
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "ទោះ​ជា​យ៉ាង​ណា​កáŸâ€‹ážŠáŸ„áž™ ព្រោះ​ážáž¶â€‹áž˜áž¶áž“​ážáž¶ážŸâ€‹áž…្រើន​ជាង​មួយ​នៅ​ក្នុង​ប្រពáŸáž“្ធ ​ប្រពáŸáž“្ធ​អាស្រáŸáž™â€‹áž›áž¾â€‹áž€áž¶ážšâ€‹áž•áŸ’គូផ្គង​ឧបករណáŸâ€‹"
+#~ "ចាស់ ។ សូម​ពិនិážáŸ’យ​មើល​ážáž¶ážáž¾ មាន​ធាážáž»â€‹â€‹áž˜áŸ‰ážºáž“ុយ​ចាប់ផ្ដើម​ផ្ទាល់ážáŸ’លួន​ដែល​អាស្រáŸáž™â€‹áž›áž¾â€‹â€‹áž…ំនួន​ដ្រាយ GRUB's (hdN) "
+#~ "ហើយ​ធ្វើ​បច្ចុប្បន្ន​ភាព​ពួក​វា​ប្រសិនបើ​ចាំបាច់ ។"
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "ប្រសិន​បើ​អ្នក​មិន​យល់​សារ​នáŸáŸ‡â€‹áž‘០ឬ​ប្រសិនបើ​គ្មាន​ធាážáž»áž˜áŸ‰ážºáž“ុយ​ចាប់ផ្ដើម​ផ្ទាល់​ážáŸ’លួន អ្នក​អាច​មិនអើពើ​សារ​នáŸáŸ‡ ។"
diff --git a/debian/po/ko.po b/debian/po/ko.po
new file mode 100644
index 0000000..d2f9b44
--- /dev/null
+++ b/debian/po/ko.po
@@ -0,0 +1,459 @@
+# Changwoo Ryu <cwryu@debian.org>, 2014, 2017, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub_debian\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-26 18:55+0900\n"
+"Last-Translator: Changwoo Ryu <cwryu@debian.org>\n"
+"Language-Team: Korean <debian-l10n-korean@lists.debian.org>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lstì—ì„œ 단계별로 ì½ì–´ë“¤ì´ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB 업그레ì´ë“œ 스í¬ë¦½íŠ¸ì—ì„œ /boot/grub ì•ˆì˜ GRUB 과거 버전 ì„¤ì •ì„ ë°œê²¬í–ˆìŠµë‹ˆ"
+"다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"ì‹œìŠ¤í…œì˜ GRUB êµ¬ë²„ì „ì„ í˜„ìž¬ GRUB 2ë¡œ 바꾸려면, /boot/grub/menu.lst 파ì¼ì„ ì¡°"
+"ì •í•´ 기존 GRUB 과거 버전 설정ì—ì„œ GRUB 2 부팅 ì´ë¯¸ì§€ë¥¼ ì½ì–´ë“¤ì´ëŠ” ë°©ë²•ì„ ì¶”ì²œ"
+"합니다. ì´ ë‹¨ê³„ëŠ” ìžë™ìœ¼ë¡œ 수행할 수 있습니다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"먼저 menu.lstì—ì„œ 단계별로 GRUB 2를 ì½ì–´ë“¤ì´ê²Œ 하고, ê·¸ 다ìŒì— GRUB 2 ì„¤ì •ì´ "
+"ë™ìž‘하는지 확ì¸í•œ ë‹¤ìŒ MBR(마스터 부트 레코드)ì— GRUB 2를 설치하는 걸 추천합"
+"니다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"어떻게 ì„ íƒí•˜ë“ , ë‚˜ì¤‘ì— rootë¡œ ë‹¤ìŒ ëª…ë ¹ì„ ì‹¤í–‰í•˜ë©´ 과거 MBR ì´ë¯¸ì§€ë¥¼ GRUB 2 "
+"ì´ë¯¸ì§€ë¡œ 바꿀 수 있습니다."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB 설치 장치:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc 패키지를 업그레ì´ë“œí•˜ëŠ” 중입니다. ì´ ë©”ë‰´ì—ì„œ (실행할 장치가 있다면) "
+"ì–´ë–¤ ìž¥ì¹˜ì— ëŒ€í•´ grub-installì„ ìžë™ìœ¼ë¡œ 실행할지 설정합니다."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"ëŒ€ë¶€ë¶„ì˜ ìƒí™©ì—서는 grub-install ìžë™ ì‹¤í–‰ì„ ì¶”ì²œí•©ë‹ˆë‹¤. 그래야 설치한 GRUB "
+"ì´ë¯¸ì§€ê°€ GRUB 모듈ì´ë‚˜ grub.cfg 파ì¼ê³¼ 어긋나지 않습니다."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ì–´ë–¤ ë“œë¼ì´ë¸Œë¥¼ BIOSì—ì„œ 사용할 부팅 ë“œë¼ì´ë¸Œë¡œ 설정할지 잘 모르겠다면, GRUB"
+"ì„ ëª¨ë“  ë“œë¼ì´ë²„ì— ì„¤ì¹˜í•˜ëŠ” ê²ƒë„ ì¢‹ì€ ë°©ë²•ìž…ë‹ˆë‹¤."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"주ì˜: GRUBì„ íŒŒí‹°ì…˜ 부트 ë ˆì½”ë“œì— ì„¤ì¹˜í•  ìˆ˜ë„ ìžˆê³ , 해당 íŒŒí‹°ì…˜ì´ ì—¬ê¸° 표시ë©"
+"니다. 하지만 파티션 부트 ë ˆì½”ë“œì— ì„¤ì¹˜í•˜ë©´ GRUBì—ì„œ ëœ ì•ˆì •ì ì¸ 블럭리스트 ë°©"
+"ì‹ì„ 사용하게 ë˜ë¯€ë¡œ 추천하지 않습니다."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"ì´ì „ì— GRUB 부트로ë”를 ì„¤ì¹˜í–ˆë˜ ë””ìŠ¤í¬ê°€ ì´ì œ ì»´í“¨í„°ì— ì—†ê±°ë‚˜, ì–´ë–¤ ì´ìœ ì—ì„œ"
+"ë“  고유 ì•„ì´ë””ê°€ 바뀌었습니다. GRUB 코어 ì´ë¯¸ì§€ê°€ GRUB 모듈 ë° grub.cfg와 ë™"
+"기화하는 게 중요합니다. GRUBì´ ì˜¬ë°”ë¥¸ 부팅 ìž¥ì¹˜ì— ì„¤ì¹˜ë˜ë„ë¡ ë‹¤ì‹œ 확ì¸í•˜ì‹­ì‹œ"
+"오."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB, ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB, ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUBì„ ë¶€íŒ… ìž¥ì¹˜ì— ì“°ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ê³„ì† í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "ë‹¤ìŒ ìž¥ì¹˜ì— ëŒ€í•´ GRUB 설치가 실패했습니다:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"ê·¸ëž˜ë„ ê³„ì† í•˜ì‹œê² ìŠµë‹ˆê¹Œ? ê³„ì† í•˜ë©´ 컴퓨터가 제대로 시작하지 ì•Šì„ ìˆ˜ë„ ìžˆìŠµë‹ˆ"
+"다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "GRUBì„ ë¶€íŒ… ìž¥ì¹˜ì— ì“°ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하시겠습니까?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"GRUBì„ ë‹¤ë¥¸ ìž¥ì¹˜ì— ì„¤ì¹˜í•  ìˆ˜ë„ ìžˆì§€ë§Œ, ê·¸ 장치ì—ì„œ ì‹œìŠ¤í…œì´ ë¶€íŒ…í•˜ëŠ”ì§€ 확ì¸í•´"
+"야 합니다. 설치하지 않으면 GRUB 구버전ì—ì„œ 업그레ì´ë“œëŠ” 취소합니다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUBì„ ì„¤ì¹˜í•˜ì§€ ì•Šê³  계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"GRUBì„ ì–´ë–¤ 장치ì—ë„ ì„¤ì¹˜í•˜ì§€ ì•Šë„ë¡ ì„ íƒí•˜ì…¨ìŠµë‹ˆë‹¤. ê³„ì† í•˜ì‹œë©´ 부트로ë”ê°€ "
+"제대로 설정ë˜ì§€ ì•Šì„ ìˆ˜ë„ ìžˆê³ , 다ìŒë²ˆì— 컴퓨터가 시작할 ë•Œ ì˜ˆì „ì— ë¶€íŠ¸ 섹터"
+"ì— ë“¤ì–´ 있는 부트로ë”를 사용합니다. GRUB 2ì˜ ì˜ˆì „ ë²„ì „ì´ ë¶€íŠ¸ì„¹í„°ì— ë“¤ì–´ 있으"
+"ë©´ ê·¸ 예전 ë²„ì „ì€ GRUB ëª¨ë“ˆì„ ì½ì–´ë“¤ì´ê±°ë‚˜ 현재 설정 파ì¼ì„ 처리하지 못할 수"
+"ë„ ìžˆìŠµë‹ˆë‹¤."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ì´ë¯¸ 다른 부트로ë”를 사용하는 중ì´ê³  ê³„ì† ì‚¬ìš©í•˜ë ¤ë©´, 아니면 부트로ë”ê°€ í•„ìš” "
+"없는 특수한 환경ì´ë¼ë©´, ê³„ì† ì§„í–‰í•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. 아니면 GRUBì„ ì–´ë””ì—ë“  설"
+"치해야 합니다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "/boot/grubì—ì„œ GRUB 2를 제거하시겠습니까?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "/boot/grubì—ì„œ 모든 GRUB 2 파ì¼ì„ 제거하시겠습니까?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"ì´ë ‡ê²Œ 하면 ë˜ ë‹¤ë¥¸ 부트로ë”를 설치하지 않는 í•œ ì‹œìŠ¤í…œì´ ë¶€íŒ… 불가능해집니다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "GRUB 2ë¡œ ì „í™˜ì„ ë§ˆì¹˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"ì´ ì‹œìŠ¤í…œì—는 GRUB êµ¬ë²„ì „ì˜ ë¶€íŠ¸ë¡œë” íŒŒì¼ì´ ì•„ì§ ì„¤ì¹˜ë˜ì–´ 있습니다. 하지만 "
+"GRUB 2 ë¶€íŠ¸ë ˆì½”ë“œë„ ë‹¤ìŒ ë””ìŠ¤í¬ì— 설치ë˜ì–´ 있습니다:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"ì´ì œ GRUB êµ¬ë²„ì „ì„ ì‚¬ìš©í•˜ì§€ 않는 것 같습니다. 그러면 GRUB 2 ì´ë¯¸ì§€ë¥¼ 업그레ì´"
+"드하고 GRUB 구버전 파ì¼ì„ 제거해서 GRUB 2 ì „í™˜ì„ ë§ˆì¹˜ì‹­ì‹œì˜¤. GRUB 2 ì´ë¯¸ì§€ë¥¼ "
+"업그레ì´ë“œí•˜ì§€ 않으면, 새 패키지와 호환ë˜ì§€ ì•Šì„ ìˆ˜ë„ ìžˆê³ , 그러면 ì‹œìŠ¤í…œì´ "
+"제대로 부팅하지 않습니다."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"ì¼ë°˜ì ì¸ 경우 GRUB 2 ì „í™˜ì„ ë§ˆì³ì•¼ 합니다. 예외는 ë¶€íŠ¸ë ˆì½”ë“œì˜ GRUB 2를 다른 "
+"ìš´ì˜ì²´ì œì—ì„œ 설치한 경우입니다."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "리눅스 명령어:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ë‹¤ìŒ ë¦¬ëˆ…ìŠ¤ 명령어를 /etc/default/grub íŒŒì¼ ë˜ëŠ” GRUB êµ¬ë²„ì „ì˜ menu.lstì˜ "
+"`kopt' 파ë¼ë¯¸í„°ì—ì„œ 뽑아냈습니다. 명령어가 올바른지 확ì¸í•˜ê³  필요하다면 수정"
+"하십시오. 명령어는 비워 둘 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "리눅스 기본 명령어:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"ë‹¤ìŒ ë¬¸ìžì—´ì„ 기본 메뉴 í•­ëª©ì˜ ë¦¬ëˆ…ìŠ¤ 파ë¼ë¯¸í„°ë¡œ 사용합니다. 복구 모드ì—서는 "
+"사용하지 않습니다."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "EFI ì´ë™ì‹ 미디어 ê²½ë¡œì— ì¶”ê°€ë¡œ ê°•ì œ 설치하시겠습니까?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"ì¼ë¶€ EFI 기반 시스템ì—는 버그 ë•Œë¬¸ì— ìƒˆë¡œìš´ 부트로ë”를 제대로 처리하지 못합니"
+"다. GRUBì„ EFI ì´ë™ì‹ 미디어 ê²½ë¡œì— ì¶”ê°€ë¡œ ê°•ì œ 설치하면, ì´ëŸ¬í•œ 버그가 있ë”"
+"ë¼ë„ ë°ë¹„안 ë¶€íŒ…ì´ ì œëŒ€ë¡œ ëœë‹¤ê³  보장할 수 있습니다. 하지만 ì´ ê²½ë¡œì— ì˜ì¡´í•˜"
+"는 다른 ìš´ì˜ì²´ì œê°€ 있으면 ê·¸ ìš´ì˜ì²´ì œë¡œ 부팅할 수 없게 ë©ë‹ˆë‹¤. ì´ëŸ° 경우 다"
+"른 ìš´ì˜ì²´ì œë¡œ 부팅할 수 있ë„ë¡ GRUBì„ ì„¤ì •í•˜ì‹­ì‹œì˜¤."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "ë°ë¹„안으로 ìžë™ 부팅하ë„ë¡ NVRAM 변수를 ì—…ë°ì´íŠ¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUBì—ì„œ ì´ í”Œëž«í¼ì˜ NVRAM 변수를 설정해서 ì „ì›ì„ ì¼°ì„ ë•Œ ë°ë¹„안으로 부팅하ë„"
+"ë¡ ì„¤ì •í•  수 있습니다. 아니면 ì´ ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ì§€ ì•Šê³  부팅 ì„¤ì •ì„ ë°”ê¾¸ì§€ 싶"
+"지 ì•Šì„ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. 예를 들어 부팅할 때마다 PXE ì„œë²„ì— ì—°ê²°í•˜ë„ë¡ NVRAM ë³€"
+"수가 설정ë˜ì–´ 있고, ì´ ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ì§€ 않으면 ê³„ì† ê·¸ë ‡ê²Œ ë™ìž‘í•  것입니다."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr "os-prober를 실행해 ìžë™ìœ¼ë¡œ 다른 OS를 검색하고 부팅할까요?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUBì—ì„œ os-prober ë„구를 사용해 ì»´í“¨í„°ì˜ ë‹¤ë¥¸ ìš´ì˜ ì²´ì œë¥¼ 검색하고, ê²€ìƒ‰ëœ "
+"ìš´ì˜ ì²´ì œë¥¼ 부팅 옵션 목ë¡ì— ìžë™ìœ¼ë¡œ 추가할 수 있습니다."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"ì»´í“¨í„°ì— ìš´ì˜ ì²´ì œê°€ 여러 ê°œ ì„¤ì¹˜ëœ ê²½ìš°ë¼ë©´, ì´ ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ëŠ” 게 ì¢‹ì„ ê²ë‹ˆ"
+"다. 하지만 컴퓨터가 LVMì„ í†µí•´ ë˜ëŠ” ë””ìŠ¤í¬ ìž¥ì¹˜ì— ì§ì ‘ 게스트 ìš´ì˜ ì²´ì œê°€ 설"
+"치ë˜ì–´ 있는 호스트 컴퓨터ë¼ë©´, os-prober를 실행하면 os-proberì—ì„œ íŒŒì¼ ì‹œìŠ¤í…œ"
+"ì„ ë§ˆìš´íŠ¸í•´ì„œ 검색하기 ë•Œë¬¸ì— ì´ ê²ŒìŠ¤íŠ¸ ìš´ì˜ ì²´ì œê°€ ì†ìƒë  수 있습니다."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD 명령어:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ë‹¤ìŒ kFreeBSD 명령어를 /etc/default/grub íŒŒì¼ ë˜ëŠ” GRUB êµ¬ë²„ì „ì˜ menu.lstì˜ "
+"`kopt' 파ë¼ë¯¸í„°ì—ì„œ 뽑아냈습니다. 명령어가 올바른지 확ì¸í•˜ê³  필요하다면 수정"
+"하십시오. 명령어는 비워 둘 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD 기본 명령어:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"ë‹¤ìŒ ë¬¸ìžì—´ì„ 기본 메뉴 í•­ëª©ì˜ kFreeBSD 파ë¼ë¯¸í„°ë¡œ 사용합니다. 복구 모드ì—ì„œ"
+"는 사용하지 않습니다."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map 파ì¼ì„ 다시 만들었습니다"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "ì•ˆì •ëœ ìž¥ì¹˜ ì´ë¦„ì„ ì‚¬ìš©í•˜ë„ë¡ /boot/grub/device.map 파ì¼ì„ 다시 ì¼ìŠµë‹ˆë‹¤. "
+#~ "ëŒ€ë¶€ë¶„ì˜ ê²½ìš° ì´ë ‡ê²Œ 하면 앞으로 ë˜ ìˆ˜ì •í•  필요가 매우 줄어듭니다. 그리고 "
+#~ "GRUBì—ì„œ 만들어낸 부팅 메뉴 í•­ëª©ì€ ì˜í–¥ì„ 받지 않습니다."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "하지만 ì‹œìŠ¤í…œì— ì—¬ëŸ¬ ê°œì˜ ë””ìŠ¤í¬ê°€ 들어 있으므로, ì‹œìŠ¤í…œì´ ê³¼ê±° 장치 맵 파"
+#~ "ì¼ì— ì˜ì¡´í•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. 사용ìžê°€ 수정한 부팅 메뉴 항목 ì¤‘ì— GRUB ë°©ì‹ "
+#~ "(hdN 형ì‹) ë“œë¼ì´ë¸Œ 번호를 사용하는 í•­ëª©ì´ ë“¤ì–´ìžˆëŠ”ì§€ 확ì¸í•˜ì‹­ì‹œì˜¤."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "ì´ ë©”ì‹œì§€ê°€ ì´í•´ë˜ì§€ 않거나, 수정한 부팅 메뉴 í•­ëª©ì´ ì—†ìœ¼ë©´ ì´ ë©”ì‹œì§€ë¥¼ 무"
+#~ "시하십시오."
diff --git a/debian/po/lt.po b/debian/po/lt.po
new file mode 100644
index 0000000..aea7592
--- /dev/null
+++ b/debian/po/lt.po
@@ -0,0 +1,474 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Rimas Kudelis <rq@akl.lt>, 2012, 2014, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-20 09:03+0300\n"
+"Last-Translator: Rimas Kudelis <rq@akl.lt>\n"
+"Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
+"Language: lt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"(n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Virtaal 0.7.1\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Paleisti grandininiu būdu iš „menu.lst“?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"„GRUB“ atnaujinimo scenarijai aptiko senojo „GRUB“ konfigūracinius failus „/"
+"boot/grub“ aplanke."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Norint pakeisti senÄ…jÄ… sistemoje esanÄiÄ… „GRUB“ versijÄ…, rekomenduojama "
+"pirmiausia papildyti jos konfigūracinį failą „/boot/grub/menu.lst“, "
+"nurodant, kad ji paleistų „GRUB 2“ grandininiu būdu. Šį žingsnį galima "
+"automatiškai atlikti dabar."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Prieš įrašant „GRUB 2“ į disko paleidimo įrašą, rekomenduojama išbandyti "
+"grandininį jos paleidimą iš „menu.lst“ ir įsitikinti, jog „GRUB 2“ sąranka "
+"veikia tinkamai."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Koks bebūtų Jūsų sprendimas, vėliau MBR turinį galėsite perrašyti „GRUB 2“ "
+"ar vėlesne versija, „root“ teisėmis paleisdami komandą:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Įrenginiai „GRUB“ diegimui:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Atnaujinamas „grub-pc“ paketas. Šiame meniu galite pasirinkti, ar kuriems "
+"nors įrenginiams komanda „grub-install“ turėtų būti paleidžiama automatiškai."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Daugumoje atvejų rekomenduojama automatiškai vykdyti „grub-install“, kad "
+"būtų išvengta neatitikimų tarp pagrindinio „GRUB“ atvaizdžio ir „GRUB“ "
+"modulių ar „grub.cfg“ failo."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Jeigu tiksliai nežinote, kurį diską kompiuterio BIOS laiko paleidimo disku, "
+"galite įdiegti „GRUB“ į visus diskus – dažniausiai tai yra nebloga mintis."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Pastaba: „GRUB“ galima įdiegti ir į skaidinių paleidimo įrašus, todėl sąraše "
+"yra ir keletas skaidinių. Vis dėlto, šiuo atveju „GRUB“ tektų naudoti blokų "
+"sąrašo (blocklist) mechanizmą, kuris yra mažiau patikimas, todėl paprastai "
+"nepatartinas."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"AnksÄiau „GRUB“ paleidyklÄ— buvo įdiegta į diskÄ…, kuris dabar nebeprieinamas "
+"arba kurio identifikatorius dÄ—l kokių nors priežasÄių pakeistas. Svarbu "
+"užtikrinti pagrindinio „GRUB“ atvaizdžio, „GRUB“ modulių ir „grub.cfg“ failo "
+"suderinamumą. Patikrinkite pasirinkimus dar kartą ir įsitikinkite, jog "
+"„GRUB“ paleidyklė bus įrašyta į reikiamus paleidimo įrenginius."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "„GRUB“ įrašyti į paleidimo įrenginį nepavyko. Ar tęsti?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Nepavyko „GRUB“ įdiegti į šiuos įrenginius:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ar tęsti, nepaisant problemos? Jos neišsprendus, kompiuteris gali tinkamai "
+"nepasileisti."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "„GRUB“ įrašyti į paleidimo įrenginį nepavyko. Bandyti dar kartą?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"GalbÅ«t „GRUB“ Jums pavyks įdiegti į kurį nors kitÄ… įrenginį, taÄiau "
+"turėtumėte įsitikinti, jog sistemą iš to įrenginio pavyks paleisti. "
+"Priešingu atveju šis atnaujinimas iš senosios „GRUB“ versijos bus atšauktas."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Ar tęsti neįdiegus „GRUB“?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Galima „GRUB“ paleidyklės ir nediegti į jokį įrenginį. Tokiu atveju ji nebus "
+"tinkamai sukonfigūruota ir kitąkart paleidus šį kompiuterį, bus bandoma "
+"įvykdyti tai, kas paleidimo sektoriuje buvo iki šiol. Jeigu jame įrašyta "
+"ankstesnė „GRUB 2“ versija, tikėtina, jog jai nepavyks įkelti reikiamų "
+"modulių ar tinkamai interpretuoti konfigūracinio failo."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Jeigu Å¡iame kompiuteryje jau naudojama kita paleidyklÄ— ir JÅ«s norite ja "
+"naudotis toliau, arba jeigu paleidyklÄ—s diegti nereikia dÄ—l kitų priežasÄių, "
+"tuomet tiesiog tęskite. Priešingu atveju „GRUB“ reikėtų kur nors įdiegti."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Pašalinti „GRUB 2“ iš „/boot/grub“?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Ar pašalinti visus „GRUB 2“ failus iš „/boot/grub“ aplanko?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Tai atlikus, sistemą paleisti gali tapti neįmanoma, nebent joje įdiegta kita "
+"paleidyklÄ—."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Užbaigti migraciją į „GRUB 2“ dabar?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Å ioje sistemoje vis dar likÄ™ įdiegtų senosios „GRUB“ failų, taÄiau joje yra "
+"įdiegti ir „GRUB 2“ paleidimo įrašai šiuose diskuose:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Panašu, kad senoji „GRUB“ nebenaudojama ir kad Jums derėtų atnaujinti „GRUB "
+"2“ atvaizdžius šiuose diskuose ir užbaigti migraciją į „GRUB 2“, pašalinant "
+"senosios „GRUB“ failus. Neatnaujinus šių „GRUB 2“ atvaizdžių, naujai įdiegti "
+"paketai gali būti su jais nesuderinami. Tokiu atveju sistema gali apskritai "
+"nepasileisti."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Paprastai derėtų užbaigti migraciją į „GRUB 2“, nebent šiuos paleidimo "
+"įrašus sukūrė „GRUB 2“ versija, įdiegta su kokia nors kita operacine sistema."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "„Linux“ komandos eilutė:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Iš „/etc/default/grub“ failo arba senosios „GRUB“ konfigūraciniame faile "
+"„menu.lst“ nurodyto „kopt“ parametro išrinkta žemiau pateikta „Linux“ "
+"komandos eilutÄ—. Patikrinkite, ar ji tinkama ir jei reikia, jÄ… "
+"patikslinkite. Komandos eilutÄ— gali bÅ«ti ir tuÅ¡Äia."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Numatytoji „Linux“ komandos eilutė:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Ši eilutė bus naudojama kaip įprastiniai „Linux“ branduolio parametrai, bet "
+"ne pasirinkus atkūrimo veikseną."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Papildomai priverstinai įdiegti į EFI keiÄiamųjų laikmenų keliÄ…?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Kai kurios EFI veiksena veikianÄios sistemos turi klaidų ir negeba "
+"korektiškai dirbti su naujomis paleidyklėmis. „GRUB“ paleidyklę papildomai "
+"priverstinai įdiegus į EFI keiÄiamųjų laikmenų keliÄ…, turÄ—tų bÅ«ti "
+"užtikrintas korektiškas „Debian“ paleidimas tokiose sistemose. Kita vertus, "
+"tai galimai užkirstų kelią paleisti kitas operacines sistemas, paleidimui "
+"taip pat naudojanÄias šį keliÄ…. Jeigu taip nutiktų, jums tektų užtikrinti, "
+"kad „GRUB“ paleidyklė sukonfigūruota tinkamai ir geba korektiškai paleisti "
+"Å¡ias operacines sistemas."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+"Ar nustatyti NVRAM parametrus taip, kad būtų automatiškai paleidžiama "
+"„Debian“ sistema?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"„GRUB“ paleidyklė gali nustatyti jūsų sistemos NVRAM parametrus, kad ją "
+"įjungus, būtų automatiškai paleidžiama „Debian“ sistema. Būna situacijų, kai "
+"tai nepageidautina, pavyzdžiui, jei jūsų sistemos NVRAM parametrai nustatyti "
+"taip, kad kaskart pasileisdama, ji susisiektų su PXE serveriu, ir jūs "
+"nenorite Å¡io scenarijaus keisti."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "„kFreeBSD“ komandos eilutė:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Iš „/etc/default/grub“ failo arba senosios „GRUB“ konfigūraciniame faile "
+"„menu.lst“ nurodyto „kopt“ parametro išrinkta žemiau pateikta „kFreeBSD“ "
+"komandos eilutÄ—. Patikrinkite, ar ji tinkama ir jei reikia, jÄ… "
+"patikslinkite. Komandos eilutÄ— gali bÅ«ti ir tuÅ¡Äia."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Numatytoji „kFreeBSD“ komandos eilutė:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Ši eilutė bus naudojama kaip įprastiniai „kFreeBSD“ branduolio parametrai, "
+"bet ne pasirinkus atkūrimo veikseną."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "Failas „boot/grub/device.map“ pergeneruotas"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Failas „/boot/grub/device.map“ perrašytas taip, kad naudotų stabilius "
+#~ "įrenginių vardus. Tai turėtų žymiai sumažinti poreikį šį failą ateityje "
+#~ "redaguoti, o „GRUB“ sugeneruotų paleidimo įrašų tai neturėtų įtakoti."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "TaÄiau kadangi Å¡iame kompiuteryje yra daugiau nei vienas diskas, gali "
+#~ "būti, jog sistema pasikliauna senuoju įrenginių planu. Patikrinkite, ar "
+#~ "neturite rankiniu bÅ«du sukÅ«rÄ™ paleidimo įrašų, naudojanÄių „(hdN)“ diskų "
+#~ "numeravimÄ… ir jei reikia, juos patikslinkite."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Jeigu nesuprantate šio pranešimo, arba neturite rankiniu būdu sukurtų "
+#~ "paleidimo įrašų, šio pranešimo galite nepaisyti."
diff --git a/debian/po/lv.po b/debian/po/lv.po
new file mode 100644
index 0000000..f723c11
--- /dev/null
+++ b/debian/po/lv.po
@@ -0,0 +1,478 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# RÅ«dolfs Mazurs <rudolfs.mazurs@gmail.com>, 2012, 2015.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-30 22:01+0300\n"
+"Last-Translator: RÅ«dolfs Mazurs <rudolfs.mazurs@gmail.com>\n"
+"Language-Team: Latvian <lata-l10n@googlegroups.com>\n"
+"Language: lv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
+"2);\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "SecÄ«gi ielÄdÄ“t no menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB uzlaboÅ¡anas skripti ir atklÄjuÅ¡i GRUB mantotos iestatÄ«jumus mapÄ“ /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Lai aizvietotu mantoto GRUB versiju savÄ sistÄ“mÄ, iesakÄm pielÄgot /boot/"
+"grub/menu.lst, lai tÄ ielÄdÄ“ GRUB 2 palaiÅ¡anas attÄ“lu no esoÅ¡Äs GRUB "
+"mantotÄs instalÄcijas. Tagad Å¡o soli var veikt automÄtiski."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Ieteicams pieņemt secÄ«gÄs ielÄdes (chainloading) GRUB 2 no menu.lst un "
+"pÄrliecinÄties, ka jaunais GRUB 2 darbojas, pirms no ierakstÄ«t MBR "
+"(galvenajÄ palaiÅ¡anas ierakstÄ)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Lai kÄds bÅ«tu lÄ“mums, jÅ«s varat aizvietot veco MBR attÄ“lu ar GRUB 2 vÄ“lÄk, "
+"dodot sekojoÅ¡Äs komandas ar root tiesÄ«bÄm:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB instalēšanas ierīces:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Tiek uzlabota grub-pc pakotne. Šī izvēlne ļauj jums izvēlēties ierīces, "
+"kuras grub-install vajadzētu palaists (ja vajag)."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"AutomÄtiska grub-install palaiÅ¡ana ir ieteicama vairumÄ gadÄ«jumu, lai "
+"nepieļautu, ka instalētais GRUB attēls būtu asinhrons ar GRUB moduļiem vai "
+"grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ja nezinÄt, kuru dzini BIOS ir nozÄ«mÄ“jis kÄ palaiÅ¡anas dzini, tad bieži ir "
+"ieteicams instalēt GRUB uz visiem dziņiem."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Å…emiet vÄ“rÄ â€” ir iespÄ“jams uzinstalÄ“t GRUB arÄ« uz nodalÄ«juma palaiÅ¡anas "
+"ierakstiem, un Å¡eit tiek piedÄvÄti daži noderÄ«gi nodalÄ«jumi. Bet tas liek "
+"GRUB izmantot bloÄ·Ä“Å¡anas saraksta mehÄnismu, kas padara to mazÄk uzticamu, "
+"tÄtad nerekomendÄ“jamu."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB palaidējs iepriekš bija uzinstalēts uz diska, kas vairs nav šeit, vai "
+"kaut kÄda iemesla dēļ tika mainÄ«ts tÄ unikÄlais identifikators. Ir svarÄ«gi "
+"nodroÅ¡inÄt, ka instalÄ“tais GRUB pamata attÄ“ls ir sinhrons ar GRUB moduļiem "
+"un grub.cfg. LÅ«dzu, vÄ“lreiz pÄrliecinieties, ka GRUB ir uzrakstÄ«ts uz "
+"atbilstoÅ¡Äm palaiÅ¡anas ierÄ«cÄ“m."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "NeizdevÄs ierakstÄ«t GRUB uz palaiÅ¡anas ierÄ«ces — turpinÄt?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "NeizdevÄs uzinstalÄ“t GRUB uz Å¡Ä«m ierÄ«cÄ“m:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Vai tomÄ“r vÄ“laties turpinÄt? Ja tÄ, dators varÄ“tu nespÄ“t pareizi palaisties."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "NeizdevÄs ierakstÄ«t GRUB uz palaiÅ¡anas ierÄ«ces — mÄ“Ä£inÄt atkal?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"IespÄ“jams, jÅ«s varat uzinstalÄ“t GRUB uz kÄdas citas ierÄ«ces, bet jums "
+"jÄpÄrliecinÄs, ka sistÄ“ma varÄ“s no tÄs ierÄ«ces palaisties. CitÄdi uzlaboÅ¡ana "
+"no GRUB mantojuma tiks atcelta."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "TurpinÄt bez GRUB instalÄ“Å¡anas?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"JÅ«s varat izvÄ“lÄ“ties neinstalÄ“t GRUB uz nevienas ierÄ«ces. Ja turpinÄsiet, "
+"palaidējs varētu nebūt pareizi konfigurēts, un kad dators tiks palaists, tas "
+"izmantos to konfigurÄciju, kas jau atrodas palaiÅ¡anas sektorÄ. Ja palaiÅ¡anas "
+"sektorÄ jau ir vecÄka GRUB 2 versija, tÄ varÄ“tu nespÄ“t ielÄdÄ“t moduļus vai "
+"apstrÄdÄt esoÅ¡o konfigurÄcijas datni."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ja jÅ«s jau izmantojat citu palaidÄ“ju un vÄ“laties to turpinÄt izmantot, vai "
+"arÄ« Å¡Ä« ir Ä«paÅ¡a vide, kur nav vajadzÄ«gs palaidÄ“js, jums vajadzÄ“tu turpinÄt. "
+"CitÄdi, jums vajadzÄ“tu kaut kur uzinstalÄ“t GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Izņemt GRUB 2 no /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Vai vēlaties, lai visi GRUB 2 faili tiktu izņemti no /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Tas padarÄ«s sistÄ“mu nepalaižamu, ja vien nav uzinstalÄ“ts kÄds cits palaidÄ“js."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Pabeigt pÄrveidoÅ¡anu uz GRUB 2 tagad?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Å ajÄ sistÄ“mÄ vÄ“l aizvien ir uzinstalÄ“tas datnes no GRUB mantojuma palaidÄ“ja, "
+"bet tam tagad ir arī GRUB 2 palaišanas ieraksti, kas ir uzinstalēti uz šiem "
+"diskiem:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"IzskatÄs, ka GRUB mantojums vairs netiek izmantots, un jums vajadzÄ“tu "
+"pabeigt GRUB 2 attÄ“lu uzlaboÅ¡anu uz Å¡iem diskiem un pabeigt pÄreju uz GRUB "
+"2, izdzÄ“Å¡ot vecÄs GRUB mantojuma datnes. Ja nevÄ“laties uzlabot Å¡os GRUB 2 "
+"attÄ“lus, tad tie varÄ“tu nebÅ«t savietojami ar jaunajÄm pakotnÄ“m un var neļaut "
+"sistēmai pareizi palaisties."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Jums vajadzÄ“tu pabeigt pÄreju uz GRUB 2, izņemot, ja Å¡os palaiÅ¡anas "
+"ierakstus izveidoja GRUB 2 instalÄcija no kÄdas citas operÄ“tÄjsistÄ“mas."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux komandrinda:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"SekojoÅ¡Ä Linux komandrinda tika izvilkta no /etc/default/grub vai `kopt' "
+"parametra GRUB mantojuma menu.lst. LÅ«dzu, pÄrliecinieties, ka tÄ ir pareiza "
+"un, ja vajag, mainiet to. Komandrinda drīkst būt tukša."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux noklusējuma komandrinda:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"SekojoÅ¡Ä virkne tiks izmantota kÄ Linux parametri izvÄ“lnes noklusÄ“juma "
+"ierakstam, bet ne sistÄ“mas atgÅ«Å¡anas režīmÄ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "ForsÄ“t papildu instalÄciju uz EFI noņemamÄ datu nesÄ“ja ceļa?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Dažas EFI sistÄ“mas ir satur kļūdas un nespÄ“j pareizi apstrÄdÄt jaunus "
+"sistÄ“mas ielÄdÄ“tÄjus. Ja forsÄ“siet GRUB instalÄ“Å¡anu uz EFI noņemamÄ datu "
+"nesÄ“ja ceļa, tam vajadzÄ“tu pÄrliecinÄties, ka Å¡Ä« sistÄ“ma pareizi ielÄdÄ“s "
+"Debian, neskatoties uz Å¡ÄdÄm problÄ“mÄm. Bet tas var liegt iespÄ“ju ielÄdÄ“t "
+"jebkuru citu operÄ“tÄjsistÄ“mu, kas ir atkarÄ«ga no Å¡Ä« ceļa. Ja tÄ, jums bÅ«s "
+"jÄpÄrliecinÄs, ka GRUB ir veiksmÄ«gi nokonfigurÄ“ts un varÄ“s veiksmÄ«gi ielÄdÄ“t "
+"citas OS instalÄcijas."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "AtjauninÄt NVRAM mainÄ«gos, lai automÄtiski ielÄdÄ“tu Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB var konfigurēt jūsu platformas NVRAM mainīgos, lai pēc sistēmas "
+"ieslÄ“gÅ¡anas ielÄdÄ“tu Debian. JÅ«s varÄ“tu vÄ“lÄ“ties izslÄ“gt Å¡o uzvedÄ«bu, lai "
+"nemainÄ«tu ielÄdes konfigurÄciju. PiemÄ“ram, ja jÅ«su NVRAM mainÄ«gie ir "
+"iestatÄ«ti tÄ, ka pie katras ielÄdes sistÄ“ma sazinÄs ar PXE serveri, Å¡is "
+"iestatÄ«jums saglabÄtu tÄdu uzvedÄ«bu."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"AutomÄtiski palaist operÄ“tÄjsistÄ“mu meklÄ“tÄju, lai atklÄtu un ielÄdÄ“tu citas "
+"OS?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB var izmantot operÄ“tÄjsistÄ“mu meklÄ“Å¡anas rÄ«ku, lai uz jÅ«su datora "
+"mÄ“Ä£inÄtu atklÄt citas operÄ“tÄjsistÄ“mas un automÄtiski pievienot tÄs pie "
+"ielÄdes opcijÄm."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Ja uz jÅ«su datora ir uzinstalÄ“tas vairÄkas operÄ“tÄjsistÄ“mas, jÅ«s visdrÄ«zÄk "
+"gribat Å¡o opciju. SavukÄrt, ja jÅ«su dators ir saimnieks viesa "
+"operÄ“tÄjsistÄ“mai, kas ir uzinstalÄ“ts caur LVM vai diska ierÄ«ci, tad "
+"operÄ“tÄjsistÄ“mu meklÄ“tÄjs var sabojÄt tÄs OS, jo, lai varÄ“tu meklÄ“t, tas "
+"montē datņu sistēmas."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD komandrinda:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"SekojoÅ¡Ä kFreeBSD komandrinda tika izvilkta no /etc/default/grub vai `kopt' "
+"parametra GRUB mantojuma menu.lst. LÅ«dzu, pÄrliecinieties, ka tÄ ir pareiza "
+"un, ja vajag, mainiet to. Komandrinda drīkst būt tukša."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD noklusējuma komandrinda:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"SekojoÅ¡Ä virkne tiks izmantota kÄ kFreeBSD parametri izvÄ“lnes noklusÄ“juma "
+"ierakstam, bet ne sistÄ“mas atgÅ«Å¡anas režīmÄ."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map tika reģistrēts"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Fails /boot/grub/device.map tika pÄrrakstÄ«ts, lai izmantotu stabilos "
+#~ "ierÄ«Äu nosaukumus. VairumÄ gadÄ«jumu tam vajadzÄ“tu bÅ«tiski samazinÄt "
+#~ "vajadzÄ«bu to mainÄ«t nÄkotnÄ“, un palaiÅ¡anas izvÄ“lnes ierakstiem, ko "
+#~ "veidojis GRUB, nevajadzētu tikt skartiem."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "TomÄ“r, tÄ kÄ sistÄ“mÄ atrodas vairÄki diski, iespÄ“jams, ka sistÄ“ma ir "
+#~ "atkarÄ«ga no vecÄs ierÄ«Äu kartes. LÅ«dzu, pÄrliecinieties, vai ir kÄdi "
+#~ "pielÄgoti palaiÅ¡anas izvÄ“lnes ieraksti, kas balstÄs uz GRUB (hdN) disku "
+#~ "numurÄ“Å¡anas, un atjauniniet tos, ja tÄ ir."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ja jÅ«s nesaprotat Å¡o ziņojumu, vai arÄ« nav pielÄgotu palaiÅ¡anas izvÄ“lnes "
+#~ "ieraktu, jūs varat ignorēt šo ziņojumu."
diff --git a/debian/po/mr.po b/debian/po/mr.po
new file mode 100644
index 0000000..3d106b8
--- /dev/null
+++ b/debian/po/mr.po
@@ -0,0 +1,450 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# localuser <sampada.n@rediffmail.com>, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2014-12-24 20:56+0530\n"
+"Last-Translator: localuser <sampada.n@rediffmail.com>\n"
+"Language-Team: C-DAC/Sampada\n"
+"Language: mr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.7.1\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst मधून चेनलोड करायचे?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "गà¥à¤°à¤¬ शà¥à¤°à¥‡à¤£à¥€à¤µà¤°à¥à¤§à¤¨ सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿà¥à¤¸à¤¨à¤¾ /boot/grub येथे गà¥à¤°à¤¬ लिगसी संरचना आढळली आहे."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"तà¥à¤®à¤šà¥à¤¯à¤¾ पà¥à¤°à¤£à¤¾à¤²à¥€à¤¤à¥€à¤² गà¥à¤°à¤¬à¤šà¥€ लिगसी आवृतà¥à¤¤à¥€ बदलणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ अशी शिफारस केली जाते की तà¥à¤®à¤šà¥à¤¯à¤¾ "
+"असà¥à¤¤à¤¿à¤¤à¥à¤µà¤¾à¤¤à¥€à¤² गà¥à¤°à¤¬ लिगसी संरचनेमधून /boot/grub/menu.lst हा गà¥à¤°à¤¬ 2 आरंभ पà¥à¤°à¤¤à¤¿à¤®à¤¾ लोड "
+"करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ बदलणà¥à¤¯à¤¾à¤¤ यावा. ही पायरी आता सà¥à¤µà¤¯à¤‚चलितपणे करता येऊ शकते."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"अशी शिफारस आहे, की तà¥à¤®à¥à¤¹à¥€ menu.lst मधून गà¥à¤°à¤¬ 2 चेनलोड करायचे सà¥à¤µà¥€à¤•à¤¾à¤°à¤¾à¤µà¥‡, व à¤à¤®à¤¬à¥€à¤†à¤° "
+"(मà¥à¤–à¥à¤¯ आरंभ अभिलेख) यानà¥à¤¸à¤¾à¤° लिहिला जाणà¥à¤¯à¤¾à¤ªà¥‚रà¥à¤µà¥€ नवीन गà¥à¤°à¤¬ 2 संरचना कारà¥à¤¯ करत आहे याची "
+"खातरजमा करावी."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"तà¥à¤®à¤šà¤¾ निरà¥à¤£à¤¯ काहीही असला तरी, तà¥à¤®à¥à¤¹à¥€ नंतर मूल मà¥à¤¹à¤£à¥‚न खालील आजà¥à¤žà¤¾ देऊन जà¥à¤¨à¥€ à¤à¤®à¤¬à¥€à¤†à¤° "
+"पà¥à¤°à¤¤à¤¿à¤®à¤¾ गà¥à¤°à¤¬ 2 ने बदलू शकता:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "गà¥à¤°à¤¬ अधिषà¥à¤ à¤¾à¤ªà¤¨à¤¾ उपकरणे:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"गà¥à¤°à¤¬-पीसी पॅकेज शà¥à¤°à¥‡à¤£à¤¿à¤µà¤°à¥à¤§à¤¿à¤¤ केले जात आहे. कोणतà¥à¤¯à¤¾ उपकरणांसाठी गà¥à¤°à¤¬-इनà¥à¤¸à¥à¤Ÿà¤¾à¤² सà¥à¤µà¤¯à¤‚चलितपणे "
+"चालवले जावे ते या मेनà¥à¤¯à¥‚दà¥à¤µà¤¾à¤°à¥‡ तà¥à¤®à¥à¤¹à¥€ निवडू शकता."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"गà¥à¤°à¤¬ गाभा पà¥à¤°à¤¤à¤¿à¤®à¥‡à¤šà¥à¤¯à¤¾ गà¥à¤°à¤¬ मोडà¥à¤¯à¥‚लà¥à¤¸ वा grub.cfg शी विसंवादाला आळा बसणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ बहà¥à¤¤à¤¾à¤‚श "
+"परिसà¥à¤¥à¤¿à¤¤à¥€à¤‚मधà¥à¤¯à¥‡ गà¥à¤°à¤¬-इनà¥à¤¸à¥à¤Ÿà¤¾à¤² सà¥à¤µà¤¯à¤‚चलितपणे चालवले जाणà¥à¤¯à¤¾à¤šà¥€ शिफारस केली जाते."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"तà¥à¤®à¤šà¥à¤¯à¤¾ बायोसने कोणता डà¥à¤°à¤¾à¤ˆà¤µà¥à¤¹ आरंभ डà¥à¤°à¤¾à¤ˆà¤µà¥à¤¹ मà¥à¤¹à¤£à¥‚न ठरवला आहे याची तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ खातà¥à¤°à¥€ नसलà¥à¤¯à¤¾à¤¸, "
+"गà¥à¤°à¤¬ सरà¥à¤µà¤š डà¥à¤°à¤¾à¤ˆà¤µà¥à¤¹à¥à¤œà¤µà¤° अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ करणे बहà¥à¤¤à¥‡à¤•à¤¦à¤¾ चांगले ठरते."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"नोंद: विभाजन आरंभ नोंदींमधà¥à¤¯à¥‡à¤¹à¥€ गà¥à¤°à¤¬ अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ करणे शकà¥à¤¯ आहे, व यासाठी काही सà¥à¤¯à¥‹à¤—à¥à¤¯ "
+"विभाजने येथे दरà¥à¤¶à¤µà¤²à¥€ आहेत. तथापि, यामà¥à¤³à¥‡ गà¥à¤°à¤¬à¤²à¤¾ बà¥à¤²à¥‰à¤•à¤²à¤¿à¤¸à¥à¤Ÿ यंतà¥à¤°à¤£à¤¾ वापरणे भाग पडते, जà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ "
+"तà¥à¤¯à¤¾à¤šà¥€ विशà¥à¤µà¤¾à¤¸à¤¾à¤°à¥à¤¹à¤¤à¤¾ कमी होते व मà¥à¤¹à¤£à¥‚न याची शिफारस केली जात नाही."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"गà¥à¤°à¤¬ आरंभ सूचक पूरà¥à¤µà¥€ जà¥à¤¯à¤¾ डिसà¥à¤•à¤µà¤° अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ केला होता ती आता असà¥à¤¤à¤¿à¤¤à¥à¤µà¤¾à¤¤ नाही, वा काही "
+"कारणासà¥à¤¤à¤µ तिचे विशिषà¥à¤Ÿ ओळखचिनà¥à¤¹ बदलले गेले आहे. अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ केलेली गà¥à¤°à¤¬ गाभा पà¥à¤°à¤¤à¤¿à¤®à¤¾ गà¥à¤°à¤¬ "
+"मोडà¥à¤¯à¥‚लà¥à¤¸ व grub.cfg यांचà¥à¤¯à¤¾à¤¶à¥€ सà¥à¤¸à¤‚वादी राहणे महतà¥à¤µà¤¾à¤šà¥‡ आहे. कृपया गà¥à¤°à¤¬ सà¥à¤¯à¥‹à¤—à¥à¤¯ आरंभ उपकरणांवर "
+"लिहिला जात आहे याची पà¥à¤¨à¥à¤¹à¤¾ खातरजमा करा."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} à¤à¤®à¤¬à¥€; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} à¤à¤®à¤¬à¥€; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "आरंभ उपकरणावर गà¥à¤°à¤¬ लिहिणे फसले - सà¥à¤°à¥‚ ठेवायचे?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "खालील उपकरणांवर गà¥à¤°à¤¬ अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ करणे असफल à¤à¤¾à¤²à¥‡:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ तरीही पà¥à¤¢à¥‡ जायचेय? असे केलà¥à¤¯à¤¾à¤¸, तà¥à¤®à¤šà¤¾ संगणक कदाचित वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¿à¤¤ सà¥à¤°à¥‚ होऊ शकणार नाही."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "आरंभ उपकरणावर गà¥à¤°à¤¬ लिहिणे फसले - पà¥à¤¨à¥à¤¹à¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ करायचा?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"तà¥à¤®à¥à¤¹à¥€ गà¥à¤°à¤¬ अनà¥à¤¯ कोणतà¥à¤¯à¤¾à¤¹à¥€ उपकरणावर अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ करू शकता, पण तà¥à¤¯à¤¾ उपकरणावरून तà¥à¤®à¤šà¥€ "
+"पà¥à¤°à¤£à¤¾à¤²à¥€ आरंभ करू शकते याची खातरजमा तà¥à¤®à¥à¤¹à¥€ केली पाहिजे. अनà¥à¤¯à¤¥à¤¾, लीगसी गà¥à¤°à¤¬à¤šà¥‡ शà¥à¤°à¥‡à¤£à¤¿à¤µà¤°à¥à¤§à¤¨ "
+"रदà¥à¤¦ केले जाईल."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "गà¥à¤°à¤¬ अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ न करता पà¥à¤¢à¥‡ जायचे?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"कोणतà¥à¤¯à¤¾à¤¹à¥€ उपकरणांवर गà¥à¤°à¤¬ अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ न करणà¥à¤¯à¤¾à¤šà¥‡ तà¥à¤®à¥à¤¹à¥€ निवडले आहे. तà¥à¤®à¥à¤¹à¥€ पà¥à¤¢à¥‡ चालू ठेवलà¥à¤¯à¤¾à¤¸, "
+"हा आरंभ सूचक योगà¥à¤¯à¤°à¤¿à¤¤à¥à¤¯à¤¾ संरचित à¤à¤¾à¤²à¥‡à¤²à¤¾ नसू शकतो, व हा संगणक पà¥à¤¨à¥à¤¹à¤¾ सà¥à¤°à¥‚ होईल तेवà¥à¤¹à¤¾ बूट "
+"सेकà¥à¤Ÿà¤°à¤®à¤§à¥à¤¯à¥‡ आधी जे काही होते ते वापरेल. बूट सेकà¥à¤Ÿà¤°à¤®à¤§à¥à¤¯à¥‡ गà¥à¤°à¤¬ 2 ची आधीची आवृतà¥à¤¤à¥€ असेल, तर "
+"कदाचित तो मोडà¥à¤¯à¥à¤²à¥à¤¸ लोड करू शकणार नाही वा सदà¥à¤¯ संरचना फाईल हाताळू शकणार नाही."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"तà¥à¤®à¥à¤¹à¥€ आधीच अनà¥à¤¯ आरंभ सूचक वापरत असाल व तोच वापरणे सà¥à¤°à¥‚ ठेऊ इचà¥à¤›à¤¿à¤¤ असाल, वा तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ आरंभ "
+"सूचकाची गरज पडणार नाही असा हा विशेष आसमंत असेल, तर तà¥à¤®à¥à¤¹à¥€ तसेच पà¥à¤¢à¥‡ चालू ठेवावे. अनà¥à¤¯à¤¥à¤¾, "
+"तà¥à¤®à¥à¤¹à¥€ कोठेतरी गà¥à¤°à¤¬ अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ केला पाहिजे."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "/boot/grub मधून गà¥à¤°à¤¬ 2 काढून टाकायचा?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "/boot/grub मधून गà¥à¤°à¤¬ 2 चà¥à¤¯à¤¾ सरà¥à¤µ फायली तà¥à¤®à¥à¤¹à¥€ काढून टाकू इचà¥à¤›à¤¿à¤¤à¤¾?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "अनà¥à¤¯ आरंभ सूचक अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ न केलà¥à¤¯à¤¾à¤¸ यामà¥à¤³à¥‡ तà¥à¤®à¤šà¥€ पà¥à¤°à¤£à¤¾à¤²à¥€ आरंभ न होणà¥à¤¯à¤¾à¤œà¥‹à¤—ी होईल."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "गà¥à¤°à¤¬ 2 मधà¥à¤¯à¥‡ परिवरà¥à¤¤à¤¨ आता थांबवायचे?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"पà¥à¤°à¤£à¤¾à¤²à¥€à¤®à¤§à¥à¤¯à¥‡ अदà¥à¤¯à¤¾à¤ªà¤¹à¥€ लीगसी गà¥à¤°à¤¬ आरंभ सूचक अधिषà¥à¤ à¤¾à¤ªà¤¨à¥‡à¤¤à¥€à¤² फायली आहेत, पण तिचà¥à¤¯à¤¾à¤¤ आता "
+"खालील डिसà¥à¤•à¥à¤¸à¤µà¤° गà¥à¤°à¤¬ 2 आरंभ नोंदीही अधिषà¥à¤ à¤¾à¤ªà¤¿à¤¤ आहेत:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"गà¥à¤°à¤¬ लीगसी आता वापरात नसणà¥à¤¯à¤¾à¤šà¤¾ संभव आहे असे भासतेय, आणि या डिसà¥à¤•à¤µà¤° तà¥à¤®à¥à¤¹à¥€ तà¥à¤¯à¤¾à¤à¤µà¤œà¥€ गà¥à¤°à¤¬ "
+"2 पà¥à¤°à¤¤à¤¿à¤®à¤¾ शà¥à¤°à¥‡à¤£à¤¿à¤µà¤°à¥à¤§à¤¿à¤¤ केलà¥à¤¯à¤¾ पाहिजेत व गà¥à¤°à¤¬ लीगसी फायली काढून टाकून गà¥à¤°à¤¬ 2 मघà¥à¤¯à¥‡ परिवरà¥à¤¤à¤¨ "
+"पूरà¥à¤£ केले पाहिजे. तà¥à¤®à¥à¤¹à¥€ या गà¥à¤°à¤¬ 2 पà¥à¤°à¤¤à¤¿à¤®à¤¾ शà¥à¤°à¥‡à¤£à¤¿à¤µà¤°à¥à¤§à¤¿à¤¤ केलà¥à¤¯à¤¾ नाहीत, तर तà¥à¤¯à¤¾ नवीन पॅकेजेसशी "
+"अनà¥à¤°à¥‚प असणार नाहीत व तà¥à¤®à¤šà¥à¤¯à¤¾ पà¥à¤°à¤£à¤¾à¤²à¥€à¤šà¤¾ योगà¥à¤¯ आरंभ होणà¥à¤¯à¤¾à¤¤ अडथळा आणू शकतील."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"या आरंभ नोंदी अनà¥à¤¯ कोणतà¥à¤¯à¤¾à¤¤à¤°à¥€ पà¥à¤°à¤šà¤¾à¤²à¤¨ पà¥à¤°à¤£à¤¾à¤²à¥€à¤µà¤° गà¥à¤°à¤¬ 2 अधिषà¥à¤ à¤¾à¤ªà¤¨à¥‡à¤¨à¥‡ निरà¥à¤®à¤¾à¤£ केलेलà¥à¤¯à¤¾ "
+"नसलà¥à¤¯à¤¾à¤¸ तà¥à¤®à¥à¤¹à¥€ सामानà¥à¤¯à¤¤à¤ƒ गà¥à¤°à¤¬ 2 मघà¥à¤¯à¥‡ परिवरà¥à¤¤à¤¨ पूरà¥à¤£ केले पाहिजे."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "लिनकà¥à¤¸ आदेश ओळ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"पà¥à¤¢à¥€à¤² लिनकà¥à¤¸ आदेश ओळ /etc/default/grub गà¥à¤°à¤¬ लीगसीचà¥à¤¯à¤¾ menu.lst मधील `kopt' "
+"घटकमूलà¥à¤¯à¤¾à¤®à¤§à¥‚न मिळवली आहे. कृपया ती योगà¥à¤¯ आहे का, याची खातरजमा करा व आवशà¥à¤¯à¤•à¤¤à¤¾ असलà¥à¤¯à¤¾à¤¸ "
+"बदल करा. आदेश ओळ रिकामी ठेवणà¥à¤¯à¤¾à¤šà¥€ अनà¥à¤®à¤¤à¥€ असते."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "लिनकà¥à¤¸ मूलनिरà¥à¤§à¤¾à¤°à¥€à¤¤ आदेश ओळ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"मà¥à¤²à¤¨à¤¿à¤°à¥à¤§à¤¾à¤°à¤¿à¤¤ मेनà¥à¤¯à¥‚ नोंदीकरिता लिनकà¥à¤¸ घटकमूलà¥à¤¯à¥‡ मà¥à¤¹à¤£à¥‚न खालील शà¥à¤°à¥à¤‚खला वापरली जाईल, पण "
+"रिकवà¥à¤¹à¤°à¥€ मोडसाठी नाही."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "ईà¤à¤«à¤†à¤¯ काढणà¥à¤¯à¤¾à¤œà¥‹à¤—à¥à¤¯à¤¾ मिडीया मारà¥à¤—ात अतिरिकà¥à¤¤ अधिषà¥à¤ à¤¾à¤ªà¤¨à¤¾ जबरदसà¥à¤¤à¥€ करायची?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"काही ईà¤à¤«à¤†à¤¯-आधारित पà¥à¤°à¤£à¤¾à¤²à¥€ दोषपूरà¥à¤£ असतात व नवीन आरंभसूचकांना योगà¥à¤¯ रीतीने हाताळत "
+"नाहीत. तà¥à¤®à¥à¤¹à¥€ ईà¤à¤«à¤†à¤¯ काढणà¥à¤¯à¤¾à¤œà¥‹à¤—à¥à¤¯à¤¾ मिडीया मारà¥à¤—ात गà¥à¤°à¤¬à¤šà¥€ अतिरिकà¥à¤¤ अधिषà¥à¤ à¤¾à¤ªà¤¨à¤¾ जबरदसà¥à¤¤à¥€ "
+"केलà¥à¤¯à¤¾à¤¸, तà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ अशी समसà¥à¤¯à¤¾ असूनही ही पà¥à¤°à¤£à¤¾à¤²à¥€ डेबियन योगà¥à¤¯à¤°à¥€à¤¤à¥à¤¯à¤¾ आरंभ करेल याची खातà¥à¤°à¥€ "
+"होईल. तथापि, तà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ याच मारà¥à¤—ावर अवलंबून असणारी अनà¥à¤¯ à¤à¤–ादी पà¥à¤°à¤šà¤¾à¤²à¤¨ पà¥à¤°à¤£à¤¾à¤²à¥€ आरंभ "
+"होणà¥à¤¯à¤¾à¤šà¥€ कà¥à¤·à¤®à¤¤à¤¾ काढून टाकली जाऊ शकते. असे असलà¥à¤¯à¤¾à¤¸, अनà¥à¤¯ à¤à¤–ादी पà¥à¤°à¤£à¤¾à¤²à¥€ योगà¥à¤¯ रीतीने आरंभ "
+"होणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ गà¥à¤°à¤¬ यशसà¥à¤µà¥€à¤ªà¤£à¥‡ संरचित केला गेला असलà¥à¤¯à¤¾à¤šà¥€ खातरजमा तà¥à¤®à¥à¤¹à¥€ करणे गरजेचे आहे."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "केफà¥à¤°à¥€à¤¬à¥€à¤à¤¸à¤¡à¥€ आदेश ओळ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"पà¥à¤¢à¥€à¤² केफà¥à¤°à¥€à¤¬à¥€à¤à¤¸à¤¡à¥€ आदेश ओळ /etc/default/grub गà¥à¤°à¤¬ लीगसीचà¥à¤¯à¤¾ menu.lst मधील `kopt' "
+"घटकमूलà¥à¤¯à¤¾à¤®à¤§à¥‚न मिळवली आहे. कृपया ती योगà¥à¤¯ आहे का, याची खातरजमा करा व आवशà¥à¤¯à¤•à¤¤à¤¾ असलà¥à¤¯à¤¾à¤¸ "
+"बदल करा. आदेश ओळ रिकामी ठेवणà¥à¤¯à¤¾à¤šà¥€ अनà¥à¤®à¤¤à¥€ असते."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "केफà¥à¤°à¥€à¤¬à¥€à¤à¤¸à¤¡à¥€ मूलनिरà¥à¤§à¤¾à¤°à¥€à¤¤ आदेश ओळ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"मà¥à¤²à¤¨à¤¿à¤°à¥à¤§à¤¾à¤°à¤¿à¤¤ मेनà¥à¤¯à¥‚ नोंदीकरिता केफà¥à¤°à¥€à¤¬à¥€à¤à¤¸à¤¡à¥€ घटकमूलà¥à¤¯à¥‡ मà¥à¤¹à¤£à¥‚न खालील शà¥à¤°à¥à¤‚खला वापरली जाईल, पण "
+"रिकवà¥à¤¹à¤°à¥€ मोडसाठी नाही."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map पà¥à¤¨à¤°à¥à¤¨à¤¿à¤°à¥à¤®à¤¿à¤²à¤¾ गेला आहे"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "फाईल /boot/grub/device.map सà¥à¤¥à¥€à¤° उपकरण नावे वापरणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ पà¥à¤¨à¥à¤¹à¤¾ लिहिली गेली आहे. "
+#~ "बहà¥à¤¤à¤¾à¤‚श बाबतील, यामà¥à¤³à¥‡ तीत भविषà¥à¤¯à¤¾à¤¤ बदल करणà¥à¤¯à¤¾à¤šà¥€ गरज लकà¥à¤·à¤£à¥€à¤¯à¤°à¤¿à¤¤à¥à¤¯à¤¾ कमी à¤à¤¾à¤²à¥€ "
+#~ "पाहिजे, व गà¥à¤°à¤¬à¤¨à¥‡ निरà¥à¤®à¤¾à¤£ केलेलà¥à¤¯à¤¾ आरंभ मेनà¥à¤¯à¥‚ नोंदींवर परिणाम होता कामा नये."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "तथापि, पà¥à¤°à¤£à¤¾à¤²à¥€à¤®à¤§à¥à¤¯à¥‡ à¤à¤•à¤¾à¤¹à¥‚न अधिक डिसà¥à¤• असà¥à¤¤à¤¿à¤¤à¥à¤µà¤¾à¤¤ असलà¥à¤¯à¤¾à¤¨à¥‡, पà¥à¤°à¤£à¤¾à¤²à¥€ जà¥à¤¨à¥à¤¯à¤¾ उपकरण "
+#~ "नकाशावर अवलंबून असणे शकà¥à¤¯ आहे. गà¥à¤°à¤¬à¤šà¥à¤¯à¤¾ (hdN) डà¥à¤°à¤¾à¤ˆà¤µà¥à¤¹ कà¥à¤°à¤®à¤¾à¤‚कांवर विसंबणारà¥â€à¤¯à¤¾ à¤à¤–ादà¥à¤¯à¤¾ "
+#~ "आरंभ मेनà¥à¤¯à¥‚ नोंदी आहेत का हे कृपया तपासा, व आवशà¥à¤¯à¤•à¤¤à¤¾ भासलà¥à¤¯à¤¾à¤¸ तà¥à¤¯à¤¾ अदà¥à¤¯à¤¯à¤¾à¤µà¤¤ करा."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ या संदेशाचा अरà¥à¤¥ समजत नसेल, वा अशा आरंभ मेनà¥à¤¯à¥‚ नोंदी नसतील, तर तà¥à¤®à¥à¤¹à¥€ या "
+#~ "संदेशाकडे दà¥à¤°à¥à¤²à¤•à¥à¤· करू शकता."
diff --git a/debian/po/nb.po b/debian/po/nb.po
new file mode 100644
index 0000000..f8dfab3
--- /dev/null
+++ b/debian/po/nb.po
@@ -0,0 +1,453 @@
+# Norwegian Bokmål translation for grub2.
+# Copyright (C) 2010 grub2
+# This file is distributed under the same license as the grub2 package.
+# Hans Fredrik Nordhaug <hans@nordhaug.priv.no>, 2010-12.
+# Petter Reinholdtsen <pere@hungry.com>, 2019, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 08:34+0200\n"
+"Last-Translator: Petter Reinholdtsen <pere@hungry.com>\n"
+"Language-Team: Norwegian Bokmål <l10n-no@lister.huftis.org>\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 20.12.0\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Kjedelaste fra menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Oppgraderingsskriptene til GRUB har funnet et GRUB Legacy-oppsett i /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"For å erstatte Legacy-versjonen av GRUB på ditt system anbefales det at /"
+"boot/grub/menu.lst justeres til å laste GRUB 2 oppstartsbilde fra ditt "
+"eksisterende GRUB Legacy-oppsett. Dette steget kan utføres automatisk nå."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Det anbefales at du aksepterer å kjedelaste GRUB 2 fra menu.lst, og "
+"verifiserer at det nye GRUB 2-oppsettet virker før det skrives til MBR "
+"(Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Uavhengig av din avgjørelse kan du erstatte det gamle MBR-bildet med GRUB 2 "
+"senere ved å kjøre følgende kommando som root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB installasjonsenheter:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Pakken grub-pc blir oppgradert. Denne menyen lar deg velge hvilke enheter "
+"du vil at grub-install skal kjøres automatisk for, hvis noen."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Kjøring av grub-install automatisk anbefales i de fleste situasjoner for å "
+"forhindre at det installerte GRUB-kjernebildet kommer ut av synk med GRUB-"
+"moduler i grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Hvis du er usikker hvilken disk som er satt som oppstartsdisk i din BIOS, er "
+"det ofte en god ide å installere GRUB på alle diskene. "
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Merk: Det er mulig å installere GRUB til partisjonsoppstartsposter også, og "
+"noen passende partisjoner er foreslått her. Imidlertid tvinger dette GRUB "
+"til å bruke blocklist-mekanismen som ikke er like pålitelig og derfor ikke "
+"anbefalt."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB oppstartslasteren var tidligere installert på en disk som ikke lenger "
+"fins eller på en disk hvor den unike identifikatoren er endret av eller "
+"annen grunn. Det er viktig å være sikker på at det installerte GRUB-"
+"kjernebildet forblir i synk med GRUB-moduler og grub.cfg. Sjekk igjen at "
+"GRUB skrive til passende oppstartsenhet."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Klarte ikke skrive GRUB til oppstartsenhet - fortsette?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Klarte ikke installere GRUB på følgende enheter:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ønsker du å fortsette likevel? Hvis du fortsetter, vil kanskje ikke din "
+"datamaskin starte opp skikkelig."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Klarte ikke skrive GRUB til oppstartsenhet - prøve igjen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Du kan klare å installere GRUB på en annen enhet, selvom du bør sjekke at "
+"systemet ditt kan/vil starte opp fra den enheten. Ellers vil oppgraderingen "
+"fra GRUB Legacy bli avbrutt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Fortsett uten å installere GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Du har valgt å ikke installere GRUB på noen enhet. Hvis du fortsetter, vil "
+"oppstartslasteren kanskje ikke være skikkelig satt opp, og når denne "
+"datamaskinen starter opp neste gang vil den bruke det tidligere innholdet i "
+"oppstartssektoren. Hvis det er en tidligere versjon av GRUB 2 i "
+"oppstartsektoren, vil den kanskje ikke være i stand til å laste inn moduler "
+"eller håndtere den aktuelle konfigurasjonsfilen."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Hvis du allerede kjører en annen oppstartslaster og ønsker å fortsette med "
+"det, eller hvis dette er et spesielt miljø hvor du ikke har bruk for en "
+"oppstartslaster, så skal du fortsette likevel. Ellers, bør du installere "
+"GRUB et eller annet sted."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Fjern GRUB 2 fra /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Vil du at alle filer for GRUB 2 skal fjernes fra /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Dette vil gjøre at systemet ikke kan starte med mindre en annen "
+"oppstartslaster er installert."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Avslutt konvertering til GRUB 2 nå?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Dette systemet har fremdeles installert filer fra GRUB Legacy-"
+"oppstartslasteren, men systemet har nå også GRUB 2 oppstartsposter "
+"installert på disse diskene:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Det virker sannsynlig at GRUB Legacy ikke lenger er i bruk, og at du i "
+"steden for skal oppgradere GRUB 2-bildene på disse diskene og avslutte "
+"konverteringen til GRUB 2 ved å fjerne eldre GRUB Legacy-filer. Hvis du ikke "
+"oppgraderer disse GRUB 2-bildene, så er de kanskje ikke kompatible med de "
+"nye pakkene og kan få ditt system til å stoppe å starte opp skikkelig."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Du bør generelt avslutte konverteringen til GRUB 2 med mindre disse "
+"oppstartspostene ble opprettet av en GRUB 2-installasjon på et annet "
+"operativsystem."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Kommandolinje i Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Den følgende Linux-kommandolinjen ble trukket ut fra /etc/default/grub eller "
+"parameteren `kopt' i GRUB Legacys menu.lst. Verifiser at den er korrekt og "
+"endre den om nødvendig. Det er lov at kommandolinjen er tom."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Standardkommandolinje i Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Den følgende teksten vil bli brukt som Linux-parametre for "
+"standardmenupunktet, men ikke for gjenopprettelsesmodus."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Tving ekstra installasjon til EFI-stien for flyttbare media? "
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Noen EFI-baserte systemer har feil og feilhåndterer nye oppstartlastere. "
+"Hvis du tvinger en ekstra installasjon av GRUB til EFI-stien for flyttbare "
+"media, så bør dette sikre at systemet vil korrekt starte opp Debian på "
+"tross av slike feil. Dette kan dog fjerne muligheten for å starte opp et "
+"annet operativsystem som også er avhengig av denne stien. Hvis det er "
+"tilfelle, så vil du måtte sikre at GRUB lar seg sette opp korrekt for å være "
+"i stand til å starte opp andre operativsysteminstallasjoner."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Oppdatere NVRAM-variabler til å automatisk starte Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB kan sette opp din platforms NVRAM-variabler slik at den automatisk "
+"starter Debian når den slås på. Du kan dog foretrekke å koble ut denne "
+"oppførselen og hoppe over endringer i ditt oppstartoppsett. Hvis du for "
+"eksempel har satt opp dine NVRAM-variabler slik at systemet ditt kontakter "
+"en PXE-tjener ved hver oppstart, så kan du slik beholde opprinnelig "
+"oppførsel."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr "Kjør os-prober automatisk for å oppdage og starte opp andre OS-er?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB kan bruke verktøyet os-prober for a forsøke å spore opp andre"
+" operativsystemer "
+"på datamaskinen din, og legge dem automatisk til listen over oppstartvalg."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Hvis datamaskinen din har flere operativsystemer installert, så er dette"
+" antagelig "
+"det du ønsker. Derimot, hvis datamaskinen din er vert for"
+" gjeste-operativsystemer "
+"installert via LVM eller rå diskenheter, så kan bruk av os-prober forårsake"
+" skade på "
+"disse gjeste-operativsystemene når den monterer filsystemer for å lete etter"
+" ting."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Kommandolinje i kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Den følgende kFreeBSD-kommandolinjen ble trukket ut fra /etc/default/grub "
+"eller fra parameteren `kopt' i GRUB Legacys menu.lst. Verifiser at den er "
+"korrekt, og endre den om nødvendig. Det er lov at kommandolinjen er tom."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Standardkommandolinje i kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Den følgende teksten vil bli brukt som kFreeBSD-parametre for "
+"standardmenupunktet men ikke for gjenopprettelsesmodus."
diff --git a/debian/po/nl.po b/debian/po/nl.po
new file mode 100644
index 0000000..5770fa4
--- /dev/null
+++ b/debian/po/nl.po
@@ -0,0 +1,466 @@
+# Dutch translation of grub2 debconf templates.
+# Copyright (C) 2008-2011 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub2 package.
+# Paul Gevers <paul@climbing.nl>, 2008-2010.
+# Jeroen Schot <schot@a-eskwadraat.nl>, 2011.
+# Frans Spiesschaert <Frans.Spiesschaert@yucom.be>, 2014, 2017, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.06-13\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-26 21:05+0200\n"
+"Last-Translator: Frans Spiesschaert <Frans.Spiesschaert@yucom.be>\n"
+"Language-Team: Debian Dutch l10n Team <debian-l10n-dutch@lists.debian.org>\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.2.1\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Doorschakelen vanuit menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUBs opwaardeerscripts hebben een oude-stijl GRUB opstelling in /boot/grub "
+"gedetecteerd."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Om de oude-stijl versie van GRUB op uw systeem te vervangen wordt het "
+"aangeraden om het bestand /boot/grub/menu.lst zo te laten aanpassen dat er "
+"een GRUB 2 opstart-image wordt geladen vanuit uw bestaande oude-stijl GRUB "
+"opstelling. Deze stap kan nu automatisch worden uitgevoerd."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"U wordt aangeraden om het doorschakelen van GRUB 2 vanuit menu.lst te "
+"accepteren, en daarna te verifiëren dat de nieuwe GRUB 2 opstelling werkt "
+"voordat het in de MBR (Master Boot Record) wordt geïnstalleerd."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Waar u ook voor kiest, u kunt het oude MBR-image later door GRUB 2 vervangen "
+"door het volgende commando uit te voeren (met beheerdersrechten (root)):"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Apparaten waarop GRUB moet komen:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Het pakket grub-pc wordt bijgewerkt. Dit menu stelt u in staat om desgewenst "
+"de apparaten te selecteren waarvoor u wilt dat grub-install automatisch "
+"wordt uitgevoerd."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Het wordt over het algemeen aanbevolen om grub-install automatisch te laten "
+"uitvoeren om te voorkomen dat het geïnstalleerde image van de GRUB-kern niet "
+"langer gesynchroniseerd zou zijn met de modules van GRUB of met grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Indien u niet zeker weet welk station door het BIOS wordt gebruikt als "
+"opstartstation, is het vaak een goed idee om GRUB op alle stations te "
+"installeren."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Merk op dat het ook mogelijk is om GRUB naar opstartstructuren op partities "
+"te installeren. Enkele geschikte partities worden hier aangeboden. Dit wordt "
+"echter niet aangeraden omdat het GRUB dwingt om een bloklijstmechanisme te "
+"gebruiken waar het minder betrouwbaar van wordt."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Het GRUB opstartprogramma was voorheen geïnstalleerd op een schijf die niet "
+"langer aanwezig is, of waarvan de unieke identificatie om een of andere "
+"reden is veranderd. Het is belangrijk om ervoor te zorgen dat het "
+"geïnstalleerde image van de GRUB-kern gesynchroniseerd blijft met GRUB "
+"modules en grub.cfg. Controleer of GRUB wel naar de juiste opstartapparaten "
+"wordt geschreven."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Schrijven van GRUB naar opstartapparaat mislukt. Doorgaan?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Het installeren van GRUB op de volgende apparaten is mislukt: "
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Wilt u desondanks verder gaan? Verder gaan kan ervoor zorgen dat uw computer "
+"niet meer goed opstart."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Schrijven van GRUB naar opstartapparaat mislukt. Opnieuw proberen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"U kunt proberen om GRUB te installeren op een ander apparaat, maar het wordt "
+"aangeraden om eerst te controleren of u kunt opstarten vanaf dat apparaat. "
+"In het andere geval zal het opwaarderen van GRUB oude-stijl geannuleerd "
+"worden."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Verder gaan zonder GRUB te installeren?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"U heeft ervoor gekozen om GRUB op geen enkele schijf te installeren. Als u "
+"nu doorgaat zou het kunnen dat het opstartprogramma niet correct "
+"geconfigureerd is en dat de computer bij de volgende start de informatie "
+"gebruikt die vroeger in de opstartsector stond. Indien daar een eerdere "
+"versie van GRUB 2 staat, kan het zijn dat modules niet geladen kunnen worden "
+"of dat het huidige configuratiebestand niet verwerkt kan worden."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"U kunt verder gaan als u al een ander opstartprogramma gebruikt en dat wilt "
+"blijven gebruiken, of als dit een speciale omgeving is waar u geen "
+"opstartprogramma nodig heeft. In de overige gevallen zou u GRUB ergens "
+"moeten installeren."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "GRUB 2 uit /boot/grub verwijderen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Wilt u dat alle GRUB 2 bestanden worden verwijderd uit /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Dit heeft tot gevolg dat het systeem niet opgestart kan worden tenzij er een "
+"ander opstartprogramma is geïnstalleerd."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Wilt u het omschakelen naar GRUB 2 nu afronden?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Er staan op dit systeem nog steeds bestanden van het opstartprogramma GRUB "
+"oude-stijl, maar op de volgende schijven is nu ook een instantie van het "
+"opstartprogramma GRUB 2 geïnstalleerd:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Het lijkt erop dat GRUB oude-stijl niet langer gebruikt wordt en dat u er "
+"best aan doet om de images van GRUB 2 op die schijven op te waarderen en de "
+"omschakeling naar GRUB 2 af te ronden door de bestanden van GRUB oude-stijl "
+"te verwijderen. Indien u de GRUB 2 images niet opwaardeert, is het mogelijk "
+"dat ze incompatibel zijn met de nieuwe pakketten en kunnen ze uw systeem "
+"verhinderen correct op te starten."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"In het algemeen zult u de conversie naar GRUB 2 willen afmaken, tenzij deze "
+"opstart-images gemaakt zijn bij het installeren van GRUB 2 met een ander "
+"besturingssysteem."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux-commandoregel:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"De volgende Linux-commandoregel is gebaseerd op /etc/default/grub of op de "
+"'kopt'-parameter, gevonden in het bestand menu.lst van GRUB oude-stijl. "
+"Gelieve deze op correctheid te controleren en indien nodig aan te passen. De "
+"commandoregel mag leeg zijn."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Standaard Linux-commandoregel:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"De volgende regel zal, behalve in de herstelmodus, gebruikt worden voor de "
+"Linux parameters in de standaard menuoptie."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+"Een extra installatie verplichten in het EFI-pad voor verwijderbare media?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Sommige op EFI gebaseerde systemen bevatten fouten en gaan niet correct om "
+"met de nieuwe opstartprogramma's. Indien u een extra installatie van GRUB in "
+"het EFI-pad voor verwijderbare media vraagt, zou dit moeten garant staan "
+"voor het feit dat dit systeem ondanks dit probleem Debian toch correct zal "
+"opstarten. Dit kan er evenwel toe leiden dat andere besturingssystemen die "
+"ook van dit pad gebruik maken, niet langer in staat zullen zijn op te "
+"starten. In voorkomend geval zult u er moeten zorg voor dragen dat GRUB "
+"succesvol geconfigureerd wordt om eventueel andere geïnstalleerde "
+"besturingssystemen correct te kunnen opstarten."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "De NVRAM-variabelen aanpassen om automatisch Debian op te starten?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB kan de NVRAM-variabelen van uw platform zo configureren dat het "
+"automatisch Debian opstart wanneer het systeem aangezet wordt. Maar "
+"misschien wenst u dat gedrag liever niet te activeren en vermijdt u liever "
+"wijzigingen aan uw opstartconfiguratie. Indien bijvoorbeeld uw NVRAM-"
+"variabelen zo ingesteld werden dat uw systeem, telkens het opgestart wordt, "
+"een PXE-server contacteert, dan blijft op die manier dit gedrag gehandhaafd."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"os-prober automatisch uitvoeren om andere besturingssystemen te detecteren "
+"en op te starten?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB kan het gereedschap os-prober gebruiken om te proberen andere "
+"besturingssystemen op uw computer te detecteren en ze automatisch toe te "
+"voegen aan de lijst met opstartopties."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Als op uw computer meerdere besturingssystemen zijn geïnstalleerd, dan is "
+"dit waarschijnlijk wat u zoekt. Als uw computer echter een gastheer is voor "
+"gastbesturingssystemen die zijn geïnstalleerd via LVM of ruwe "
+"schijfapparaten, kan het uitvoeren van os-prober schade toebrengen aan die "
+"gast-besturingssystemen omdat het bestandssystemen aankoppelt om naar dingen "
+"te zoeken."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD-commandoregel:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"De volgende kFreeBSD-commandoregel is gebaseerd op /etc/default/grub of op "
+"de 'kopt'-parameter, gevonden in het bestand menu.lst van GRUB oude-stijl. "
+"Gelieve deze op correctheid te controleren en indien nodig aan te passen. De "
+"commandoregel mag leeg zijn."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Standaard kFreeBSD-commandoregel:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"De volgende regel zal, behalve in de herstelmodus, gebruikt worden voor de "
+"kFreeBSD parameters in de standaard menuoptie."
diff --git a/debian/po/pl.po b/debian/po/pl.po
new file mode 100644
index 0000000..9f3c10b
--- /dev/null
+++ b/debian/po/pl.po
@@ -0,0 +1,480 @@
+# Copyright (C) 2012
+# This file is distributed under the same license as the grub-pc package.
+#
+# Michał Kułach <michal.kulach@gmail.com>, 2012.
+# Åukasz Dulny <BartekChom@poczta.onet.pl>, 2014, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-20 14:11+0100\n"
+"Last-Translator: Åukasz Dulny <BartekChom@poczta.onet.pl>\n"
+"Language-Team: Polish <debian-l10n-polish@lists.debian.org>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 2.0\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Załadować z menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Skrypty aktualizacyjne GRUB-a wykryły ustawienia wersji GRUB Legacy w /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Aby zastąpić starą wersję GRUB-a w systemie, zaleca się dostosowanie /boot/"
+"grub/menu.lst do uruchomienia obrazu rozruchowego GRUB 2 z istniejÄ…cej "
+"instalacji GRUB Legacy. Ten krok zostanie teraz wykonany automatycznie."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Zaleca siÄ™ zaakceptowanie szeregowego uruchomienia (ang. chainload) GRUB 2 z "
+"menu.lst i zweryfikowanie poprawności nowych ustawień GRUB-a 2 przed jego "
+"zapisem do głównego sektora rozruchowego (ang. MBR - Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Niezależnie od podjętej teraz decyzji, zastąpienie starego obrazu MBR przez "
+"GRUB 2 można przeprowadzić później, wykonując następujące polecenie z "
+"uprawnieniami administratora:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "UrzÄ…dzenia do instalacji GRUB-a:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Pakiet grub-pc został zaktualizowany. To menu pozwala na wybranie urządzeń, "
+"dla których powinno zostać uruchomione automatycznie polecenie grub-install, "
+"jeśli to konieczne."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Automatyczne uruchomienie grub-install jest wskazane w większości "
+"przypadków, aby zapobiec straceniu synchronizacji z modułami GRUB-a w grub."
+"cfg przez jego główny obraz."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Jeśli nie jest się pewnym, który napęd został wybrany jako napęd rozruchowy "
+"przez BIOS komputera, dobrym pomysłem jest zainstalowanie GRUB-a na "
+"wszystkich dyskach."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Uwaga: jest możliwe zainstalowanie GRUB-a również w sektorach rozruchowych "
+"partycji i część odpowiednich partycji jest tu wypisana. Niestety, wymusza "
+"to na GRUB-ie użycie mechanizmu blocklist, który jest bardziej zawodny i, w "
+"zwiÄ…zku z tym, niezalecany."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Program rozruchowy GRUB był zainstalowany wcześniej na dysku który jest "
+"teraz nieobecny lub którego unikalny identyfikator zmienił się z jakiegoś "
+"powodu. Jest istotne, aby upewnić się, że główny obraz GRUB-a jest "
+"zsynchronizowany z modułami GRUB-a w grub.cfg. Proszę sprawdzić ponownie, "
+"czy GRUB jest zapisywany na właściwe urządzenia rozruchowe."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+"Zapisywanie GRUB-a na urządzenia rozruchowe nie powiodło się - kontynuować?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Nie powiodło się zainstalowanie GRUB-a na następujących urządzeniach:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Czy kontynuować mimo to? Jeśli tak, ten komputer może nie uruchomić się "
+"poprawnie."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Zapisywanie GRUB-a na urządzenia rozruchowe nie powiodło się - spróbować "
+"ponownie?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Istnieje możliwość zainstalowania GRUB-a na jakimś innym urządzeniu, ale "
+"należy sprawdzić, czy system się z niego uruchomi. W innym przypadku, "
+"aktualizacja z GRUB Legacy zostanie odwołana."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Kontynuować bez instalowania GRUB-a?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Wybrano nieinstalowanie GRUB-a na żadnym urządzeniu. W przypadku "
+"kontynuowania, program rozruchowy może nie być poprawnie skonfigurowany, a "
+"kiedy komputer zostanie uruchomiony ponownie, będzie używał tego, co "
+"znajdowało się poprzednio w sektorze rozruchowym. Jeśli jest tam "
+"wcześniejsza wersja GRUB-a 2, załadowanie modułów lub obsłużenie aktualnego "
+"pliku konfiguracyjnego może być niemożliwe."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Jeśli używany jest obecnie inny program rozruchowy i ma być on używany nadal "
+"lub jeśli jest to specjalne środowisko, które nie potrzebuje programu "
+"rozruchowego, należy kontynuować. W przeciwnym wypadku, powinno się gdzieś "
+"zainstalować GRUB-a."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Usunąć GRUB-a 2 z /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Czy usunąć wszystkie pliki GRUB-a 2 z /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Może to spowodować brak możliwości uruchomienia systemu, chyba że "
+"zainstalowany jest inny program rozruchowy."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Zakończyć przejście do GRUB-a 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"System ma wciąż zainstalowane pliki z programu rozruchowego GRUB Legacy, ale "
+"na następujących dyskach zainstalowano także wpisy rozruchowe GRUB-a 2:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Wygląda na to, że GRUB Legacy nie jest już dłużej używany i należy "
+"zaktualizować obrazy GRUB-a 2 na tych dyskach oraz zakończyć przejście na "
+"GRUB-a 2 przez usunięcie starych plików GRUB Legacy. Jeśli nie "
+"zaktualizowano tych obrazów GRUB-a 2, mogą być one niekompatybilne z nowymi "
+"pakietami i spowodować problemy z poprawnym uruchamianiem systemu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Można zakończyć przejście na GRUB-a 2, chyba że te wpisy rozruchowe zostały "
+"stworzone przez GRUB-a 2 zainstalowanego w jakimÅ› innym systemie operacyjnym."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Wiersz poleceń do Linuksa:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Następujące polecenie do Linuksa zostało wyodrębnione z /etc/default/grub "
+"lub z parametru \"kopt\" w menu.lst GRUB-a Legacy. Proszę sprawdzić czy jest "
+"właściwe i zmodyfikować go, jeśli to konieczne. Wiersz z poleceniem może być "
+"pusty."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Domyślny wiersz poleceń do Linuksa:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Następujący ciąg będzie użyty jako parametry przekazywane do jądra Linux w "
+"domyślnym wpisie menu (ale nie w trybie ratunkowym)."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Wymusić dodatkową instalację do ścieżki nośników wymiennych EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Niektóre oparte na EFI systemy mają błędy i nie obsługują poprawnie nowych "
+"programów rozruchowych. Jeśli wymusisz dodatkową instalację GRUB-a do "
+"ścieżki nośników wymiennych EFI, powinno to zapewnić, że system załaduje "
+"Debiana prawidłowo mimo tego problemu. Jednak może to także uniemożliwić "
+"ładowanie innych systemów operacyjnych, które również zależą od tej ścieżki. "
+"W takiej sytuacji będziesz musiał upewnić się, że GRUB jest skonfigurowany "
+"poprawnie i będzie mógł ładować te systemy."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Zaktualizować zmienne NVRAM, aby automatycznie ładować Debiana?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB może skonfigurować zmienne NVRAM platformy tak, aby automatycznie "
+"ładowała Debiana po uruchomieniu. Można też wyłączyć to zachowanie i nie "
+"zmieniać konfiguracji rozruchu. To pozwala na przykład pozostawić ustawienia "
+"zmiennych NVRAM takie, że system kontaktuje się z serwerem PXE przy każdym "
+"uruchomieniu."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Wiersz poleceń do kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Następujące polecenie do kFreeBSD zostało wyodrębnione z /etc/default/grub "
+"lub z parametru \"kopt\" w menu.lst GRUB-a Legacy. Proszę sprawdzić czy jest "
+"właściwe i zmodyfikować go, jeśli to konieczne. Wiersz z poleceniem może być "
+"pusty."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Domyślny wiersz poleceń do kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Następujący ciąg będzie użyty jako parametry przekazywane do jądra kFreeBSD "
+"w domyślnym wpisie menu (ale nie w trybie ratunkowym)."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map został odtworzony"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Plik /boot/grub/device.map został odtworzony tak, aby używał stabilnych "
+#~ "nazw urządzeń. W większości przypadków powinno to ograniczyć konieczność "
+#~ "jego zmian w przyszłości, a wpisy menu wygenerowane przez GRUB-a nie "
+#~ "powinny zostać naruszone."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Jednakże, ponieważ w systemie jest więcej niż jeden dysk, istnieje "
+#~ "możliwość, że system korzysta ze starej mapy urządzeń. Proszę sprawdzić, "
+#~ "czy istnieją jakieś specjalne wpisy rozruchowe menu, które polegają na "
+#~ "numeracji GRUB-a (hdN) i zaktualizować je, jeśli to konieczne."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Jeśli ta wiadomość jest niezrozumiała lub jeśli nie tworzono żadnych "
+#~ "specjalnych wpisów menu, można ją zignorować."
diff --git a/debian/po/pt.po b/debian/po/pt.po
new file mode 100644
index 0000000..51150dd
--- /dev/null
+++ b/debian/po/pt.po
@@ -0,0 +1,493 @@
+# Portuguese translation for grub2's debconf messages
+# Copyright (C) 2007 Miguel Figueiredo
+# This file is distributed under the same license as the grub2 package.
+#
+# Miguel Figueiredo <elmig@debianpt.org>, 2007, 2010, 2011.
+# Ricardo Silva <ardoric@gmail.com>, 2008.
+# Tiago Fernandes <tjg.fernandes@gmail.com>, 2010.
+# Rui Branco - DebianPT <ruipb@debianpt.org>, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.02-beta3-5\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-06-04 12:30+0000\n"
+"Last-Translator: Rui Branco - DebianPT <ruipb@debianpt.org>\n"
+"Language-Team: Portuguese <traduz@debianpt.org>\n"
+"Language: pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Carregar em cadeia a partir do menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Os scripts de actualização do GRUB detectaram uma configuração do GRUB "
+"Legacy em /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Por forma a substituir a versão antiga do GRUB que se encontra no sistema, é "
+"recomendado que o /boot/grub/menu.lst seja ajustado para permitir carregar "
+"imagem de boot do GRUB 2 a partir da configuração actual do GRUB antigo. "
+"Esta etapa agora pode ser feita automaticamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"É recomendado que aceite carregar em cadeia o GRUB 2 a partir do menu.lst, e "
+"verificar que a configuração do novo GRUB 2 está funcional, antes de ser "
+"escrito no MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Qualquer que seja a sua decisão, pode substituir mais tarde a antiga imagem "
+"do MBR com o GRUB 2, executando como root o seguinte comando:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "dispositivos de instalação GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"O pacote grub-pc está a ser actualizado. Este menu permite-lhe seleccionar "
+"quais os dispositivos onde gostaria que o grub-install corresse "
+"automaticamente, se algum."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Correr o grub-install automaticamente é recomendado na maior parte das "
+"situações, para prevenir que a imagem core do GRUB instalada não fique "
+"dessincronizada com os módulos do GRUB ou grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Se não têm a certeza de qual a drive designada como driver de arranque pela "
+"sua BIOS, é normalmente boa ideia instalar o GRUB em todas elas."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: é possível instalar o GRUB no boot record de partições, e são "
+"oferecidas algumas partições aqui. No entanto, isto força o GRUB a utilizar "
+"o mecanismo blocklist, que o torna menos fiável. Assim não é recomendável."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"O boot loader do GRUB foi instalado num disco que não se encontra presente, "
+"ou então o seu identificador único foi alterado por alguma razão. É "
+"importante ter a certeza que a imagem core do GRUB se mantêm sincronizada "
+"com os módulos do GRUB e grub.cfg. Por favor verifique de novo para ter a "
+"certeza de que o GRUB é escrito nos dispositivos apropriados de arranque."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "A escrita do GRUB para o dispositivo de arranque falhou - continuar?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "A instalação do GRUB falhou nos seguintes dispositivos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Pretende continuar de qualquer modo? Em caso afirmativo, o seu computador "
+"pode não arrancar em condições. "
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"A escrita do GRUB para o dispositivo de arranque falhou - tentar de novo?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Poderá instalar o GRUB noutro dispositivo, no entanto deverá verificar que o "
+"seu sistema arranca desse dispositivo. Se não o fizer, a actualização a "
+"partir do GRUB Legacy será cancelada."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Continuar sem instalar o GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Escolheu não instalar o GRUB em qualquer dispositivo. Se continuar, o gestor "
+"de arranque pode não ficar correctamente configurado, e quando o computador "
+"arrancar da próxima vez irá usar o que estiver anteriormente no sector de "
+"arranque. Se existir uma versão anterior do GRUB 2 no sector de arranque, "
+"poderá não ser capaz de carregar os módulos e gerir o ficheiro de "
+"configuração actual."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Se já estiver a utilizar um gestor de arranque diferente e quiser continuar "
+"a fazê-lo, ou se se tratar de um ambiente especial onde não necessita de "
+"gestor de arranque, deverá então continuar de qualquer modo. Caso contrário, "
+"deverá instalar o GRUB em algum sitio."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Remover o GRUB 2 de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Deseja remover todos os ficheiros do GRUB 2 de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Isto fará com que o sistema não arranque até que seja instalado outro gestor "
+"de arranque."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Finalizar a conversão para o GRUB 2 agora?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Este sistema ainda tem ficheiros instalados do gestor de arranque GRUB "
+"Legacy, no entanto agora também tem registos de arranque do GRUB 2 "
+"instalados nos discos seguintes:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Parece provável que o GRUB Legacy não esteja a ser usado, deve fazer a "
+"actualização das imagens do GRUB 2 nestes discos e finalizar a conversão "
+"para o GRUB 2 removendo os ficheiros antigos do GRUB Legacy. Se não "
+"actualizar estas imagens GRUB 2 então estas podem ser incompatíveis com "
+"novos pacotes e provocar uma falha no arranque do sistema."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Normalmente deverá finalizar a conversão para o GRUB 2 a não ser que estes "
+"registos de arranque tenham sido criados por uma instalação do GRUB 2 noutro "
+"sistema operativo."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linha de comandos do Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A seguinte linha de comandos Linux foi extraída de /etc/default/grub ou do "
+"parâmetro `kopt' no menu.lst do GRUB Legacy. Por favor verifique que está "
+"correcta, e modifique se necessário. É permitido que a linha de comandos "
+"esteja vazia."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linha de comandos padrão do Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"A seguinte linha será utilizada como parâmetros para o Linux na entrada "
+"predefinida do menu, mas não para o modo de recuperação."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Forçar a instalação extra para o caminho de media removível EFI? "
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Alguns sistemas baseados em EFI possuem bugs e não irão gerir os novos "
+"bootloaders correctamente. Se forçar uma instalação extra do GRUB para o "
+"caminho de media removível EFI por favor assegure-se que o sistema irá "
+"arrancar com o Debian correctamente apesar do problema. Além disso poderá "
+"remover o arranque de qualquer sistema operativo que também dependa deste "
+"caminho. Se assim for terá que se certificar que o GRUB é configurado "
+"correctamente para que possa arrancar com instalações de outros sistemas "
+"operativos."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Actualizar as variáveis NVRAM para arrancar automaticamente o Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"O GRUB pode configurar as variáveis NVRAM da sua plataforma de modo a que "
+"arranque o Debian automaticamente quando ligar a máquina. No entanto pode "
+"preferir desactivar este comportamento e evitar alterações à sua "
+"configuração de arranque. Por exemplo, se as suas variáveis NVRAM foram "
+"definidas de modo a que o seu sistema contacte um servidor PXE em cada "
+"arranque, isto preservará esse comportamento. "
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "linha de comandos kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A seguinte linha de comandos kFreeBSD foi extraída a partir de /etc/default/"
+"grub ou do parâmetro `kopt' no menu.lst do GRUB Legacy. Por favor verifique "
+"que está correcta, e modifique se necessário. É permitido que a linha esteja "
+"vazia."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Linha de comandos padrão do kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"A seguinte linha será utilizada como parâmetros para o kFreeBSD para a "
+"entrada por omissão do menu, mas não para o modo de recuperação."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "O /boot/grub/device.map foi recriado"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "O ficheiro /boot/grub/device.map foi reescrito para usar nomes de "
+#~ "dispositivos estáveis. Na maioria dos casos, esta acção reduz "
+#~ "significativamente a necessidade de alterações no futuro e as entradas de "
+#~ "menu geradas pelo GRUB não deverão ser afectadas."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "No entanto, desde que está presente no sistema mais do que um disco, é "
+#~ "possível que o sistema esteja dependente do mapa antigo de dispositivos "
+#~ "(device map). Por favor verifique se tem algumas entradas personalizadas "
+#~ "no menu de arranque que dependam da numeração de drives do GRUB (hdN), e "
+#~ "actualize-as se necessário."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Se não entende esta mensagem ou se não tiver entradas personalizadas no "
+#~ "menu de arranque, pode ignorar esta mensagem."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Em qualquer dos casos, quando quiser que o GRUB 2 seja carregado "
+#~ "directamente a partir do MBR, pode fazê-lo executando (como root) o "
+#~ "seguinte comando: "
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "A instalação do GRUB falhou. Continuar?"
diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po
new file mode 100644
index 0000000..05f8f76
--- /dev/null
+++ b/debian/po/pt_BR.po
@@ -0,0 +1,495 @@
+# grub2 Brazilian Portuguese translation
+# Copyright (C) 2009 THE grub2'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub2 package.
+# Flamarion Jorge <jorge.flamarion@gmail.com>, 2009, 2010, 2011.
+# Adriano Rafael Gomes <adrianorg@debian.org>, 2014-2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.02~beta3-4\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-24 21:29-0300\n"
+"Last-Translator: Adriano Rafael Gomes <adrianorg@debian.org>\n"
+"Language-Team: Brazilian Portuguese <debian-l10n-portuguese@lists.debian."
+"org>\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Carregar em cadeia a partir do menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Os scripts de atualização do GRUB detectaram uma configuração do GRUB Legado "
+"em /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"A fim de substituir a versão Legada do GRUB no seu sistema, é recomendável "
+"que o /boot/grub/menu.lst seja ajustado para carregar uma imagem do GRUB 2 a "
+"partir da sua configuração existente do GRUB Legado. Este passo pode ser "
+"executado automaticamente agora."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"É recomendado que você aceite o carregamento em cadeia do GRUB 2 a partir do "
+"menu.lst, e verifique que sua nova configuração do GRUB 2 está funcional, "
+"antes de gravá-lo na MBR (\"Master Boot Record\")."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Seja qual for sua decisão, você pode substituir a antiga imagem da MBR com o "
+"GRUB 2 mais tarde executando o seguinte comando como root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Instalar o GRUB nos dispositivos:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"O pacote grub-pc está sendo atualizado. Este menu permite a você selecionar "
+"em quais dispositivos você quer que seja executado automaticamente o grub-"
+"install, se houver algum."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Executar o grub-install automaticamente é recomendado na maioria das "
+"situações para prevenir que a imagem principal instalada do GRUB saia de "
+"sincronia com os módulos do GRUB ou com o grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Se você não tiver certeza de qual unidade é designada como unidade de "
+"inicialização pela sua BIOS, muitas vezes é uma boa ideia instalar o GRUB em "
+"todas elas."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Nota: é possível instalar o GRUB em registros de inicialização de partições, "
+"e algumas partições apropriadas para isso são oferecidas aqui. No entanto, "
+"isto força o GRUB a usar o mecanismo de lista de blocos, que o torna menos "
+"confiável, portanto, não é recomendado."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"O carregador de inicialização GRUB foi instalado anteriormente em um disco "
+"que não está mais presente, ou seu identificador único foi modificado por "
+"alguma razão. É importante certificar-se de que a imagem principal do GRUB "
+"instalada está em sincronia com os módulos do GRUB e com o grub.cfg. Por "
+"favor, verifique novamente e esteja certo de que o GRUB está gravado nos "
+"dispositivos de inicialização apropriados."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "A gravação do GRUB no dispositivo de inicialização falhou - continuar?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Falha ao instalar o GRUB nos seguintes dispositivos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Você deseja continuar de qualquer maneira? Se você continuar, seu computador "
+"talvez não inicialize corretamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"A gravação do GRUB no dispositivo de inicialização falhou - tentar novamente?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Você pode conseguir instalar o GRUB em outro dispositivo, mas você deve "
+"verificar se o seu sistema vai conseguir inicializar a partir deste "
+"dispositivo. Caso contrário, a atualização do GRUB Legado será cancelada."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Continuar sem instalar o GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Você escolheu não instalar o GRUB em nenhum dispositivo. Se você continuar, "
+"o carregador de inicialização poderá não ser configurado corretamente, e na "
+"próxima vez que este computador inicializar ele usará a versão que estava "
+"anteriormente no setor de inicialização. Se houver uma versão anterior do "
+"GRUB 2 no setor de inicialização, pode ser que ele não consiga carregar "
+"módulos ou manipular corretamente o arquivo de configuração atual."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Se você já estiver usando um carregador de inicialização diferente e quiser "
+"continuar a fazê-lo, ou se este é um ambiente especial, onde você não "
+"precisa de um carregador de inicialização, então você deve continuar de "
+"qualquer maneira. Caso contrário, você deve instalar o GRUB em algum outro "
+"lugar."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Remover o GRUB 2 do /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Você deseja ter todos os arquivos do GRUB 2 removidos de /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Isto fará com que seu sistema não inicialize a menos que outro carregador de "
+"inicialização esteja instalado."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Completar a conversão para o GRUB 2 agora?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Este sistema ainda tem arquivos do carregador de inicialização do GRUB "
+"Legado instalados, mas agora também tem registros de inicialização do GRUB 2 "
+"instalados nestes discos:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Parece provável que o GRUB Legado não está mais em uso, e que você deve "
+"atualizar as imagens do GRUB 2 nestes discos e completar a conversão para o "
+"GRUB 2, removendo arquivos antigos do GRUB Legado. Se você não atualizar "
+"essas imagens do GRUB 2, então elas podem ser incompatíveis com os novos "
+"pacotes e fazer com que o sistema deixe de inicializar corretamente."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Você normalmente deveria completar a conversão para o GRUB 2, a menos que "
+"esses registros de inicialização tenham sido criados por uma instalação do "
+"GRUB 2 em algum outro sistema operacional."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linha de comando Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A linha de comando Linux a seguir foi extraída de /etc/default/grub ou do "
+"parâmetro 'kopt' do menu.lst do GRUB Legado. Por favor, verifique se ela "
+"está correta, e modifique-a se necessário. A linha de comando pode ser vazia."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linha de comando padrão Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"O seguinte texto será usado como lista de parâmetros do Linux para a entrada "
+"padrão do menu, mas não para o modo de recuperação."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Forçar instalação extra no caminho de mídia removível EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Alguns sistemas baseados em EFI contém bugs e não lidam corretamente com "
+"novos carregadores de inicialização. Se você forçar uma instalação extra do "
+"GRUB no caminho de mídia removível EFI, isso deverá assegurar que este "
+"sistema inicializará o Debian corretamente, apesar desse problema. No "
+"entanto, isso pode remover a habilidade de inicializar quaisquer outros "
+"sistemas operacionais que também dependam desse caminho. Caso afirmativo, "
+"você precisará certificar-se de que o GRUB seja configurado com sucesso para "
+"ser capaz de inicializar corretamente quaisquer instalações de outros "
+"sistemas operacionais."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Atualizar variáveis NVRAM para inicializar automaticamente no Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"O GRUB pode configurar as variáveis NVRAM da sua plataforma de forma que ela "
+"inicialize automaticamente no Debian quando for ligada. No entanto, você "
+"pode preferir desabilitar esse comportamento e evitar mudanças na sua "
+"configuração de inicialização. Por exemplo, se as suas variáveis NVRAM "
+"tiverem sido configuradas de forma que o seu sistema contate um servidor PXE "
+"a cada inicialização, isso preservaria tal comportamento."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Executar os-prober automaticamente para detectar e inicializar outros "
+"sistemas operacionais?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"O GRUB pode usar a ferramenta os-prober para tentar detectar outros sistemas "
+"operacionais no seu computador e adicioná-los na lista de opções de "
+"inicialização automaticamente."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Se o seu computador tem múltiplos sistemas operacionais instalados, então "
+"essa opção é provavelmente o que você quer. Entretanto, se o seu computador "
+"é um hospedeiro para sistemas operacionais convidados instalados via LVM ou "
+"dispositivos de disco \"raw\", executar o os-prober pode causar danos a "
+"esses sistemas operacionais convidados, uma vez que ele monta os sistemas de "
+"arquivos para fazer procuras."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Linha de comando kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"A linha de comando kFreeBSD a seguir foi extraída de /etc/default/grub ou do "
+"parâmetro 'kopt' do menu.lst do GRUB Legado. Por favor, verifique se ela "
+"está correta, e modifique-a se necessário. A linha de comando pode ser vazia."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Linha de comando padrão kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"O seguinte texto será usado como lista de parâmetros do kFreeBSD para a "
+"entrada padrão do menu, mas não para o modo de recuperação."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map foi gerado novamente"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "O arquivo /boot/grub/device.map foi reescrito para usar nomes estáveis de "
+#~ "dispositivo. Na maioria dos casos, isto pode reduzir de forma "
+#~ "significativa a necessidade de mudá-los no futuro, e as entradas do menu "
+#~ "de inicialização geradas pelo GRUB não devem ser afetadas."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Entretanto, como mais de um disco está presente no sistema, é possível "
+#~ "que o sistema esteja dependendo do antigo mapa de dispositivos. Por "
+#~ "favor, verifique se existem quaisquer outras entradas personalizadas no "
+#~ "menu de inicialização que dependam da numeração de unidade do GRUB (hdN), "
+#~ "e atualize-as se necessário."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Se você não compreende esta mensagem, ou se não existem entradas "
+#~ "personalizadas no menu de inicialização, você pode ignorar esta mensagem."
diff --git a/debian/po/ro.po b/debian/po/ro.po
new file mode 100644
index 0000000..164315e
--- /dev/null
+++ b/debian/po/ro.po
@@ -0,0 +1,540 @@
+# translation of ro.po to Romanian
+# Romanian translations for grub package
+# Traducerea în limba română pentru pachetul grub (debconf-strings).
+# Copyright © 2007, 2008, 2010, 2012, 2014, 2023 THE grub'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub package.
+#
+# Eddy Petrișor <eddy.petrisor@gmail.com>, 2007,2008.
+# ioan-eugen STAN <stan.ieugen@gmail.com>, 2010.
+# Lucian Adrian Grijincu <lucian.grijincu@gmail.com>, 2010.
+# Andrei POPESCU <andreimpopescu@gmail.com>, 2012, 2014.
+# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ro\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 02:07+0200\n"
+"Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\n"
+"Language-Team: Romanian <debian-l10n-romanian@lists.debian.org>\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: 2;\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Doriți să fie înlănțuite la meniul de pornire intrările din „menu.lst�"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Scripturile de înnoire ale lui GRUB au detectat în directorul „/boot/grub†o "
+"configurație pentru vechiul GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically performed "
+"now."
+msgstr ""
+"Pentru a înlocui vechea versiune a lui GRUB, se recomandă modificarea "
+"fiÈ™ierului „/boot/grub/menu.lstâ€, astfel încât să încarce o imagine de pornire "
+"GRUB 2 din configurația existentă. Acest pas poate fi făcut chiar acum în mod "
+"automat."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and verify "
+"that the new GRUB 2 setup works before it is written to the MBR (Master Boot "
+"Record)."
+msgstr ""
+"Este recomandat să acceptați înlănțuirea în meniul de pornire al lui GRUB 2 a "
+"intrărilor din „menu.lst†și să verificați că noua configurație pentru GRUB 2 "
+"funcționează, înainte de instalarea în sectorul de pornire („Master Boot "
+"Recordâ€: MBR)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later by "
+"issuing the following command as root:"
+msgstr ""
+"Indiferent ce decideți, puteți înlocui ulterior imaginea MBR veche cu GRUB 2 "
+"executând următoarea comandă cu privilegii root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Dispozitive pentru a instala GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Pachetul grub-pc este în curs de înnoire. Acest meniu vă permite să alegeți "
+"pentru ce dispozitive doriți să ruleze automat «grub-install», dacă este cazul."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Rularea automată a asistentului de instalare «grub-install» este recomandată în "
+"majoritatea situațiilor, pentru ca imaginea GRUB instalată să fie sincronizată "
+"cu modulele GRUB È™i fiÈ™ierul de configurare „grub.cfgâ€."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Dacă nu știți sigur care unitate este desemnată ca unitatea de pornire de către "
+"BIOS este o idee bună să instalați GRUB pe toate unitățile."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to use "
+"the blocklist mechanism, which makes it less reliable, and therefore is not "
+"recommended."
+msgstr ""
+"Notă: este posibil să instalați GRUB în sectorul de pornire al unei partiții, "
+"iar unele partiții adecvate sunt prezentate aici. Totuși, aceasta va forța GRUB "
+"să utilizeze mecanismul „blocklistâ€, care este mai puÈ›in fiabil. ÃŽn consecință "
+"această metodă nu este recomandată."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is written "
+"to the appropriate boot devices."
+msgstr ""
+"Încărcătorul de sistem GRUB a fost instalat pe un disc care nu mai este "
+"prezent, sau al cărui identificator unic a fost modificat dintr-un motiv "
+"oarecare. Este important să vă asigurați că imaginea GRUB rămâne sincronizată "
+"cu modulele GRUB È™i fiÈ™ierul de configurare „grub.cfgâ€. Ar fi bine să "
+"verificați din nou, pentru a vă asigura că GRUB este scris pe dispozitivul "
+"pornire corect."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} Mo; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} Mo; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Scrierea GRUB pe dispozitivul de pornire a eșuat. Se continuă?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Instalarea GRUB pe următoarele dispozitive a eșuat:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Doriți să continuați oricum? Dacă da, este posibil ca sistemul să nu pornească "
+"corespunzător."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Scrierea GRUB pe dispozitivul de pornire a eșuat. Se încearcă din nou?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should check "
+"that your system will boot from that device. Otherwise, the upgrade from GRUB "
+"Legacy will be canceled."
+msgstr ""
+"Puteți instala GRUB pe alt dispozitiv, însă ar trebui să verificați dacă "
+"sistemul va porni de pe acel dispozitiv. Altfel, înnoirea de la GRUB Legacy va "
+"fi anulată."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Continuați fără să instalați GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot loader "
+"may not be properly configured, and when this computer next starts up it will "
+"use whatever was previously in the boot sector. If there is an earlier version "
+"of GRUB 2 in the boot sector, it may be unable to load modules or handle the "
+"current configuration file."
+msgstr ""
+"Ați ales să nu instalați GRUB pe niciun dispozitiv. Dacă veți continua, este "
+"posibil ca încărcătorul de sistem să nu fie configurat corespunzător, iar la "
+"pornirea calculatorului acesta va folosi ce se afla deja în sectorul de "
+"pornire. Dacă există o versiune mai veche de GRUB 2 în sectorul de pornire este "
+"posibil ca aceasta să nu poată încărca modulele sau să proceseze fișierul de "
+"configurare curent."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing so, "
+"or if this is a special environment where you do not need a boot loader, then "
+"you should continue anyway. Otherwise, you should install GRUB somewhere."
+msgstr ""
+"Dacă folosiți deja un alt încărcător de sistem și doriți să continuați, sau "
+"dacă acesta este un mediu special în care nu aveți nevoie de încărcător de "
+"sistem, atunci ar trebui să continuați. Altfel, ar trebui să instalați GRUB "
+"undeva."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Se îndepărtează GRUB 2 din directorul „/boot/grub�"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Doriți ca toate fișierele GRUB 2 să fie îndepărtate din „/boot/grub�"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Aceasta va împiedica pornirea sistemului, în afara cazului în care este "
+"instalat un alt încărcător de sistem."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Finalizați acum conversia la GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but it "
+"now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Acest sistem încă mai are instalate fișiere din încărcătorul de pornire GRUB "
+"Legacy, dar acum are și înregistrări de pornire GRUB 2 instalate pe aceste "
+"discuri:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion to "
+"GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these GRUB 2 "
+"images, then they may be incompatible with the new packages and cause your "
+"system to stop booting properly."
+msgstr ""
+"Este foarte probabil ca GRUB Legacy să nu mai fie folosit și ar trebui să "
+"actualizați imaginile GRUB 2 pe aceste discuri și să definitivați trecerea la "
+"GRUB 2 îndepărtând fișierele GRUB Legacy vechi. Dacă nu actualizați aceste "
+"imagini GRUB 2, ele ar putea fi incompatibile cu noile pachete și ar putea "
+"împiedica sistemul să pornească corespunzător."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot records "
+"were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"În general este bine să încheiați conversia la GRUB 2, în afara cazului în care "
+"acele înregistrări de pornire au fost create de o instalare GRUB 2 a altui "
+"sistem de operare."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linia de comandă Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is correct, "
+"and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Această linie de comandă Linux a fost extrasă din fișierul „/etc/default/grub†"
+"sau din parametrul „kopt†din fișierul „menu.lst†al vechiului GRUB. Verificați "
+"corectitudinea acesteia și modificați-o, dacă este nevoie. Linia de comandă "
+"este permisă să fie goală."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linia de comandă implicită Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Următorul șir va fi folosit ca parametru pentru Linux pentru intrarea implicită "
+"din meniu, dar nu și pentru cea de recuperare."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Se forțează o instalare suplimentară pe calea suportului amovibil EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders correctly. "
+"If you force an extra installation of GRUB to the EFI removable media path, "
+"this should ensure that this system will boot Debian correctly despite such a "
+"problem. However, it may remove the ability to boot any other operating systems "
+"that also depend on this path. If so, you will need to make sure that GRUB is "
+"configured successfully to be able to boot any other OS installations correctly."
+msgstr ""
+"Anumite sisteme EFI au probleme și nu funcționează corect cu încărcători de "
+"sistem noi. Forțând o instalare GRUB suplimentară în calea EFI pentru suporturi "
+"amovibile ar trebui să asigure o încărcare corectă a sistemului Debian chiar și "
+"în cazul acestor probleme. Totuși, în acest fel este posibil să pierdeți "
+"posibilitatea de încărcare a altor sisteme care depind de aceiași metodă. În "
+"acest caz va trebui să vă asigurați că GRUB este configurat corect pentru a "
+"putea încărca și orice alte sisteme de operare."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+"Doriți să se modifice variabilele NVRAM astfel încât aceasta (memoria "
+"nevolatilă) să fie încărcată automat în Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into Debian "
+"automatically when powered on. However, you may prefer to disable this behavior "
+"and avoid changes to your boot configuration. For example, if your NVRAM "
+"variables have been set up such that your system contacts a PXE server on every "
+"boot, this would preserve that behavior."
+msgstr ""
+"GRUB poate configura variabilele NVRAM ale platformei dumneavoastră astfel "
+"încât memoria nevolatilă să pornească automat în Debian. Cu toate acestea, este "
+"posibil să preferați să dezactivați acest comportament și să evitați "
+"modificările configurației de pornire. De exemplu, dacă variabilele dvs. NVRAM "
+"au fost configurate astfel încât sistemul dumneavoastră contactează un server "
+"PXE la fiecare pornire, acest lucru ar păstra acest comportament.."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Doriți ca «os-prober» să fie rulat automat pentru a detecta și a porni alte "
+"sisteme de operare?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems on "
+"your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB poate folosi instrumentul «os-prober» pentru a încerca să detecteze alte "
+"sisteme de operare de pe calculatorul dvs. și să le adauge automat la lista sa "
+"de opțiuni de pornire."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Dacă calculatorul dvs. are mai multe sisteme de operare instalate, atunci "
+"acesta este probabil ceea ce doriți. Cu toate acestea, dacă calculatorul dvs. "
+"este o gazdă pentru sistemele de operare invitate instalate prin LVM sau "
+"dispozitive de disc brute, rularea lui «os-prober» poate provoca daune acelor "
+"sisteme de operare invitate, deoarece montează sistemele de fișiere pentru a "
+"căuta lucruri."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Linia de comandă kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is correct, "
+"and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Această linie de comandă kFreeBSD a fost extrasă din fișierul „/etc/default/"
+"grub†sau din parametrul „kopt†din fișierul „menu.lst†al vechiului GRUB. "
+"Verificați corectitudinea acesteia și modificați-o, dacă este nevoie. Linia de "
+"comandă este permisă să fie goală."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Linia de comandă implicită kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Următorul șir va fi folosit ca parametru pentru kFreeBSD pentru intrarea "
+"implicită din meniu, dar nu și pentru cea de recuperare."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map a fost regenerat"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change it "
+#~ "in future, and boot menu entries generated by GRUB should not be affected."
+#~ msgstr ""
+#~ "Fișierul /boot/grub/device.map a fost rescris să folosească nume stabile de "
+#~ "dispozitive. ÃŽn majoritatea cazurilor, acest lucru va reduce semnificativ "
+#~ "nevoia de a-l modifica ulterior și intrările în meniu generate de grub nu ar "
+#~ "trebui să fie afectate. "
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is possible "
+#~ "that the system is depending on the old device map. Please check whether "
+#~ "there are any custom boot menu entries that rely on GRUB's (hdN) drive "
+#~ "numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Totuși, deoarece există mai mult de un disc în sistem, este posibil ca "
+#~ "sistemul să depindă de vechea hartă de dispozitive. Verificați dacă aveți "
+#~ "intrări personalizate în meniu care depind de numerotarea GRUB (hdN) și "
+#~ "actualizați-le dacă este cazul."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot menu "
+#~ "entries, you can ignore this message."
+#~ msgstr ""
+#~ "Dacă nu înțelegeți acest mesaj, sau nu există poziții personalizate în "
+#~ "meniu, îl puteți ignora."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, you "
+#~ "can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "În orice caz, atunci când veți dori ca GRUB 2 sa fie încărcat direct din "
+#~ "MBR, puteți rula (ca root) comanda următoare:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Instalarea GRUB a eșuat. Continuați?"
+
+#~ msgid "GRUB 1.95 numbering scheme transition"
+#~ msgstr "Tranziția la schema de numerotare pentru GRUB 1.95"
+
+#~ msgid ""
+#~ "As of version 1.95, GRUB 2 has changed its numbering scheme. Partitions are "
+#~ "now counted starting from 1 rather than 0. This is to make it consistent "
+#~ "with device names of Linux and the other kernels used in Debian. For "
+#~ "example, when using Linux as the kernel, \"(hd0,1)\" refers to the same "
+#~ "partition as the /dev/sda1 device node."
+#~ msgstr ""
+#~ "Începând cu versiunea 1.95, GRUB 2 și-a schimbat schema de numerotare. "
+#~ "Partițiile sunt acum numerotate începând de la 1 (în loc de 0). Acest lucru "
+#~ "este consecvent cu numele de dispozitive ale Linux-ului și a altor nuclee "
+#~ "folosite în Debian. De exemplu, când se folosește nucleul Linux, „(hd0,1)†"
+#~ "se referă la aceiași partiție ca și nodul de dispozitiv /dev/sda1."
+
+#~ msgid ""
+#~ "Because of this, there's a chance your system becomes unbootable if update-"
+#~ "grub(8) is run before GRUB is updated, generating a grub.cfg file that your "
+#~ "installed GRUB won't yet be able to parse correctly. To ensure your system "
+#~ "will be able to boot, you have to:"
+#~ msgstr ""
+#~ "De aceea, există riscul ca sistemul să nu mai pornească dacă update-grub(8) "
+#~ "este rulat înainte ca GRUB să fie actualizat, generând astfel un fișier grub."
+#~ "cfg pe care GRUB-ul instalat nu-l va putea încă analiza corect. Pentru a vă "
+#~ "asigura că sistemul va putea porni, va trebui să:"
+
+#~ msgid ""
+#~ " - Reinstall GRUB (typically, by running grub-install).\n"
+#~ " - Rerun update-grub to generate a new grub.cfg."
+#~ msgstr ""
+#~ " - Reinstalați GRUB (în mod normal, prin rularea lui grub-install).\n"
+#~ " - Rulați din nou update-grub pentru a genera un nou grub.cfg."
diff --git a/debian/po/ru.po b/debian/po/ru.po
new file mode 100644
index 0000000..744872b
--- /dev/null
+++ b/debian/po/ru.po
@@ -0,0 +1,490 @@
+# translation of ru.po to Russian
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub2 package.
+#
+# Yuri Kozlov <kozlov.y@gmail.com>, 2007, 2008.
+# Yuri Kozlov <yuray@komyakino.ru>, 2009, 2010, 2011, 2014, 2017, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 2.06-13\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-30 06:47+0300\n"
+"Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n"
+"Language-Team: Russian <debian-l10n-russian@lists.debian.org>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 22.12.3\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Включить загрузку по цепочке (chainload) в menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Сценарии Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ð½Ð°Ñ€ÑƒÐ¶Ð¸Ð»Ð¸ уÑтановку GRUB предыдущего Ð¿Ð¾ÐºÐ¾Ð»ÐµÐ½Ð¸Ñ Ð² /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Чтобы заменить в ÑиÑтеме верÑию GRUB предыдущего поколениÑ, рекомендуетÑÑ "
+"иÑправить /boot/grub/menu.lst так, чтобы образ GRUB 2 загружалÑÑ Ð¸Ð· "
+"иÑпользуемой уÑтановки GRUB предыдущего поколениÑ. Это может быть Ñделано "
+"автоматичеÑки прÑмо ÑейчаÑ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"РекомендуетÑÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð¸Ñ‚ÑŒ утвердительно Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ GRUB 2 из menu.lst по "
+"цепочке и проверить, что Ð½Ð¾Ð²Ð°Ñ Ð½Ð°Ñтройка GRUB 2 работает так как нужно, "
+"перед тем как уÑтанавливать её непоÑредÑтвенно в MBR (главную загрузочную "
+"запиÑÑŒ)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Ð’ любом Ñлучае, вы можете заменить Ñтарый образ MBR на GRUB 2 позднее Ñ "
+"помощью Ñледующей команды, выполненной Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¼Ð¸ ÑуперпользователÑ:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "УÑтройÑтва, на которые уÑтанавливаетÑÑ GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"ВыполнÑетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ðµ пакета grub-pc. Это меню позволÑет вам выбрать "
+"уÑтройÑтва, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… нужно автоматичеÑки запуÑтить grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Ð’ большинÑтве Ñлучаев рекомендуетÑÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÑÑ‚ÑŒ автоматичеÑкий запуÑк grub-"
+"install, так как Ñто Ñинхронизирует оÑновной образ GRUB Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñми GRUB и "
+"grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ЕÑли вы не знаете какое уÑтройÑтво указано в BIOS Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸, чаÑто лучше "
+"вÑего уÑтановить GRUB на вÑе уÑтройÑтва."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Замечание: также возможно уÑтановить GRUB в загрузочную запиÑÑŒ раздела, и "
+"здеÑÑŒ предлагаютÑÑ ÑоответÑтвующие разделы. Однако, Ñто включает в GRUB "
+"иÑпользование механизма блок-лиÑта, при котором уменьшаетÑÑ Ð½Ð°Ð´Ñ‘Ð¶Ð½Ð¾ÑÑ‚ÑŒ, и "
+"поÑтому Ñто не рекомендуетÑÑ."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"СиÑтемный загрузчик GRUB был уÑтановлен на диÑк, которого больше нет в "
+"ÑиÑтеме, или по какой-то причине был изменён уникальный идентификатор. Важно "
+"убедитьÑÑ, что уÑтановленный оÑновной образ GRUB Ñинхронизирован Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñми "
+"GRUB и grub.cfg. Проверьте ещё раз, что GRUB запиÑан на правильные "
+"загрузочные уÑтройÑтва."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} МБ; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} МБ; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Ðе удалоÑÑŒ запиÑать GRUB на загрузочное уÑтройÑтво -- продолжить?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Ðе удалоÑÑŒ уÑтановить GRUB на Ñледующие уÑтройÑтва:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Продолжить, не ÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° Ñто? Возможно, не удаÑÑ‚ÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ компьютер."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Ðе удалоÑÑŒ запиÑать GRUB на загрузочное уÑтройÑтво -- попробовать ещё раз?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Ð’Ñ‹ можете уÑтановить GRUB на другое уÑтройÑтво, но проверьте, что компьютер "
+"будет загружатьÑÑ Ñ Ñтого уÑтройÑтва. Иначе, обновление Ñо Ñтарой верÑии "
+"GRUB Legacy будет отменено."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Продолжить без уÑтановки GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Ð’Ñ‹ отказалиÑÑŒ от уÑтановки GRUB. ЕÑли продолжите, то ÑиÑтемный загрузчик "
+"может быть неправильно наÑтроен, и когда компьютер будет включён в Ñледующий "
+"раз, будет иÑпользоватьÑÑ Ñ‚Ð¾, что было раньше в загрузочном Ñекторе. ЕÑли "
+"там была Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ GRUB 2, то она не Ñможет загрузить модули или "
+"обработать текущий файл наÑтройки."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ЕÑли у Ð²Ð°Ñ ÑƒÐ¶Ðµ работает другой ÑиÑтемный загрузчик и вы хотите оÑтавить "
+"выполнение как еÑÑ‚ÑŒ, или еÑли еÑÑ‚ÑŒ Ñпециальное окружение, где не нужен "
+"ÑиÑтемный загрузчик, то продолжайте уÑтановку. Иначе, вам нужно уÑтановить "
+"GRUB как-то иначе."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Удалить GRUB 2 из /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Удалить вÑе файлы GRUB 2 из /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"ЕÑли не уÑтановлен другой ÑиÑтемный загрузчик Ñто Ñделает ÑиÑтему "
+"незагружаемой."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Завершить переход к GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ð’ ÑиÑтеме оÑталиÑÑŒ файлы от Ñтарого ÑиÑтемного загрузчика GRUB Legacy, но "
+"теперь на те же диÑки уÑтановлена Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¾Ñ‡Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ GRUB 2:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"ВероÑтно, GRUB Legacy больше не иÑпользуетÑÑ Ð¸ вам нужно обновить образы "
+"GRUB 2 на Ñтих диÑках и завершить переход к GRUB 2, удалив Ñтарые файлы GRUB "
+"Legacy. ЕÑли вы не обновите данные образы GRUB 2, то они могут оказатьÑÑ "
+"неÑовмеÑтимыми Ñ Ð½Ð¾Ð²Ñ‹Ð¼Ð¸ пакетами и ÑиÑтема больше не загрузитÑÑ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Обычно, вам нужно завершить переход к GRUB 2, еÑли нет загрузочных запиÑей, "
+"Ñозданных уÑтановкой GRUB 2 в какой-то другой операционной ÑиÑтеме."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ПредÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð½Ð¸Ð¶Ðµ Ñтрока команд Linux была извлечена из /etc/default/grub "
+"или параметра «kopt» файла menu.lst Ñтарой верÑии GRUB. Проверьте, что вÑÑ‘ "
+"правильно, или измените её, еÑли требуетÑÑ. Также ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока может "
+"быть пуÑтой."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока Linux по умолчанию:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Ð”Ð°Ð½Ð½Ð°Ñ Ñтрока будет иÑпользоватьÑÑ Ð² качеÑтве параметров Linux в пункте меню "
+"по умолчанию, кроме режима воÑÑтановлениÑ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Выполнить принудительную уÑтановку в путь Ñъёмных ноÑителей EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Ðекоторые ÑиÑтемы на оÑнове EFI Ñодержат ошибки и неправильно работают Ñ "
+"новыми ÑиÑтемными загрузчиками. ЕÑли выполнить принудительную уÑтановку GRUB "
+"в путь Ñъёмных ноÑителей EFI, то на такой ÑиÑтеме Debian будет запуÑкатьÑÑ "
+"неÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° Ñту проблему. Однако Ñто может привеÑти к отказу запуÑка вÑех "
+"оÑтальных операционных ÑиÑтем, которые также завиÑÑÑ‚ от Ñтого пути. "
+"Проверьте, что GRUB правильно наÑтроен Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ любой другой ОС."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Обновить переменные NVRAM Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого запуÑка Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB может изменить переменные NVRAM на вашей платформе и Debian будет "
+"загружатьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки при подаче питаниÑ. Однако, иногда Ñто "
+"нежелательно. Ðапример, еÑли в переменных NVRAM указаны наÑтройки Ð´Ð»Ñ "
+"подключению к Ñерверу PXE при каждом запуÑке, то лучше ничего не менÑÑ‚ÑŒ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr "ЗапуÑкать os-prober Ð´Ð»Ñ Ð¾Ð±Ð½Ð°Ñ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð¸ загрузки других ОС?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ os-prober может находить другие операционные ÑиÑтемы"
+"на компьютере и автоматичеÑки добавлÑÑ‚ÑŒ их в ÑпиÑок загрузки."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"ЕÑли на компьютере уÑтановлено неÑколько операционных ÑиÑтем, то Ñто то, "
+"что вам нужно. Однако, еÑли компьютер ÑвлÑетÑÑ Ð½Ð¾Ñителем гоÑтевых ОС,"
+"уÑтановленных в LVM или на неÑтруктурированные диÑковые уÑтройÑтва, "
+"запуÑк os-prober может повредить Ñти гоÑтевые ОС, так как при работе "
+"он монтирует файловые ÑиÑтемы."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ПредÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð½Ð¸Ð¶Ðµ Ñтрока команд kFreeBSD была извлечена из /etc/default/"
+"grub или параметра «kopt» файла menu.lst Ñтарой верÑии GRUB. Проверьте, что "
+"вÑÑ‘ правильно, или измените её, еÑли требуетÑÑ. Также ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока может "
+"быть пуÑтой."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока kFreeBSD по умолчанию:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Ð”Ð°Ð½Ð½Ð°Ñ Ñтрока будет иÑпользоватьÑÑ Ð² качеÑтве параметров kFreeBSD в пункте "
+"меню по умолчанию, кроме режима воÑÑтановлениÑ."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "ПереÑоздан файл /boot/grub/device.map"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Файл /boot/grub/device.map перезапиÑан, ÑоглаÑно имеющимÑÑ Ñтабильным "
+#~ "именам уÑтройÑтв. Ð’ большинÑтве Ñлучаев, Ñто должно значительно Ñократить "
+#~ "необходимоÑÑ‚ÑŒ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐµÐ³Ð¾ в будущем, и пункты загрузочного меню, "
+#~ "Ñозданного GRUB, не должны быть затронуты."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Однако, так как у Ð²Ð°Ñ Ð² ÑиÑтеме более одного диÑка, возможно, что была "
+#~ "завиÑимоÑÑ‚ÑŒ от Ñтарого Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ ÑƒÑтройÑтв. Проверьте, что во вÑех "
+#~ "наÑтроенных вручную пунктах загрузочного меню иÑпользуетÑÑ Ð½ÑƒÐ¼ÐµÑ€Ð°Ñ†Ð¸Ñ "
+#~ "уÑтройÑтв GRUB (hdâ„–), и измените их, еÑли нужно."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "ЕÑли вы не понимаете о чём речь, или у Ð²Ð°Ñ Ð½ÐµÑ‚ наÑтроенных вручную "
+#~ "пунктов загрузочного меню, то игнорируйте Ñто Ñообщение."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Ð’ любом Ñлучае, еÑли вы хотите, чтобы GRUB 2 загружалÑÑ Ð½ÐµÐ¿Ð¾ÑредÑтвенно "
+#~ "из MBR, выполните Ñледующую команду (Ð¸Ð¼ÐµÑ Ð¿Ñ€Ð°Ð²Ð° ÑуперпользователÑ):"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "УÑтановка GRUB завершилаÑÑŒ неудачно. Продолжить?"
diff --git a/debian/po/si.po b/debian/po/si.po
new file mode 100644
index 0000000..9f1d913
--- /dev/null
+++ b/debian/po/si.po
@@ -0,0 +1,440 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Danishka Navin <danishka@gmail.com> , 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2011-09-29 08:35+0530\n"
+"Last-Translator: Danishka Navin <danishka@gmail.com>\n"
+"Language-Team: Sinhala <info@hanthana.org>\n"
+"Language: si\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.2\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst චක්â€à¶» පූර්ණය"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "GRUB යà·à·€à¶­à·Š විධà·à¶±à·à·€à¶½à·’ පà·à¶»à¶«à·’ GRUB à·ƒà·à¶šà·ƒà·”මක් /boot/grub à·„à·’ සොයà·à¶œà·™à¶± ඇත."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"ඔබේ පද්ධතියේ පවතින GRUB සංස්කරණය ප්â€à¶»à¶­à·’පිහිටුවීමට. /boot/grub/menu.lst පවතින GRUB ස්ථà·à¶´à¶±à¶º "
+"මගින් GRUB 2 ආරම්භක පිළිබිඹුවක් පූර්ණය කිරීමට à·ƒà·à¶šà·ƒà·“ම නිර්දේà·à·’තයි.\n"
+"මෙම ස්ථà·à¶´à¶±à¶º දà·à¶±à·Š ස්වයංක්â€à¶»à·“යව ඉටුකල à·„à·à¶š."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"menu.lst වෙතින් GRUB 2 දà·à¶¸à¶´à·–ර්ණය පිළිගà·à¶±à·“ම නිර්දේà·à·’තයි. එමෙන්ම එය MBR (ප්â€à¶»à¶°à·à¶± ආරම්භක සටහන) "
+"වෙත ලිවීමට පෙර GRUB 2 ස්ථà·à¶´à¶±à¶º ක්â€à¶»à·’යà·à¶šà¶»à¶ºà·’ දà·à¶ºà·’ පිරික්සන්න."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"ඔබේ තීරණය කුමක් වුවත් ඔබට අග්â€à¶»à¶º ලෙස පහත විධà·à¶±à¶º නිකුත් කිරීමෙන් GRUB 2 සමඟ පà·à¶»à¶«à·’ MBR "
+"ප්â€à¶»à¶®à·’පිහිටුවිය à·„à·à¶š."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB ස්ථà·à¶´à¶± උපකරණ:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc පà·à¶šà·šà¶¢à¶º යà·à·€à¶­à·Š වෙමින්. මෙම මෙනුව ඔබට grub-install ස්වයංක්â€à¶»à·“යව ධà·à·€à¶±à¶º විය යුත්තේ "
+"කුමන උපකරණ මත දà·à¶ºà·’ තේරීමට ඉඩදෙයි."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"බොහ෠අවස්ථ෠වලදී grub-install ස්වයංක්â€à¶»à·“යව ධà·à·€à¶±à¶º කිරීම නිර්දේà·à·’තයි. GRUB මොඩියුල à·„à· grub."
+"cfg මගින් ස්ථà·à¶´à·’ත GRUB මූල පිළිබිඹුව සම්මුහුර්තයෙන් බà·à·„à·à¶» යà·à¶¸ වලක්වයි."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ඔබට ඔබේ BIOS මගින් සඳහන් කර ඇති ආරම්භක ධà·à·€à¶šà¶º කුමක් දà·à¶ºà·’ විà·à·Šà·€à·à·ƒ නොමà·à¶­à·’ නම්. සියල්ලේම GRUB "
+"පිහිටුවීම හොඳ අදහසකි."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"සටහන: GRUB කොටස් ආරම්භක à·€à·à¶»à·Šà¶®à· තුළද පිහිටුවිය à·„à·à¶š. එමෙන්ම ඇතà·à¶¸à·Š සුදුසු කොටස් මෙහිදී පිරිනà·à¶¸à·š. "
+"කෙසේවුවත්, මෙය GRUB වෙත à·€à·à¶½à¶šà·”ම් ලà·à¶ºà·’ස්තු ක්â€à¶»à·’යà·à·€à¶½à·’ය සිදුකිරිමට බල කරයි. එය වඩ෠අස්ථිර බà·à·€à·’න් "
+"නිර්දේ෠නොකෙරේ."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB ආරම්භක පූරකය දà·à¶±à¶§ නොපවතින තà·à¶§à·’යට ස්ථà·à¶´à¶±à¶º කර තිබී ඇත. හ෠එහි අනන්â€à¶º à·„à·à¶³à·’න්වීම කිසියම් "
+"හේතුවක් නිස෠වෙනස් වී ඇත. ස්ථà·à¶´à·’ත GRUB මූල පිළිබිඹුව GRUB මොඩියුල à·„à· grub.cfg සමඟ සම්මුහුර්ත "
+"බව තහවුරු කරගà·à¶±à·“ම à·€à·à¶¯à¶œà¶­à·Šà·€à·š. කරුණà·à¶šà¶» සුදුසු ආරම්භක උපකරණයන් à·„à·’ GRUB ලියà·à·€à·“ ඇතිදà·à¶ºà·’ නà·à·€à¶­ "
+"පිරික්සන්න."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUB ආරම්භක උපකරණය ලිවීම අසà·à¶»à·Šà¶®à¶šà¶ºà·’ - ඉදිරියට?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB පහත උපකරණ ස්ථà·à¶´à¶±à¶ºà·™à·„à·’ අසà·à¶»à·Šà¶®à¶š විය:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr "ඔබට කෙසේ හ෠ඉදිරියට යෑමට ඇවà·à·ƒà·’ද? එසේ නම් ඔබේ පරිගණකය නිසිපරිදි ආරම්භ නොවනු ඇත."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "GRUB ආරම්භක උපකරණය ලිවීම අසà·à¶»à·Šà¶®à¶šà¶ºà·’ - නà·à·€à¶­ උත්සà·à·„?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"ඔබට GRUB වෙනත් උපකරණයක ස්ථà·à¶´à¶±à¶º කල à·„à·à¶š. ඒ අතර ඔබේ පද්ධතිය එම උපකරණය මගින් ආරම්භ "
+"වේදà·à¶ºà·’ සොයà·à¶¶à¶½à¶±à·Šà¶±. එසේ නොමà·à¶­à·’ නම් පà·à¶»à¶«à·’ GRUB වෙතින් යà·à·€à¶­à·Š වීම අවලංගු වේ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB ස්ථà·à¶´à¶±à¶ºà·™à¶±à·Š තොරව ඉදිරියට යන්නද?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"ඔබ කිසිඳු උපකරණයකට GRUB ස්ථà·à¶´à¶±à¶º නොකිරීමට තà·à¶»à· ඇත. ඔබ ඉදිරියට යයි නම් ආරම්භක පූරකය නිසිලෙස "
+"නොසà·à¶šà·ƒà·™à¶±à·” ඇත. ඊලඟ වතà·à·€à·š පරිගණකය ආරම්භ වන විට එය ආරම්භක කොටසේ පà·à·€à¶­à·’ ඕනෑම දෙයක් භà·à·€à·’ත "
+"කරයි. ආරම්භක කොටසේ GRUB 2 පà·à¶»à¶«à·’ සංස්කරණයක් පවතී නම්. එය මොඩියුල à·„à·à·ƒà·’රවීමේ හ෠වත්මන් à·ƒà·à¶šà·ƒà·”ම් "
+"ගොනුව භà·à·€à·’තයේ අසමත් විය à·„à·à¶š."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ඔබ දà·à¶±à¶§à¶¸à¶­à·Š වෙනස් ආරම්භක පූරකයක් භà·à·€à·’ත කරයි නම් හ෠එය දිගටම භà·à·€à·’ත කිරීමට ඇවà·à·ƒà·’ නම්. හ෠මෙය "
+"ආරම්භක පූරකයක් ඇවà·à·ƒà·’ නොවන විà·à·šà·‚ිත පරිසරයක් නම්. ඔබට කෙසේ හ෠ඉදිරියට ය෠හà·à¶š. එසේ නොවේ "
+"නම්, ඔබට කොතà·à¶±à¶š à·„à· GRUB ස්ථà·à¶´à¶±à¶ºà¶§ සිදුවේ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr " /boot/grub වෙතින් GRUB 2 ඉවත් කරන්නද?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "ඔබට /boot/grub වෙතින් සියළු GRUB 2 ගොනු ඉවත් කිරිමට ඇවà·à·ƒà·’ද?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "මෙය වෙනත් ආරම්භක පූරකයක් ස්ථà·à¶´à¶±à¶º කරන තුරු පද්ධතිය ආරම්භ කල නොහà·à¶šà·’ කරයි."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "GRUB 2 වෙත à·„à·à¶»à·€à·“ම අවසන් කරන්නද?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"තවමත් මෙම පද්ධතිය සතුව පà·à¶»à¶«à·’ GRUB ආරම්භක පූරකය ස්ථà·à¶´à·’තව පවතී. නමුත් පහත තà·à¶§à·’ තුළ දà·à¶±à¶§ GRUB "
+"2 ආරම්භක à·€à·à¶»à·Šà¶®à· ස්ථà·à¶´à·’තව ඇත."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"පà·à¶»à¶«à·’ GRUB භà·à·€à·’තයේ නොපවතින ලෙසක් දිස්වේ. එනම් ඔබට එම තà·à¶§à·’ වල GRUB 2 පිළිබිඹු යà·à·€à¶­à·Š කිරීමට "
+"à·„à· GRUB 2 වෙත à·„à·à¶»à·€à·“ම සම්පූර්ණ කිරීමට පà·à¶»à¶«à·’ GRUB ගොනු ඉවත්කිරීමට සිදුවන බවයි. ඒව෠නව පà·à¶šà·šà¶¢ "
+"සමඟ සහà·à¶º නොදක්වනු ඇති අතර ඔබේ පද්ධතිය නිසිලෙස ආරම්භ නොවනු ඇත."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"GRUB 2 ස්ථà·à¶´à¶±à¶º මගින් වෙනත් මෙහෙයුම් පද්ධතියක් මත මෙම ආරම්භක à·€à·à¶»à·Šà¶®à· නිර්මà·à¶«à¶º කර නොමà·à¶­à·’ නම්, "
+"ඔබ à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà·™à¶±à·Š GRUB 2 වෙත à·„à·à¶»à·€à·“ම අවසන් කල යුතුයි."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux විධà·à¶± රේඛà·à·€:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"පහත Linux විධà·à¶±à¶º /etc/default/grub හ෠පà·à¶»à¶«à·’ GRUB à·„à·’ menu.lst à·„à·’ 'kopt' පරà·à¶¸à·’තියෙන් "
+"උපුටà·à¶œà¶±à·Šà¶±à· ලදී. කරුණà·à¶šà¶» එය නිවà·à¶»à¶¯à·’ දà·à¶ºà·’ තහවුරු කරන්න, ඇවà·à·ƒà·’නම් වෙනස්කම් කරන්න. විධà·à¶± රේඛà·à·€ "
+"හිස්ව පà·à·€à¶­à·“මට ඉඩදෙයි. "
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "පෙරනිමි Linux විධà·à¶± රේඛà·à·€:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"පහත යෙදුම පෙරනිමි මෙනු ඇතුළත් කිරීම් සඳහ෠Linux පරà·à¶¸à·’තියක් ලෙස භà·à·€à·’ත වන නමුත් ගà·à¶½à·€à·“ම් ප්â€à¶»à¶šà·à¶»à¶ºà¶§ "
+"නොවේ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD විධà·à¶± රේඛà·à·€:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"පහත kFreeBSD විධà·à¶±à¶º /etc/default/grub හ෠පà·à¶»à¶«à·’ GRUB à·„à·’ menu.lst à·„à·’ 'kopt' "
+"පරà·à¶¸à·’තියෙන් උපුටà·à¶œà¶±à·Šà¶±à· ලදී. කරුණà·à¶šà¶» එය නිවà·à¶»à¶¯à·’ දà·à¶ºà·’ තහවුරු කරන්න, ඇවà·à·ƒà·’නම් වෙනස්කම් කරන්න. "
+"විධà·à¶± රේඛà·à·€ හිස්ව පà·à·€à¶­à·“මට ඉඩදෙයි. "
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD පෙරනිමි විධà·à¶± රේඛà·à·€:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"පහත යෙදුම පෙරනිමි මෙනු ඇතුළත් කිරීම් සඳහ෠kFreeBSD පරà·à¶¸à·’තියක් ලෙස භà·à·€à·’ත වන නමුත් ගà·à¶½à·€à·“ම් "
+"ප්â€à¶»à¶šà·à¶»à¶ºà¶§ නොවේ."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map නà·à·€à¶­ ජනනය වී ඇත"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "ස්ථà·à·€à¶» උපකරණ නà·à¶¸ භà·à·€à·’තය සඳහ෠/boot/grub/device.map නà·à·€à¶­ ලියවිනි. බොහ෠අවස්ථà·à·€à¶½, "
+#~ "මෙය ඉදිරියේදී වෙනස් කිරීමට ඇවà·à·ƒà·’ නොවේ, තවද GRUB මගින් ජනිත ආරම්භක මෙනු ඇතුළත් කිරීම් වෙනස් "
+#~ "නොකල යුතුයි."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "කෙසේ වුවත් පද්ධතියේ තà·à¶§à·’ එකකට වඩ෠පවතින බà·à·€à·’න්, පද්ධතිය පà·à¶»à¶«à·’ උපකරණ සිතියමක් මත "
+#~ "රඳà·à¶´à·€à¶­à·’නව෠විය à·„à·à¶š. කරුණà·à¶šà¶» GRUB à·„à·’ (hdN) ධà·à·€à¶š අංකකරණය මත රඳà·à¶´à·€à¶­à·’න රුචි ආරම්භක "
+#~ "මෙනු ඇතුළත් කිරීම් පවතීදà·à¶ºà·’ සොයන්න. ඇවà·à·ƒà·’නම් ඒව෠යà·à·€à¶­à·Š කරන්න."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "මෙම පණිවුඩය ඔබට තේරුම්ගත නොහà·à¶šà·’ නම් à·„à·, කිසිඳු රුචි ආරම්භක මෙනු ඇතුළත්කිරිමක් නොමà·à¶­à·’ නම් ඔබට "
+#~ "මෙම පණිවුඩය මඟහà·à¶»à·’ය à·„à·à¶š."
diff --git a/debian/po/sk.po b/debian/po/sk.po
new file mode 100644
index 0000000..8f45b48
--- /dev/null
+++ b/debian/po/sk.po
@@ -0,0 +1,468 @@
+# Slovak translations for grub2 package.
+# Copyright (C) 2010 THE grub2'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub2 package.
+# Slavko <linux@slavino.sk>, 2010, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 1.99-5\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2011-07-19 07:49+0200\n"
+"Last-Translator: Slavko <linux@slavino.sk>\n"
+"Language-Team: Slovak <nomail>\n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Zreťaziť z menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"AktualizaÄné skripty GRUB zistili nastavenie starej verzie GRUB (Legacy) v /"
+"boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Na nahradenie starej verzie GRUB (Legacy) vo vaÅ¡om systéme, je odporúÄané "
+"aby bol /boot/grub/menu.lst prispôsobený na zreťazenie (chainload) "
+"zavádzacieho obrazu GRUB 2 z vášho existujúceho nastavenia GRUB (Legacy). "
+"Tento krok môže byť automaticky vykonaný teraz."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Je odporúÄané aby ste schválili zreÅ¥azenie GRUB 2 z menu.lst a overili, že "
+"nastavenie vášho nového GRUB 2 je funkÄné eÅ¡te predtým, ako bude zapísaný do "
+"vášho MBR (Master Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Nech sa rozhodnete akokoľvek, neskôr môžete nahradiť obraz MBR s GRUB 2 "
+"spustením nasledujúceho príkazu s právami root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Zariadenia na inštaláciu GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Balík grub-pc je aktualizovaný. Toto menu vám umožňuje vybrať si, pre ktoré "
+"zariadenia bude automaticky spustený grub-install, ak nejaké vyberiete."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Vo väÄÅ¡ine prípadov je odporúÄané spustiÅ¥ automaticky grub-install, aby ste "
+"predišli tomu, že máte nainštalované rôzne verzie základného obrazu GRUB a "
+"modulov GRUB, Äi grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ak si nie ste istý, ktoré zariadenie je nastavené na zavádzanie vo vašom "
+"BIOSe, Äasto je dobrý nápad nainÅ¡talovaÅ¥ GRUB na vÅ¡etky."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Poznámka: je možné nainštalovať GRUB aj do zavádzacieho sektora partície a v "
+"zozname sú aj niektoré príslušné partície. Avšak, tento spôsob vynúti aby "
+"GRUB požil mechanizmus blocklist, ktorý ho robí menej spoľahlivým a preto "
+"nie je odporúÄaný."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"ZavádzaÄ GRUB bol predtým nainÅ¡talovaný na disk, ktorý sa už v systéme "
+"nenachádza alebo ktorého unikátny identifikátor bol z nejakého dôvodu "
+"zmenený. Je dôležité zaistiť, aby nainštalovaný základný obraz GRUB mal "
+"rovnakú verziu ako moduly GRUB a grub.cfg. Prosím pre istotu znova "
+"skontrolujte, že je GRUB zapisovaný do správnych zavádzacích zariadení."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Zápis GRUBu do zavádzacieho zariadenia zlyhal – pokraÄovaÅ¥?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Inštalácia GRUB zlyhala na týchto zariadeniach:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Chcete napriek tomu pokraÄovaÅ¥? Ak áno, môže sa staÅ¥, že váš poÄítaÄ "
+"nenaštartuje správne."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Zápis GRUB do zavádzacieho zariadenia zlyhal – skúsiť znova?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Možno sa vám podarí nainštalovať GRUB aj na niektoré iné zariadenie, ale "
+"musíte skontrolovať, že váš systém dokáže z neho zavádzať. Inak bude "
+"aktualizácia zo starého GRUB (Legacy) zrušená."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "PokraÄovaÅ¥ bez inÅ¡talácie GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Zvolili ste si neinÅ¡talovaÅ¥ GRUB na žiadne zariadenie, ak budete pokraÄovaÅ¥, "
+"zavádzaÄ nemusí byÅ¥ správne nastavený a pri ÄalÅ¡om Å¡tarte tohoto poÄítaÄa "
+"bude použité to, Äo bolo v zavádzacom sektore predtým. Ak je v zavádzacom "
+"sektore predchádzajúca verzia GRUB 2, nemusí sa jej podariÅ¥ naÄítaÅ¥ moduly "
+"alebo spracovaÅ¥ aktuálny konfiguraÄný súbor."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ak už používate iný zavádzaÄ a chcete ho zachovaÅ¥, alebo ak používate "
+"Å¡peciálne prostredie, v ktorom zavádzaÄ nepotrebujete, potom môžete "
+"pokraÄovaÅ¥. V opaÄnom prípade by ste mali niekde GRUB nainÅ¡talovaÅ¥."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Odstrániť GRUB 2 z /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Chcete odstrániť všetky súbory GRUB 2 z /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Týmto nebude možné váš systém naštartovať, kým nebude nainštalovaný iný "
+"zavádzaÄ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "DokonÄiÅ¥ konverziu na GRUB 2 teraz?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Tento systém má stále nainÅ¡talované súbory zo starého zavádzaÄa GRUB "
+"(Legacy), ale má nainštalované aj nové zavádzacie záznamy GRUB 2 na týchto "
+"diskoch:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Vyzerá to, že starý GRUB (Legacy) už nie je používaný, a tak môžete na "
+"týchto diskoch aktualizovaÅ¥ obrazy GRUB 2 a dokonÄiÅ¥ konverziu na GRUB 2 "
+"odstránením súborov starého GRUB (Legacy). Ak nezaktualizuje tieto obrazy "
+"GRUB 2, potom nemusia byť kompatibilné s novými balíkmi a môžu narušiť "
+"správne zavádzanie systému."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Mali by ste dokonÄiÅ¥ konverziu na GRUB 2, ibaže boli tieto zavádzacie "
+"záznamy vytvorené inÅ¡taláciou GRUB 2 iného operaÄného systému."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linuxový príkazový riadok:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Nasledujúci príkazový riadok Linuxu bol získaný z /etc/default/grub alebo z "
+"parametra 'kopt' z menu.lst starého GRUB (Legacy). Skontrolujte prosím jeho "
+"správnosť a prípadne ho upravte. Príkazový riadok môže byť aj prázdny."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Predvolený Linuxový príkazový riadok:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Nasledujúci reťazec bude použitý ako Linuxové parametre predvolenej položky "
+"menu, ale nie pre záchranný režim."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Príkazový riadok kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Nasledujúci príkazový riadok kFreeBSD bol získaný z /etc/default/grub alebo "
+"z parametra 'kopt' z menu.lst starého GRUB (Legacy). Skontrolujte prosím "
+"jeho správnosť a prípadne ho upravte. Príkazový riadok môže byť aj prázdny."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Predvolený príkazový riadok kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Nasledujúci reťazec bude použitý ako kFreeBSD parametre predvolenej položky "
+"menu, ale nie pre záchranný režim."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map bol aktualizovaný"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Súbor /boot/grub/device.map bol upravený tak, aby používal stabilné mená "
+#~ "zariadení. VäÄÅ¡inou to významne zníži potrebu zmien v budúcnosti a "
+#~ "položky zavádzacieho menu, generované GRUBom, by tým nemali byť "
+#~ "ovplyvnené."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "AvÅ¡ak, keÄže máte vo svojom systéme viac ako jeden disk, je možné, že "
+#~ "systém závisí na starej mape zariadení. Skontrolujte prosím, že "
+#~ "nepoužívate žiadne položky menu, ktoré závisia na Äíslovaní zariadení "
+#~ "GRUBu (hdN) a prípadne ich aktualizuje."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ak nerozumiete tejto správe, alebo ak nemáte žiadne vlastné položky "
+#~ "zavádzacieho menu, môžete túto správu ignorovať."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "KeÄ sa rozhodnete zavádzaÅ¥ GRUB 2 priamo z MBR, môžete to urobiÅ¥ pomocou "
+#~ "nasledujúceho príkazu (ako root):"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "InÅ¡talácia GRUB zlyhala. PokraÄovaÅ¥?"
diff --git a/debian/po/sl.po b/debian/po/sl.po
new file mode 100644
index 0000000..2a95405
--- /dev/null
+++ b/debian/po/sl.po
@@ -0,0 +1,481 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-20 08:53+0100\n"
+"Last-Translator: Vanja Cvelbar <cvelbar@gmail.com>\n"
+"Language-Team: Slovenian <sl@li.org>\n"
+"Language: sl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
+"n%100==4 ? 3 : 0);\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Generator: Poedit 1.6.10\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Verižno nalaganje iz menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "Skript za nadgradnjo je zaznal namestitev GRUB Legacy v /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Da zamenjate razliÄico GRUB Legacy na vaÅ¡em sistemu vam priporoÄamo, da se /"
+"boot/grub/menu.lst spremeni tako, da verižno naloži GRUB 2 iz vaÅ¡e obstojeÄe "
+"namestitve GRUB Legacy. To dejanje lahko zdaj izvedete samodejno."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"PriporoÄamo vam, da sprejmete verižno nalaganje GRUB 2 iz datoteke menu.lst "
+"in preverite delovanje namestitve GRUB2 preden ga namestite na MBR (Master "
+"Boot Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Kakorkoli se odloÄite, stari MBR lahko kasneje vedno zamenjate z GRUB 2, Äe "
+"izvedete kot root sledeÄi ukaz:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Namestitvene naprave za GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Nadgrajevanje paketa grub-pc. Ta meni vam omogoÄi izbiro naprav za katere "
+"želite samodejno zagnati grub-install."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"V veÄini primerov je priporoÄen samodejni zagon grub-install, da prepreÄite "
+"neskladja med jedrom GRUBa in moduli ali grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"V primeru, da niste prepriÄani kateri pogon je oznaÄuje vaÅ¡ BIOS za "
+"zagonskega, je ponavadi dobro, da namestite GRUB kar na vse."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Opomba: GRUB je mogoÄe namestiti tudi na zagonski zapis razdelka. Primerni "
+"razdelki so na tem spisku. To pa zahteva uporabo mehanizma blocklist, ki je "
+"manj zanesljiv in zato ni priporoÄen."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Zagonski nalagalnik GRUB je bil nameÅ¡Äen na disku, ki ni veÄ prisoten ali se "
+"mu je spremenil enoliÄni identifikator. Važno je, da so jedro GRUBa in "
+"moduli ter grub.cfg skladni. Preverite prosim, da je GRUB zapisan na "
+"pravilno zagonsko napravo."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Napaka pri pisanju na zagonsko napravo za GRUB. Želite nadaljevati?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Napaka pri nameÅ¡Äanju GRUBa na sledeÄe naprave:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Želite vseeno nadaljevati? V primeru, da boste nadaljevali se raÄunalnik "
+"mogoÄe ne bo pravilno zagnal."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"NameÅ¡Äanje GRUBa na zagonsko napravo ni uspelo. Želite Å¡e enkrat poskusiti?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"MogoÄe lahko namestite GRUB na katero drugo napravo, preveriti pa morate, da "
+"se bo lahko vaÅ¡ sistem zagnal iz te naprave. DrugaÄe bo posodobitev iz "
+"zastarelega GRUB prekinjena ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Želite nadaljevati, ne da bi namestili GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Izbrali ste, da ne boste namestili GRUBa na nobeno napravo. V primeru, da "
+"nadaljujete zagonski nalagalnik ne bo pravilno nastavljen. RaÄunalnik bo ob "
+"naslednjem zagonu uporabil karkoli je bilo prej nameÅ¡Äeno na zagonskem "
+"sektorju. V primeru, da se tam nahaja starejÅ¡a razliÄica GRUB 2 mogoÄe ta ne "
+"bo uspela naložiti modulov ali brati sedanje nastavitvene datoteke."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"V primeru, da že uporabljate razliÄen zagonski nalagalnik in želite s tem "
+"nadaljevati ali pa je to posebno zagonsko okolje kjer ne rabite zagonskega "
+"nalagalnika lahko vsekakor nadaljujete. V ostalih primerih bi morali nekam "
+"namestiti GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Želite odstraniti GRUB 2 iz /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+"Želite odstraniti iz /boot/grub vse datoteke, ki se nanašajo na GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Zaradi tega se sistem ne bo mogel zagnati, razen, Äe uporabite drugi "
+"zagonski nalagalnik."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Želite zdaj dokonÄati pretvorbo v GRUB 2?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Na tem sistemu so Å¡e nameÅ¡Äene datoteke iz zastarelega GRUBa, a zdaj je "
+"nameÅ¡Äen tudi zagonski zapis GRUB 2 na sledeÄih diskih:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Zdi se verjetno, da zastareli GRUB ni veÄ v uporabi in da bi morali namesto "
+"tega nadgraditi te diske na GRUB 2 ter dokonÄati pretvorbo v GRUB 2 z "
+"odstranitvijo datotek za zastareli GRUB. V primeru, da ne boste izvedli "
+"nadgradnje na GRUB 2 lahko pride do nezdružljivosti z novimi paketi in težav "
+"pri zagonu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"ObiÄajno bi morali dokonÄati pretvorbo v GRUB 2 razen, Äe so bili ti "
+"zagonski zapisi ustvarjeni pri nameÅ¡Äanju GRUB 2 na drugem operacijskem "
+"sistemu."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Ukazna vrstica Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"SledeÄi ukaz za Linux je vzet iz datoteke /etc/default/grub ali iz parametra "
+"`kopt' v datoteki menu.lst sistema GRUB Legacy. Preverite prosim, da je "
+"toÄen in ga po potrebi popravite. Ukazna vrstica je lahko tudi prazna."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Privzeta ukazna vrstica Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"SledeÄa vrstica bo uporabljena kot parameter Linuxa za privzeti vnos v "
+"meniju, ne pa za reÅ¡evalni naÄin."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Prisilna dodatna namestitev v pot EFI na odstranljivem mediju?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Nekateri sistemi na osnovi EFI imajo napake in ne morejo pravilno "
+"uporabljati novih zagonskih nalagalnikov. ÄŒe prisilno dodatno namestite GRUB "
+"v pot EFI na odstranljivem mediju, bi to moralo zadostovati, da bo, kljub "
+"tem težavam, lahko sistem zagnal Debian. Zaradi tega pa mogoÄe ne boste "
+"mogli veÄ zagnati drugih operacijskih sistemov, ki so odvisni od te poti. V "
+"takem primeru morate preveriti, da je GRUB pravilno nastavljen in boste "
+"lahko zagnali tudi druge operacijske sisteme."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Želite posodobiti spremenljivke NVRAM za samodejni zagon v Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB lahko nastavi spremenljivke NVRAM vaÅ¡ega raÄunalniÅ¡kega okolja tako, da "
+"samodejno zažene Debian ob vklopu. V primeru, da tega ne želite, lahko to "
+"onemogoÄite in prepreÄite spremembo vaÅ¡e zagonske konfiguracije. Na primer, "
+"Äe so spremenljivke NVRAM nastavljene tako, da vaÅ¡ sistem ob vsakem zagonu "
+"komunicira s strežnikom PXE, bo ta nastavitev ohranjena."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Ukazna vrstica kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"SledeÄi ukaz za kFreeBSD je vzet iz datoteke /etc/default/grub ali iz "
+"parametra `kopt' v datoteki menu.lst sistema GRUB Legacy. Preverite "
+"prosim, da je toÄen in ga po potrebi popravite. Ukazna vrstica je lahko tudi "
+"prazna."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Privzeta ukazna vrstica kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"SledeÄa vrstica bo uporabljena kot parameter kFreeBSD za privzeti vnos v "
+"meniju, ne pa za reÅ¡evalni naÄin."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "ustvarjena je bila datoteka /boot/grub/device.map"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Datoteka /boot/grub/device.map je bila prepisana s stabilnimi imeni "
+#~ "naprav. V veÄini primerov bo to v prihodnosti moÄno zmanjÅ¡alo potrebo po "
+#~ "njenih spremembah. Na vnose v zagonskem meniju, ki jih ustvari GRUB to ne "
+#~ "bi smelo imeti uÄinka."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ker imate veÄ kot en disk na vaÅ¡em sistemu je možno, da ste bili odvisni "
+#~ "od starega spiska naprav. Preverite prosim ali imate kakšen vnos po meri "
+#~ "v zagonskem meniju, ki se naslanja na poimenovanje diskov (hdN) v GRUBu "
+#~ "in ga posodobite, Äe je to potrebno."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "V primeru, da tega sporoÄila ne razumete ali nimate nobenih vnosov po "
+#~ "meri v zagonskem meniju se za to sporoÄilo ne menite."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "V primeru, da želite, da se GRUB 2 naloži neposredno iz MBRja, lahko v "
+#~ "obeh primerih zaženete (kot sistemski skrbnik) sledeÄi ukaz:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "GRUB ni bil nameÅ¡Äen. Želite nadaljevati?"
diff --git a/debian/po/sq.po b/debian/po/sq.po
new file mode 100644
index 0000000..25210f1
--- /dev/null
+++ b/debian/po/sq.po
@@ -0,0 +1,463 @@
+# translation of grub_debian_po_sq.po to Albanian
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+#
+# Silva Arapi <silva.arapi@gmail.com>, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-09-04 18:50+0200\n"
+"Last-Translator: Silva Arapi <silva.arapi@gmail.com>\n"
+"Language-Team: Albanian <debian-l10n-albanian@lists.debian.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : "
+"4;\n"
+"X-Generator: Gtranslator 2.91.7\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Ngarko zinxhir nga menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Skriptet e përmirësimit të GRUB zbuluan një ndertim të trashëguar të GRUB "
+"në /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Në mënyrë që të zëvëndësoni versionin e trashëguar të GRUB në sistemin tuaj, "
+"rekomandohet që /boot/grub/menu.lst të rregullohet në mënyrë të tillë që të "
+"ngarkoj një imazh të GRUB 2 nga konfigurimi i trashëguar i GRUB ekzistues."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Rekomandohet që të pranosh ngarkimin zinxhir GRUB 2 nga menu.lst, dhe të "
+"verifikosh që konfigurimi i ri GRUB 2 punon para se ai të shkruhet në MBR "
+"(Master Boot Record)"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Cilido të jetë vendimi, ti mund të zëvëndësosh imazhin e vjetër MBR me GRUB "
+"2 me vonë duke ekzekutuar komandën e mëposhtme si root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Paisjet GRUB install:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Paketa po përmirësohet. Kjo menu të lejon të zgjedhësh se cilat paisje do të "
+"doje që grub-install ti ekzekutoj automatikisht, nëse ka ndonjë të till."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Ekzekutimi i grub-install automatikisht rekomandohet në shumicën e "
+"situatave, për të parandaluar imazhin e instaluar të GRUB core që të dal "
+"jashtë sinkronizimi me modulet e GRUB dhe grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Nëse nuk je i sigurt se cili drive është caktuar si drive i ndezjes nga BIOS "
+"i juaj, zakonisht është ide e mirë ta instaloni GRUB në secilin prej tyre. "
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Shënim: është gjithashtu e mundur që të instaloni GRUB për të ndarë "
+"rekoredet e ndezjes, dhe disa ndarje të përshtatshme janë këtu. Gjithsesi, "
+"kjo e detyron GRUB të përdorë mekanizmin blocklist, gjë që e bënë atë më pak "
+"të besueshëm, dhe për këtë arsye nuk rekomandohet."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Ngarkuesi i ndezjes GRUB ishte më parë i instaluar në një disk që nuk është "
+"më i pranishëm, ose identifikuesi unik i të cilit ka ndryshuar për ndonjë "
+"arsye. Është e rëndësishme që të sigurohesh që imazhi i instaluar i GRUB "
+"core të qëndoroj në sinkronizim me modulet GRUB dhe grub.cfg. Të lutem "
+"kontollo përsëri që GRUB të shkruhet në paisjet e duhura të ndezjes."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Shkrimi i GRUP për të ndezur paisjen dvshtoi - do të vazhdoni?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB nuk arriti të instaloj paisjet në vijim:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Dëshironi të vazhdoni gjithsesi? Nëse po, kompjuteri juaj nuk do të filloj "
+"siç duhet."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Shkrimi i GRUB për të ndezur paisjen dështoi - do e provosh përsëri?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Ti mund të jesh në gjëndje ta instalosh GRUB nga disa paisje të tjera, "
+"gjithsesi ti duhet të kontrollosh që sistemi do të ndizet nga ajo paisje. "
+"Përndryshe, përmirësimi nga GRUB i trashëguar do të anullohet."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Do të vazhdosh pa e instaluar GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Ti zgjodhe të mos e instalosh GRUB në asnjë paisje. Nëse vazhdon, ngarkuesi "
+"i ndezjes mund të mos konfigurohet siç duhet dhe kur ky kompjuter të filloj "
+"herën tjetër, do të përdor çfardo ishte më parë në sektorin e ndezjes."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Nëse po e përdorni tashmë një ngarkues të ndezjes të ndryshëm dhe doni të "
+"vazhdoni me të, ose nëse ky është një mjedis i vacantë ku ju nuk keni nevoj "
+"për ngarkuesin e ndezjes atëherë ti duhet të vazhdosh gjithsesi. Përndryshe "
+"ju duhet ta instaloni GRUB diku."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Do e fshish GRUB 2 nga /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Do që ti heqësh të gjitha filet e GRUB 2 nga /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Kjo do e bëjë sistemin jo të ndezshëm për sa kohë nuk instalohet një tjetër "
+"ngarkues i ndezjes."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Përfundo konvertimin në GRUB 2 tani?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ky sistem ka akoma skedar nga ngarkuesi i ndezjes i trashëguar GRUB që është "
+"i instaluar, por tani ka edhe rekordet e ndezjes GRUB 2 të instaluara në "
+"këto disqe:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Duket se GRUB i trashëguar nuk është më në përdorim, dhe ti duhet të "
+"përmirësosh imazhet GRUB 2 në këto disqe dhe të përfundosh konvertimin në "
+"GRUB 2 duke hequr skedarët e vjetër të trashëguar GRUB. Nëse ti nuk i "
+"përmirëson këto imazhe GRUB 2, atëherë ato mund të mos përputhen me paketat "
+"dhe të shkaktojnë fillomin jo si duhet të ndezjes."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Ti duhet të përfundosh në përgjithësi konvertimin në GRUB 2 përveç rasteve "
+"kur këto rekorde të ndezjes janë krijuar nga instalimi i GRUB 2 në ndonjë "
+"sistem shfrytëzimi tjetër. "
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linja komanduese linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Linja komanduese në vijim u ekstraktua nga /etc/default/grub ose nga "
+"parametri 'kopt' në menu.lst në GRUB të trashëguar. Të lutem verifiko nëse "
+"është korrekte ose modifikoje nëse do jetë e nevojshme. Kjo linjë komanduese "
+"lejohet të jetë bosh."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linja komanduese fillestare linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Stringu në vijim do të përdoren si parametër Linux për menun fillaster "
+"hyrëse por jo për gjëndjen e rekuperimit."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Linja komanduese kFreeBSD"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Linja komanduese kFreeBSD e mëposhtme u ekstraktua nga /etc/default/grub ose "
+"parametri `kopt'në menu.lst të GRUB të trashëguar. Të lutem verifiko që ajo "
+"është korrekte, dhe modifikoje nëse do jetë e nevojshme. Kjo linjë "
+"komanduese lejohet të jetë bosh."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Linja komanduese fillestare kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Stringu në vijim do të përdoren si parametër kFreeBSD për menun fillaster "
+"hyrëse por jo për gjëndjen e rekuperimit."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr " /boot/grub/device.map është rigjeneruar"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Skedari /boot/grub/device.map është rishkruar për të përdorur emra "
+#~ "paisjesh të qëndrueshëm. Në shumicën e rasteve, kjo duhet të reduktoj "
+#~ "dukshëm nevojën për ta ndryshuar atë në të ardhmen, dhe hyrësit e menus "
+#~ "së ndezjes së gjeneruar nga GRUB nuk duhet të preken."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Gjithsesi, meqë më shumë se një disk është i pranishëm në sistem, është e "
+#~ "mundur që sistemi të jetë i varuar nga harta e paisjes së mëparshme. Të "
+#~ "lutem kontrollo nëse ka ndonjë menu hyrëse të ndezjes që mbështetet në "
+#~ "numërimin e drive të GRUB (hdN), dhe përditësoje atë nëse do jetë e "
+#~ "nevojshme."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Nëse nuk e kupton këtë mesazh, ose nëse nuk ka menu të zakonshme hyrëse, "
+#~ "ti mund ta injorosh këtë mesazh."
diff --git a/debian/po/sr.po b/debian/po/sr.po
new file mode 100644
index 0000000..371fb2a
--- /dev/null
+++ b/debian/po/sr.po
@@ -0,0 +1,457 @@
+# Serbian/Cyrillic messages for grub2.
+# Copyright (C) 2010-2012 Software in the Public Interest, Inc.
+# This file is distributed under the same license as the grub2 package.
+# Janos Guljas <janos@resenje.org>, 2010-2012.
+# Karolina Kalic <karolina@resenje.org>, 2010-2012.
+# Milan Kostic <kosticmilan77@open.telekom.rs>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 1.98+2010804-2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-10-23 23:33+0100\n"
+"Last-Translator: Karolina Kalic <karolina@resenje.org>\n"
+"Language-Team: Serbian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Чеинлоуд из „menu.lst“?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB Ñкрипте за апгрејд Ñу пронашле подешавања за GRUB Legacy у /boot/grub "
+"фолдеру."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Да биÑте заменили Legacy верзију GRUB-а у вашем ÑиÑтему, препоручује Ñе да "
+"Ñе /boot/grub/menu.lst фајл прилагоди да учитава GRUB 2 Ñлику за покретање "
+"из поÑтојећег GRUB Legacy подешавања. Овај корак може аутоматÑки Ñада да Ñе "
+"изврши."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Препоручљиво је да прихватите учитавање GRUB 2 из menu.lst, и потврдите да "
+"нова GRUB 2 подешавања раде пре него што Ñе запишу на MBR (Master Boot "
+"Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Која год да је ваша одлука, можете заменити Ñтари MBR Ñа GRUB-ом 2 каÑније "
+"покретањем Ñледеће команде као рут:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Уређаји за инÑталирање GRUB-а:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Пакет grub-pc Ñе апгрејдује. Овај мени вам дозвољава да изаберете за које "
+"уређаје ће grub-install аутоматÑки да Ñе покрене."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Покретање grub-install програма аутоматÑки је препоручено у већини "
+"Ñитуација, да Ñпречи инÑталирану GRUB Ñржну Ñлику да избегне Ñинхронизацију "
+"Ñа GRUB модулима или grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ðко ниÑте Ñигурни који драјвер је дизајниран као покретачки драјвер у BIOS-"
+"у, најчешће је добра идеја да Ñе инÑталира GRUB на Ñве драјвере."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Могуће је такође инÑталирати GRUB у бут рекорд партиција, и неке од "
+"одговарајућих партиција Ñу понуђене овде. Међутим, GRUB тада кориÑти "
+"блоклиÑÑ‚ механизам, који је мање поуздан и не препоручује Ñе."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB је претходно био инÑталиран на диÑку који не поÑтоји, или чији Ñе "
+"јединÑтвени идентификациони број променио из неког разлога. Битно је да "
+"подаци GRUB-а буду Ñинхронизовани Ñа модулима и фајлом grub.cfg. Проверите "
+"да ли је GRUB инÑталиран на одговарајућем уређају."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB, ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "ИнÑталација GRUB-а није уÑпела - наÑтавити?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "ИнÑталација GRUB-а није уÑпела на Ñледећим уређајима:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Да ли желите да наÑтавите у Ñваком Ñлучају? Ðко наÑтавите, ваш рачунар Ñе "
+"можда неће добро покренути."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "ИнÑталација GRUB-а није уÑпела - покушати поново?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Можда можете да инÑталирате GRUB на неки други уређај, мада требате да "
+"проверите да ли ће Ñе ваш ÑиÑтем покренути Ñа тог уређаја. Иначе ће Ñе "
+"апгрејд GRUB Legacy-а отказати."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "ÐаÑтавити без инÑталирања GRUB-а?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Одабрали Ñте да не инÑталирате GRUB ни на један уређај. Ðко наÑтавите, бут "
+"учитавач можда неће бити иÑправно подешен, акада Ñе овај рачунар Ñледећи пут "
+"упали, кориÑтиће Ñе шта год да је претходно било у бут Ñектору. Ðко Ñе тамо "
+"налази ранијаверзија GRUB 2, можда ће доћи до проблема Ña учитавањем модула "
+"или читањем тренутне датотеке поÑтавки."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ðко већ имате неки други бут учитавач и желите га задржати, или ако је ово "
+"неко поÑебно окружење где не треба бут учитавач, можете наÑтавити. У "
+"Ñупротном, морали биÑте негде инÑталирати GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Уклонити GRUB 2 из /boot/grub фолдера?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Да ли желите да Ñве GRUB 2 фајлове уклоните из /boot/grub фолдера?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Ово ће учинити да ÑиÑтем не може да Ñе покрене оÑим ако други покретачки "
+"програм није инÑталиран."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Завршити конверзију на GRUB 2 Ñада?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Овај ÑиÑтем још увек има инаÑталиране фајлове Ñа GRUB Legacy покретачког "
+"програма, али Ñада Ñадржи GRUB 2 покретачке податке инÑталиране на Ñледећим "
+"диÑковима:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Изгледа да GRUB Legacy није више у употреби, умеÑто тога требали биÑте "
+"надоградити на GRUB 2 на диÑковима, а Ñ‚akoђе Ñамо пребацивање на GRUB 2 "
+"укључује и бриÑање Ñтарих GRUB Legacy датотека. Ðко ниÑте надоградили на "
+"GRUB 2, онда би могло доћи до некомпатибилноÑти Ñа новијим верзијама пакета, "
+"што би даље могло довеÑти и до немогућноÑти иÑправног покретања ÑиÑтема."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Требали биÑте да забршите конверзију на GRUB 2, оÑим ако Ñу ови покретачки "
+"подаци креирани од GRUB 2 инÑталације на неком другом оперативном ÑиÑтему."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux командна линија:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ова линија намењена за Linux keрнел је из /etc/default/grub (GRUB 2) или из "
+"„kopt“ параметра датотеке menu.lst (GRUB Legacy). Проверите да ли је линија "
+"иÑправна и ако треба поправите је. Линија иначе, може оÑтати и празна. "
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux подразумевајућа команда линија:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Следећи Ñтринг ће бити употребљен као Linux параметри за подреазумевано "
+"покретање, али не и за мод за поправку."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD командна линија:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ова линија намењена кFreeBSD keрнелу је из /etc/default/grub (GRUB 2) или из "
+"„kopt“ параметра датотеке menu.lst (GRUB Legacy). Проверите да ли је линија "
+"иÑправна и ако треба поправите је. Линија иначе, може оÑтати и празна."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD подразумевајућа командна линија:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Следећи Ñтринг ће бити употребљен као kFreeBSD параметри за подреазумевано "
+"покретање, али не и за мод за поправку."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map је поново генериÑан"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Датотека /boot/grub/device.map је поново напиÑана како би Ñе у њој "
+#~ "кориÑтили Ñтабилни називи за уређаје. У већини Ñлучајева, овим би Ñе "
+#~ "требало Ñмањити потреба за њеним мењањем, Ñ Ñ‚Ð¸Ð¼ да Ñтавке у GRUB менију "
+#~ "више не буду подложне таквој промени."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ипак, како поÑтоји више од једног диÑка на овом ÑиÑтему, могуће је да "
+#~ "завиÑите од Ñтаре мапе уређаја. Проверите имате ли неке од Ñтавки у GRUB "
+#~ "менију koje завиÑе од Ñтарог ÑиÑтема означавања (hdN) и aжурирајте их "
+#~ "уколико је потребно."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ðко не разумете ову поруку, или ако не поÑтоје прилагођени уноÑи за "
+#~ "покретачки мени, можете да игноришете ову поруку."
diff --git a/debian/po/sr@latin.po b/debian/po/sr@latin.po
new file mode 100644
index 0000000..fd8276b
--- /dev/null
+++ b/debian/po/sr@latin.po
@@ -0,0 +1,457 @@
+# Serbian/Latin messages for grub2.
+# Copyright (C) 2010-2012 Software in the Public Interest, Inc.
+# This file is distributed under the same license as the grub2 package.
+# Janos Guljas <janos@resenje.org>, 2010-2012.
+# Karolina Kalic <karolina@resenje.org>, 2010-2012.
+# Milan Kostic <kosticmilan77@open.telekom.rs>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2 1.98+2010804-2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-10-23 23:33+0100\n"
+"Last-Translator: Karolina Kalic <karolina@resenje.org>\n"
+"Language-Team: Serbian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Čeinloud iz „menu.lst“?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB skripte za apgrejd su pronašle podešavanja za GRUB Legacy u /boot/grub "
+"folderu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Da biste zamenili Legacy verziju GRUB-a u vaÅ¡em sistemu, preporuÄuje se da "
+"se /boot/grub/menu.lst fajl prilagodi da uÄitava GRUB 2 sliku za pokretanje "
+"iz postojećeg GRUB Legacy podešavanja. Ovaj korak može automatski sada da se "
+"izvrši."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"PreporuÄljivo je da prihvatite uÄitavanje GRUB 2 iz menu.lst, i potvrdite da "
+"nova GRUB 2 podešavanja rade pre nego što se zapišu na MBR (Master Boot "
+"Record)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Koja god da je vaša odluka, možete zameniti stari MBR sa GRUB-om 2 kasnije "
+"pokretanjem sledeće komande kao rut:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Uređaji za instaliranje GRUB-a:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Paket grub-pc se apgrejduje. Ovaj meni vam dozvoljava da izaberete za koje "
+"uređaje će grub-install automatski da se pokrene."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Pokretanje grub-install programa automatski je preporuÄeno u većini "
+"situacija, da spreÄi instaliranu GRUB sržnu sliku da izbegne sinhronizaciju "
+"sa GRUB modulima ili grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Ako niste sigurni koji drajver je dizajniran kao pokretaÄki drajver u BIOS-"
+"u, najÄešće je dobra ideja da se instalira GRUB na sve drajvere."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Moguće je takođe instalirati GRUB u but rekord particija, i neke od "
+"odgovarajućih particija su ponuđene ovde. Međutim, GRUB tada koristi "
+"bloklist mehanizam, koji je manje pouzdan i ne preporuÄuje se."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB je prethodno bio instaliran na disku koji ne postoji, ili Äiji se "
+"jedinstveni identifikacioni broj promenio iz nekog razloga. Bitno je da "
+"podaci GRUB-a budu sinhronizovani sa modulima i fajlom grub.cfg. Proverite "
+"da li je GRUB instaliran na odgovarajućem uređaju."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB, ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Instalacija GRUB-a nije uspela - nastaviti?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Instalacija GRUB-a nije uspela na sledećim uređajima:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Da li želite da nastavite u svakom sluÄaju? Ako nastavite, vaÅ¡ raÄunar se "
+"možda neće dobro pokrenuti."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Instalacija GRUB-a nije uspela - pokušati ponovo?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Možda možete da instalirate GRUB na neki drugi uređaj, mada trebate da "
+"proverite da li će se vaÅ¡ sistem pokrenuti sa tog ureÄ‘aja. InaÄe će se "
+"apgrejd GRUB Legacy-a otkazati."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Nastaviti bez instaliranja GRUB-a?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Odabrali ste da ne instalirate GRUB ni na jedan uređaj. Ako nastavite, but "
+"uÄitavaÄ možda neće biti ispravno podeÅ¡en, akada se ovaj raÄunar sledeći put "
+"upali, koristiće se šta god da je prethodno bilo u but sektoru. Ako se tamo "
+"nalazi ranijaverzija GRUB 2, možda će doći do problema sa uÄitavanjem modula "
+"ili Äitanjem trenutne datoteke postavki."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Ako već imate neki drugi but uÄitavaÄ i želite ga zadržati, ili ako je ovo "
+"neko posebno okruženje gde ne treba but uÄitavaÄ, možete nastaviti. U "
+"suprotnom, morali biste negde instalirati GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Ukloniti GRUB 2 iz /boot/grub foldera?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Da li želite da sve GRUB 2 fajlove uklonite iz /boot/grub foldera?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Ovo će uÄiniti da sistem ne može da se pokrene osim ako drugi pokretaÄki "
+"program nije instaliran."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Završiti konverziju na GRUB 2 sada?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ovaj sistem joÅ¡ uvek ima inastalirane fajlove sa GRUB Legacy pokretaÄkog "
+"programa, ali sada sadrži GRUB 2 pokretaÄke podatke instalirane na sledećim "
+"diskovima:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Izgleda da GRUB Legacy nije više u upotrebi, umesto toga trebali biste "
+"nadograditi na GRUB 2 na diskovima, a takođe samo prebacivanje na GRUB 2 "
+"ukljuÄuje i brisanje starih GRUB Legacy datoteka. Ako niste nadogradili na "
+"GRUB 2, onda bi moglo doći do nekompatibilnosti sa novijim verzijama paketa, "
+"što bi dalje moglo dovesti i do nemogućnosti ispravnog pokretanja sistema."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Trebali biste da zabrÅ¡ite konverziju na GRUB 2, osim ako su ovi pokretaÄki "
+"podaci kreirani od GRUB 2 instalacije na nekom drugom operativnom sistemu."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux komandna linija:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ova linija namenjena za Linux kernel je iz /etc/default/grub (GRUB 2) ili iz "
+"„kopt“ parametra datoteke menu.lst (GRUB Legacy). Proverite da li je linija "
+"ispravna i ako treba popravite je. Linija inaÄe, može ostati i prazna. "
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux podrazumevajuća komanda linija:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Sledeći string će biti upotrebljen kao Linux parametri za podreazumevano "
+"pokretanje, ali ne i za mod za popravku."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD komandna linija:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Ova linija namenjena kFreeBSD kernelu je iz /etc/default/grub (GRUB 2) ili "
+"iz „kopt“ parametra datoteke menu.lst (GRUB Legacy). Proverite da li je "
+"linija ispravna i ako treba popravite je. Linija inaÄe, može ostati i prazna."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD podrazumevajuća komandna linija:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Sledeći string će biti upotrebljen kao kFreeBSD parametri za podreazumevano "
+"pokretanje, ali ne i za mod za popravku."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map je ponovo generisan"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Datoteka /boot/grub/device.map je ponovo napisana kako bi se u njoj "
+#~ "koristili stabilni nazivi za ureÄ‘aje. U većini sluÄajeva, ovim bi se "
+#~ "trebalo smanjiti potreba za njenim menjanjem, s tim da stavke u GRUB "
+#~ "meniju više ne budu podložne takvoj promeni."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Ipak, kako postoji više od jednog diska na ovom sistemu, moguće je da "
+#~ "zavisite od stare mape uređaja. Proverite imate li neke od stavki u GRUB "
+#~ "meniju koje zavise od starog sistema oznaÄavanja (hdN) i ažurirajte ih "
+#~ "ukoliko je potrebno."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Ako ne razumete ovu poruku, ili ako ne postoje prilagođeni unosi za "
+#~ "pokretaÄki meni, možete da ignoriÅ¡ete ovu poruku."
diff --git a/debian/po/sv.po b/debian/po/sv.po
new file mode 100644
index 0000000..e158899
--- /dev/null
+++ b/debian/po/sv.po
@@ -0,0 +1,494 @@
+# translation of grub2 debconf messages to Swedish
+# Swedish translation for grub2.
+# Copyright (C) 2007, 2008, 2009, 2010, 2014, 2017 Free Software Foundation, Inc.
+# This file is distributed under the same license as the grub2 package.
+#
+# Daniel Nylander <po@danielnylander.se>, 2007.
+# Martin Ã…gren <martin.agren@gmail.com>, 2008, 2009.
+# Martin Bagge <brother@bsnet.se>, 2010, 2014, 2017
+# Luna Jernberg <droidbittin@gmail.com>, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2_sv\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-23 20:27+0000\n"
+"PO-Revision-Date: 2023-04-25 15:27+0200\n"
+"Last-Translator: Luna Jernberg <droidbittin@gmail.com>\n"
+"Language-Team: Swedish <debian-l10n-swedish@lists.debian.org>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Kedjeladda från menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB:s uppgraderingsskript har upptäckt en gammal GRUB-inställning i /boot/"
+"grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Om du vill ersätta den gamla versionen av GRUB i systemet, rekommenderas "
+"att /boot/grub/menu.lst justeras till att kedjeladda GRUB 2 från din "
+"existerande, gamla GRUB-inställning. Detta steg kan utföras automatiskt nu."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Det rekommenderas att GRUB 2 kedjeladdas från menu.lst så att det kan "
+"säkerställas att den nya GRUB 2-inställningen fungerar innan den installeras "
+"direkt till huvudstartsektorn (MBR)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Oberoende av ditt beslut kan den gamla MBR-avbildningen ersättas med GRUB 2 "
+"vid ett senare tillfälle genom att följande kommando utförs som root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB installationsenheter:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Paketet grub-pc uppdateras. Denna meny ger dig möjlighet att välja vilka, om "
+"några, enheter som grub-install ska köras automatiskt för."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Att köra grub-install automatiskt är rekommenderat i de flesta situationer "
+"för att förhindra den installerade GRUB-huvudavbildningen från att hamna i "
+"ett förhållande där GRUB-moduler eller grub.cfg inte är i korrekt läge."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Om du är osäker på vilken disk som är uppstartsdisken enligt BIOS så är det "
+"vanligen en god idé att installera GRUB på alla."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"OBS: det är möjligt att installera GRUB i partitionens uppstartsområde "
+"också, några av dessa visas nedan. Dock innebär installation där att GRUB "
+"tvingas använda en blockeringslista, som gör funktionen mindre pålitlig, och "
+"detta rekommenderas inte."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Uppstartshanteraren GRUB var tidigare installerad på en disk som inte längre "
+"finns tillgänglig eller vars unika identifikation har ändrats av någon "
+"anledning. Det är viktigt att säkerställa att den installerade GRUB-"
+"huvudavbildningen är korrekt i förhållande till GRUB-moduler och grub.cfg. "
+"Kontrollera återigen att GRUB är tillgänglig på rätt uppstartsenhet."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Skriva GRUB till uppstartsenhet misslyckades - fortsätta?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB kunde inte installeras på följande enheter:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Vill du fortsätta i alla fall? Det kan innebära att systemet inte kan starta "
+"korrekt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Skrivningen av GRUB till uppstartsenheten misslyckades - försöka igen?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Du kan kanske installera GRUB till någon annan enhet, du bör dock "
+"kontrollera att systemet kommer att starta från den enheten. I annat fall "
+"kommer uppgraderingen från äldre GRUB-version att avbrytas."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Fortsätt utan att installera GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Du valde att inte installera GRUB på några enheter. Om du fortsätter kommer "
+"uppstartshanteraren kanske inte att få korrekta inställningar och när ditt "
+"system startar nästa gång kommer det att använda vad som tidigare fanns i "
+"boot-sektorn. Om en tidigare version av GRUB 2 används i boot-sektorn finns "
+"risk att vissa moduler inte kan laddas och hantera de aktuella "
+"inställningsfilerna."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Om du redan kör en annan uppstartshanterare och vill fortsätta med det eller "
+"om detta är en specialmiljö som inte behöver en uppstartshanterare ska du "
+"fortsätta i alla fall. I annat fall ska du installera GRUB någonstans."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Radera GRUB 2 från /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Vill du att alla GRUB 2-filer ska raderas från /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Detta innebär att systemet inte kan starta om ingen annan uppstartshanterare "
+"är installerad."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Avsluta konverteringen till GRUB 2 nu?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Detta system har fortfarande filer från den äldre GRUB-uppstartshanteraren "
+"installerade men nu finns det dessutom GRUB 2 uppstartsinformation på "
+"följande enheter:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Det är troligt att den äldre GRUB-versionen inte längre används och du bör "
+"istället uppgradera till GRUB 2-avbildningar på dessa enheter och avsluta "
+"konverteringen till GRUB 2 genom att ta bort äldre GRUB-filer. Om du inte "
+"vill uppgradera dessa GRUB 2-avbildningar kan de bli oanvändbara tillsammans "
+"med det nya paketet och systemet sluta att fungera korrekt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Det generella rådet är att avsluta konverteringen till GRUB 2 om dessa filer "
+"inte skapats av en GRUB 2-installation på ett annat operativsystem."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Kommandorad för Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Följande Linux-kommandorad hämtades från /etc/default/grub eller \"kopt\"-"
+"parametern i gamla GRUB:s menu.lst. Verifiera att den är korrekt och "
+"modifiera den om nödvändigt. Kommandoraden kan vara tom."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Standardkommandorad för Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Följande sträng kommer användas som Linux-parametrar för standardmenyvalet "
+"men inte för återhämtningsläge (eng. recovery)."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Forcera installation till flyttbar EFI-media?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Vissa EFI-baserade system beter sig felaktigt och kan inte hantera nyare "
+"uppstartshanterare korrekt. Om Grub-installationen forceras in i en flyttbar "
+"EFI-enhet så ska detta säkerställa att systemet kommer att starta Debian "
+"korrekt oavsett sådana problem. Å andra sidan kan detta innebära att andra "
+"operativsystem inte kan startas eftersom de är beroende av den sökvägen. Om "
+"detta är fallet behöver du säkerställa att Grub ställts in komplett för att "
+"kunna starta andra operativsystem korrekt."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Uppdatera NVRAM-variabler för att automatiskt starta Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"Grub kan ställa in systemets NVRAM-variabler så att det kan starta Debian "
+"automatiskt. Det kan tänkas att du inte vill ha detta läge aktivt och "
+"undvika att ändra inställningarna för systemstart. Exempelvis om dina NVRAM-"
+"variabler är satta till att systemet kontaktar en PXE-server vid varje start."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"Köra os-prober automatiskt för att upptäcka och starta upp andra "
+"operativsystem?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB kan använda os-prober verktyget för att försöka upptäcka andra "
+"operativsystem på din dator och lägga till dem till sin lista över "
+"startalternativ automatiskt."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Om din dator har flera operativsystem installerade är det förmodligen det du "
+"vill ha. Men om din dator är en värd för gästoperativsystem installerade via "
+"LVM eller rådiskenheter, kan körning av os-prober orsaka skada på dessa "
+"gästoperativsystem eftersom det monterar filsystem för att leta reda på "
+"saker."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD kommandorad:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Följande kFreeBSD-kommandorad hämtades från /etc/default/grub eller \"kopt\"-"
+"parametern i gamla GRUB:s menu.lst. Verifiera att den är korrekt och "
+"modifiera den om nödvändigt. Kommandoraden kan vara tom."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD standardkommandorad"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Följande sträng kommer användas som Linux-parametrar för standardmenyvalet "
+"men inte för återhämtningsläge (eng. recovery)."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map har skapats på nytt"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Filen /boot/grub/device.map har skrivits om för att använda stabila "
+#~ "enhetsnamn. I de allra flesta fall kommer detta innebära att "
+#~ "anledningarna att byta namn i framtiden minskar drastiskt. Posterna i "
+#~ "uppstartsmenyn som skapas av GRUB ska inte påverkas."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Dock, eftersom mer än en disk finns i systemet kan det innebära att "
+#~ "systemet är beroende av den gamla enhetskopplingen. Kontrollera om det "
+#~ "finns manuellt införda poster i uppstartsmenyn som är beroende av GRUB:s "
+#~ "enhetsnumrering (hdN) och uppdatera dessa om nödvändigt."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Om du inte förstår detta meddelande eller om du inte har några "
+#~ "alternativa menyposter kan du ignorera detta meddelande."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "När GRUB 2 ska laddas direkt från huvudstartsektorn, kan detta "
+#~ "åstadkommas genom att (som root) köra följande kommando:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Installationen av GRUB misslyckades. Fortsätta?"
diff --git a/debian/po/ta.po b/debian/po/ta.po
new file mode 100644
index 0000000..c525df6
--- /dev/null
+++ b/debian/po/ta.po
@@ -0,0 +1,456 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Dr,T,Vasudevan <agnihot3@gmail.com>, 2010.
+# Dr.T.Vasudevan <agnihot3@gmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: ta\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2012-02-16 10:15+0530\n"
+"Last-Translator: Dr.T.Vasudevan <agnihot3@gmail.com>\n"
+"Language-Team: Tamil <Ubuntu-l10n-tam@lists.ubuntu.com>\n"
+"Language: ta\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.1\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst இலிரà¯à®¨à¯à®¤à¯ சஙà¯à®•à®¿à®²à®¿à®à®±à¯à®±à®®à¯ செயà¯à®¯à®²à®¾à®®à®¾?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "/boot/grub இல௠பாரமà¯à®ªà®°à®¿à®¯ கà¯à®°à®ªà¯ அமைபà¯à®ªà¯ உளà¯à®³à®¤à®¾à®• கà¯à®°à®ªà¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ நிரல௠கணà¯à®Ÿà®¤à¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+" பாரமà¯à®ªà®°à®¿à®¯ கà¯à®°à®ªà¯ அமைபà¯à®ªà¯ˆ உஙà¯à®•à®³à¯ கணினியிலிரà¯à®¨à¯à®¤à¯ மாறà¯à®± இபà¯à®ªà¯‹à®¤à¯à®³à¯à®³ பாரமà¯à®ªà®°à®¿à®¯ கà¯à®°à®ªà¯ அமைபà¯à®ªà®¿à®©à¯ /"
+"boot/grub/menu.lst ஠கà¯à®°à®ªà¯2 தà¯à®µà®•à¯à®•à®¿ பிமà¯à®ªà®¤à¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ à®à®±à¯à®±à®®à¯ செயà¯à®¯ சரிகà¯à®•à®Ÿà¯à®Ÿ "
+"பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. இநà¯à®¤ படி இபà¯à®ªà¯‹à®¤à¯ தானியஙà¯à®•à®¿à®¯à®¾à®• செயà¯à®¯à®ªà¯à®ªà®Ÿ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+" menu.lst இலிரà¯à®¨à¯à®¤à¯ கà¯à®°à®ªà¯2 ஠சஙà¯à®•à®¿à®²à®¿ à®à®±à¯à®±à®®à¯ செயà¯à®¯ இபà¯à®ªà¯‹à®¤à¯ ஒபà¯à®ªà¯à®•à¯à®•à¯Šà®³à¯à®³ பரிநà¯à®¤à¯à®°à¯ˆ "
+"செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. மேலà¯à®®à¯ உஙà¯à®•à®³à¯ பà¯à®¤à®¿à®¯ கà¯à®°à®ªà¯2 அமைபà¯à®ªà¯ செயல௠சரியாக உளà¯à®³à®¤à®¾ எனà¯à®ªà®¤à¯ˆà®¯à¯à®®à¯ சரி "
+"பாரà¯à®¤à¯à®¤ பின௠எமà¯à®ªà®¿à®†à®°à¯ (மாஸà¯à®Ÿà®°à¯ பூட௠ரெகாரà¯à®Ÿà¯) இல௠நிறà¯à®µà®¿à®•à¯à®•à¯Šà®³à¯à®³à®²à®¾à®®à¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"நீஙà¯à®•à®³à¯ எனà¯à®© à®®à¯à®Ÿà®¿à®µà¯ செயà¯à®¤à®¾à®²à¯à®®à¯ பழைய எமà¯à®ªà®¿à®†à®°à¯ பிமà¯à®ªà®¤à¯à®¤à¯ˆ, பினà¯à®©à®¾à®²à¯ பின௠வரà¯à®®à¯ கடà¯à®Ÿà®³à¯ˆà®¯à¯ˆ ரூட௠ஆக "
+"இடà¯à®Ÿà¯ கà¯à®°à®ªà¯ 2 ஆல௠மாறà¯à®±à®¿à®•à¯à®•à¯Šà®³à¯à®³à®²à®¾à®®à¯."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "கà¯à®°à®ªà¯ நிறà¯à®µà®²à¯ சாதனஙà¯à®•à®³à¯: "
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"கà¯à®°à®ªà¯-பிசி பொதி மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. இநà¯à®¤ மென௠கà¯à®°à®ªà¯ நிறà¯à®µà®²à¯ தானியஙà¯à®•à®¿à®¯à®¾à®• இயஙà¯à®• "
+"சாதனஙà¯à®•à®³à¯ à®à®¤à¯à®®à¯ இரà¯à®¨à¯à®¤à®¾à®²à¯ அதை தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®• இத௠அனà¯à®®à®¤à®¿à®•à¯à®•à®¿à®±à®¤à¯."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"பெரà¯à®®à¯à®ªà®¾à®²à®¾à®© நேரஙà¯à®•à®³à®¿à®²à¯ தானியஙà¯à®•à®¿à®¯à®¾à®• கà¯à®°à®ªà¯ நிறà¯à®µà®¿à®¯à¯ˆ இயகà¯à®•à¯à®µà®¤à¯ பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. "
+"இத௠கà¯à®°à®ªà¯ கர௠பிமà¯à®ªà®®à¯ கà¯à®°à®ªà¯ மாடà¯à®¯à¯‚லà¯à®•à®³à¯ அலà¯à®²à®¤à¯ grub.cfg இலிரà¯à®¨à¯à®¤à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®µà¯ இலà¯à®²à®¾à®®à®²à¯ போவதை "
+"தடà¯à®•à¯à®•à®¿à®±à®¤à¯."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"நீஙà¯à®•à®³à¯ எநà¯à®¤ தொகà¯à®¤à®¿ பூட௠தொகà¯à®¤à®¿à®¯à®¾à®• உஙà¯à®•à®³à¯ பயாஸால௠அமரà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯ என தெரியவிலà¯à®²à¯ˆà®¯à®¾à®©à®¾à®²à¯ "
+"எலà¯à®²à®¾à®µà®±à¯à®±à®¿à®²à¯à®®à¯ கà¯à®°à®ªà¯ ஠நிறà¯à®µà¯à®µà®¤à¯ நலà¯à®² தேரà¯à®µà®¾à®•à¯à®®à¯."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"கà¯à®±à®¿à®ªà¯à®ªà¯: கà¯à®°à®ªà¯ ஠பகிரà¯à®µà¯à®•à®³à®¿à®©à¯ பூட௠பதிவில௠நிறà¯à®µà®µà¯à®®à¯ இயலà¯à®®à¯. சில பொரà¯à®¤à¯à®¤à®®à®¾à®© பகிரà¯à®µà¯à®•à®³à¯ "
+"இஙà¯à®•à¯ தரபà¯à®ªà®Ÿà¯à®•à®¿à®©à¯à®±à®©. ஆனால௠இத௠கà¯à®°à®ªà¯à®ªà¯ˆ தடà¯à®ªà¯à®ªà¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®¯à®²à¯ பாஙà¯à®•à¯ˆ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ "
+"வலியà¯à®±à¯à®¤à¯à®¤à¯à®•à®¿à®±à®¤à¯. அதனால௠இத௠கொஞà¯à®šà®®à¯ நமà¯à®ªà®•à®¤à¯à®¤à®©à¯à®®à¯ˆ கà¯à®±à¯ˆà®µà®¾à®©à®¤à¯. ஆகவே இதை "
+"பரிநà¯à®¤à¯à®°à¯ˆà®ªà¯à®ªà®¤à®¿à®²à¯à®²à¯ˆ."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"கà¯à®°à®ªà¯ பூட௠à®à®±à¯à®±à®¿ à®®à¯à®©à¯à®ªà¯ ஒர௠வடà¯à®Ÿà®¿à®²à¯ பதியபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯; அநà¯à®¤ வடà¯à®Ÿà¯ இபà¯à®ªà¯‹à®¤à¯ இலà¯à®²à¯ˆ அலà¯à®²à®¤à¯ à®à®©à¯‹ அதன௠"
+"பிரதà¯à®¯à¯‡à®• அடையாளமà¯à®•à®¾à®£à®¿ மாறிவிடà¯à®Ÿà®¤à¯. கà¯à®°à®ªà¯ கர௠பிமà¯à®ªà®®à¯ கà¯à®°à®ªà¯ மாடà¯à®¯à¯‚லà¯à®•à®³à¯ அலà¯à®²à®¤à¯ grub.cfg "
+"உடன௠ஒதà¯à®¤à®¿à®šà¯ˆà®µà¯ இரà¯à®ªà¯à®ªà®¤à¯ அவசியமà¯. பொரà¯à®¤à¯à®¤à®®à®¾à®© பூட௠சாதனஙà¯à®•à®³à®¿à®²à¯ கà¯à®°à®ªà¯ எழà¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯ என "
+"மீணà¯à®Ÿà¯à®®à¯ சோதிதà¯à®¤à¯ உறà¯à®¤à®¿ செயà¯à®¤à¯ கொளà¯à®•."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} எமà¯à®ªà®¿ (MB); ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} எமà¯à®ªà®¿(MB); ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "பூட௠சாதனதà¯à®¤à¯à®•à¯à®•à¯ கà¯à®°à®ªà¯ ஠எழà¯à®¤à¯à®µà®¤à¯ தோவியடைநà¯à®¤à®¤à¯ - தொடரலாமா?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "பின௠வரà¯à®®à¯ சாதனஙà¯à®•à®³à®¿à®²à¯ கà¯à®°à®ªà¯ நிறà¯à®µà¯à®¤à®²à¯ தோலà¯à®µà®¿à®¯à®Ÿà¯ˆà®¨à¯à®¤à®¤à¯:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"எபà¯à®ªà®Ÿà®¿à®¯à¯à®®à¯ தொடர வேணà¯à®Ÿà¯à®®à®¾? தொடரà¯à®¨à¯à®¤à®¾à®²à¯ உஙà¯à®•à®³à¯ கணினி சரியாக தà¯à®µà®™à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®®à®²à¯ போகலாமà¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "பூட௠சாதனதà¯à®¤à¯à®•à¯à®•à¯ கà¯à®°à®ªà¯ ஠நிறà¯à®µà¯à®¤à®²à¯ தோலà¯à®µà®¿à®¯à®Ÿà¯ˆà®¨à¯à®¤à®¤à¯. மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®²à®¾à®®à®¾?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"நீஙà¯à®•à®³à¯ வேற௠சாதனதà¯à®¤à®¿à®²à¯ கà¯à®°à®ªà¯ ஠நிறà¯à®µ à®®à¯à®Ÿà®¿à®¯à®²à®¾à®®à¯. ஆனால௠உஙà¯à®•à®³à¯ கணினி அநà¯à®¤ சாதனதà¯à®¤à®¿à®²à¯ "
+"இரà¯à®¨à¯à®¤à¯ பூட௠ஆகà¯à®®à¯ எனà¯à®ªà®¤à¯ˆ உறà¯à®¤à®¿ செயà¯à®¤à¯ கொளà¯à®³ வேணà¯à®Ÿà¯à®®à¯. இலà¯à®²à¯ˆà®¯à¯†à®©à®¿à®²à¯ பாரமà¯à®ªà®°à®¿à®¯ கà¯à®°à®ªà¯ "
+"இலிரà¯à®¨à¯à®¤à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®¤à®²à¯ ரதà¯à®¤à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®®à¯. "
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "கà¯à®°à®ªà¯ ஠நிறà¯à®µà®¾à®®à®²à¯ தொடரலாமா?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"நீஙà¯à®•à®³à¯ எநà¯à®¤ சாதனதà¯à®¤à®¿à®²à¯à®®à¯ கà¯à®°à®ªà¯ ஠நிறà¯à®µà®¾à®®à®²à¯ இரà¯à®•à¯à®• தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤à¯ உளà¯à®³à¯€à®°à¯à®•à®³à¯. நீஙà¯à®•à®³à¯ தொடரà¯à®¨à¯à®¤à®¾à®²à¯ "
+"பூட௠à®à®±à¯à®±à®¿ சரியாக வடிவமைகà¯à®•à®ªà¯à®ªà®Ÿà®¾à®®à®²à¯ போகலாமà¯. அதனால௠கணினி மீணà¯à®Ÿà¯à®®à¯ தà¯à®µà®™à¯à®•à¯à®®à¯à®ªà¯‹à®¤à¯ à®®à¯à®©à¯à®ªà¯ "
+"பூட௠தொகà¯à®¤à®¿à®¯à®¿à®²à¯ எனà¯à®© இரà¯à®¨à¯à®¤à®¤à¯‹ அதையே பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯. à®…à®™à¯à®•à¯‡ கà¯à®°à®ªà¯ 2 இன௠மà¯à®¨à¯à®¤à¯ˆà®¯ பதிபà¯à®ªà¯ "
+"இரà¯à®ªà¯à®ªà®¿à®©à¯ மாடà¯à®¯à¯‚லà¯à®•à®³à¯ˆ à®à®±à¯à®±à¯à®¤à®²à¯à®®à¯ நடபà¯à®ªà¯ வடிவமைபà¯à®ªà¯ கோபà¯à®ªà¯ˆ கையாளà¯à®µà®¤à¯à®®à¯ இயலாமல௠போகலாமà¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"நீஙà¯à®•à®³à¯ à®à®±à¯à®•à¯†à®©à¯†à®µà¯‡ வேற௠தà¯à®µà®•à¯à®• à®à®±à¯à®±à®¿à®¯à¯ˆ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®•à¯à®•à¯Šà®£à¯à®Ÿà¯ இரà¯à®¨à¯à®¤à¯ அதையே தொடர நினைதà¯à®¤à®¾à®²à¯, "
+"அலà¯à®²à®¤à¯ இத௠ஒர௠விசேஷ சூழலாக இரà¯à®¨à¯à®¤à¯ உஙà¯à®•à®³à¯à®•à¯à®•à¯ தà¯à®µà®•à¯à®•à®¿ தேவையிலà¯à®²à¯à®²à®¾à®®à®²à¯ இரà¯à®¨à¯à®¤à®¾à®²à¯, "
+"எபà¯à®ªà®Ÿà®¿à®¯à¯à®®à¯ நீஙà¯à®•à®³à¯ தொடர வேணà¯à®Ÿà¯à®®à¯. அலà¯à®²à®¤à¯ கà¯à®°à®ªà¯ ஠வேற௠இடதà¯à®¤à®¿à®²à¯ நிறà¯à®µ வேணà¯à®Ÿà¯à®®à¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "கà¯à®°à®ªà¯ 2 à® /boot/grub இலிரà¯à®¨à¯à®¤à¯ நீகà¯à®•à®µà®¾?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "எலà¯à®²à®¾ கà¯à®°à®ªà¯ 2 கோபà¯à®ªà¯à®•à¯à®•à®³à¯ˆà®¯à¯à®®à¯ /boot/grub இலிரà¯à®¨à¯à®¤à¯ நீகà¯à®• விரà¯à®ªà¯à®ªà®®à®¾?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"இத௠வேற௠ஒர௠தà¯à®µà®•à¯à®•à®¿à®¯à¯ˆ நிறà¯à®µà®¿ இரà¯à®¨à¯à®¤à®¾à®²à¯ ஒழிய கணினியை தà¯à®µà®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®®à®²à¯ ஆகà¯à®•à¯à®®à¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "கà¯à®°à®ªà¯ 2 கà¯à®•à¯ மாறà¯à®±à®¤à¯à®¤à¯ˆ இபà¯à®ªà¯‹à®¤à¯ à®®à¯à®Ÿà®¿à®•à¯à®•à®²à®¾à®®à®¾?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"இநà¯à®¤ கணினியில௠இனà¯à®©à¯à®®à¯ கà¯à®°à®ªà¯ பாரமà¯à®ªà®°à®¿à®¯ தà¯à®µà®•à¯à®•à®¿ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. ஆனால௠இபà¯à®ªà¯‹à®¤à¯ கà¯à®°à®ªà¯ 2 பூட௠"
+"பதிவà¯à®•à®³à¯à®®à¯ பின௠வரà¯à®®à¯ வடà¯à®Ÿà¯à®•à®³à®¿à®²à¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"பாரமà¯à®ªà®°à®¿à®¯ கà¯à®°à®ªà¯ இபà¯à®ªà¯‹à®¤à¯ பà¯à®´à®•à¯à®•à®¤à¯à®¤à®¿à®²à¯ இலà¯à®²à¯ˆ எனà¯à®±à¯ தெரிகிறதà¯. நீஙà¯à®•à®³à¯ இநà¯à®¤ வடà¯à®Ÿà¯à®•à®³à®¿à®²à¯ உளà¯à®³ கà¯à®°à®ªà¯ "
+"2 பிமà¯à®ªà®™à¯à®•à®³à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤ வேணà¯à®Ÿà¯à®®à¯. பழைய பாரà¯à®®à®ªà®°à®¿à®¯ கà¯à®°à®ªà¯ கோபà¯à®ªà¯à®•à¯à®•à®³à¯ˆ நீகà¯à®•à®¿ மாறà¯à®±à®¤à¯à®¤à¯ˆ இறà¯à®¤à®¿ "
+"செயà¯à®¯ வேணà¯à®Ÿà¯à®®à¯. நீஙà¯à®•à®³à¯ இநà¯à®¤ பிமà¯à®ªà®™à¯à®•à®³à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¾à®µà®¿à®Ÿà¯à®Ÿà®¾à®²à¯ பà¯à®¤à®¿à®¯ பொதிகளà¯à®Ÿà®©à¯ அவை "
+"பொரà¯à®¤à¯à®¤à®®à®¿à®²à¯à®²à®¾à®®à®²à¯ போய௠உஙà¯à®•à®³à¯ கணினி சரியாக தà¯à®µà®™à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®®à®²à¯ போகலாமà¯."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"இநà¯à®¤ பூட௠பதிவà¯à®•à®³à¯ வேற௠ஒர௠இயஙà¯à®•à¯ தளதà¯à®¤à¯ˆ நிறà¯à®µà¯à®®à¯ போத௠கà¯à®°à®ªà¯ 2 ஆல௠"
+"உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®¨à¯à®¤à®¾à®²à¯ ஒழிய நீஙà¯à®•à®³à¯ பொதà¯à®µà®¾à®• கà¯à®°à®ªà¯ 2 மாறà¯à®±à®¤à¯à®¤à¯ˆ à®®à¯à®Ÿà®¿à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "லீனகà¯à®¸à¯ கடà¯à®Ÿà®³à¯ˆ வரி:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"பின௠வரà¯à®®à¯ லீனகà¯à®¸à¯ கடà¯à®Ÿà®³à¯ˆ வரி /etc/default/grub இலிரà¯à®¨à¯à®¤à¯ அலà¯à®²à®¤à¯ கà¯à®°à®ªà¯ இன௠பாரமà¯à®ªà®°à®¿à®¯ "
+"menu.lst இன௠`kopt' அளபà¯à®°à¯à®µà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ பெறபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. இத௠சரியா எனà¯à®±à¯ சோதிதà¯à®¤à¯ "
+"தேவையானால௠மறà¯à®±à®µà¯à®®à¯. இநà¯à®¤ கடà¯à®Ÿà®³à¯ˆ வரி காலியாக இரà¯à®•à¯à®• அனà¯à®®à®¤à®¿ உணà¯à®Ÿà¯."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "லீனகà¯à®¸à¯ à®®à¯à®©à¯à®©à®¿à®°à¯à®ªà¯à®ªà¯ கடà¯à®Ÿà®³à¯ˆ வரி:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"பின௠வரà¯à®®à¯ சரஙà¯à®•à®³à¯ à®®à¯à®©à¯à®©à®¿à®°à¯à®ªà¯à®ªà¯ மென௠உளà¯à®³à¯€à®Ÿà¯à®Ÿà¯à®•à¯à®•à¯ லீனகà¯à®¸à¯ அளபà¯à®°à¯à®•à¯à®•à®³à®¾à®• பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®®à¯; "
+"ஆனால௠மீடà¯à®Ÿà¯†à®Ÿà¯à®ªà¯à®ªà¯ பாஙà¯à®•à¯à®•à¯à®•à¯ அலà¯à®²"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "கேபà¯à®°à¯€à®ªà®¿à®Žà®¸à¯à®Ÿà®¿ கடà¯à®Ÿà®³à¯ˆ வரி:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"பின௠வரà¯à®®à¯ கேபà¯à®°à¯€à®ªà®¿à®Žà®¸à¯à®Ÿà®¿ கடà¯à®Ÿà®³à¯ˆ வரி /etc/default/grub இலிரà¯à®¨à¯à®¤à¯ அலà¯à®²à®¤à¯ கà¯à®°à®ªà¯ இன௠"
+"பாரமà¯à®ªà®°à®¿à®¯ menu.lst இன௠`kopt' அளபà¯à®°à¯à®µà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ பெறபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. இத௠சரியா எனà¯à®±à¯ "
+"சோதிதà¯à®¤à¯ தேவையானால௠மறà¯à®±à®µà¯à®®à¯. இநà¯à®¤ கடà¯à®Ÿà®³à¯ˆ வரி காலியாக இரà¯à®•à¯à®• அனà¯à®®à®¤à®¿ உணà¯à®Ÿà¯."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "கேபà¯à®°à¯€à®ªà®¿à®Žà®¸à¯à®Ÿà®¿ à®®à¯à®©à¯à®©à®¿à®°à¯à®ªà¯à®ªà¯ கடà¯à®Ÿà®³à¯ˆ வரி:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"பின௠வரà¯à®®à¯ சரஙà¯à®•à®³à¯ à®®à¯à®©à¯à®©à®¿à®°à¯à®ªà¯à®ªà¯ மென௠உளà¯à®³à¯€à®Ÿà¯à®Ÿà¯à®•à¯à®•à¯ கேபà¯à®°à¯€à®ªà®¿à®Žà®¸à¯à®Ÿà®¿ அளபà¯à®°à¯à®•à¯à®•à®³à®¾à®• "
+"பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®®à¯; ஆனால௠மீடà¯à®Ÿà¯†à®Ÿà¯à®ªà¯à®ªà¯ பாஙà¯à®•à¯à®•à¯à®•à¯ அலà¯à®²"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map மற௠உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ " /boot/grub/device.map கோபà¯à®ªà¯ நிலையான சாதனஙà¯à®•à®³à®¿à®©à¯ பெயரை பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à®¾à®±à¯ மீணà¯à®Ÿà¯à®®à¯ "
+#~ "உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. பெரà¯à®®à¯à®ªà®¾à®²à®¾à®© சமயஙà¯à®•à®³à®¿à®²à¯ இத௠எதிரà¯à®•à®¾à®²à®¤à¯à®¤à®¿à®²à¯ மாறà¯à®± வேனà¯à®Ÿà®¿à®¯ அவசியம௠"
+#~ "à®à®±à¯à®ªà®Ÿà®¾à®¤à¯. கà¯à®°à®ªà¯ ஆல௠உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯ பூட௠மென௠உளà¯à®³à¯€à®Ÿà¯à®•à®³à¯ பாதிகà¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤à¯."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "இரà¯à®ªà¯à®ªà®¿à®©à¯à®®à¯ கணினியில௠ஒனà¯à®±à¯à®•à¯à®•à¯ மேறà¯à®ªà®Ÿà¯à®Ÿ வடà¯à®Ÿà¯à®•à®³à¯ இரà¯à®ªà¯à®ªà®¤à®¾à®²à¯ கணினி பழைய சாதன "
+#~ "வரைபடதà¯à®¤à¯ˆ சாரà¯à®¨à¯à®¤à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®•à¯à®•à¯Šà®£à¯à®Ÿà¯ இரà¯à®•à¯à®• வாயà¯à®ªà¯à®ªà¯ உணà¯à®Ÿà¯. கà¯à®°à®ªà¯ இன௠(hdN) எணà¯à®£à®¿à®Ÿà®²à¯ˆ "
+#~ "சாரà¯à®¨à¯à®¤ தனிபà¯à®ªà®¯à®©à¯ பூட௠மென௠à®à®¤à¯à®®à¯ உளà¯à®³à®¤à®¾ என தயை செயà¯à®¤à¯ சோதிகà¯à®•à®µà¯à®®à¯; அபà¯à®ªà®Ÿà®¿ இரà¯à®ªà¯à®ªà®¿à®©à¯ "
+#~ "அவறà¯à®±à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "இநà¯à®¤ செயà¯à®¤à®¿ உஙà¯à®•à®³à¯à®•à¯à®•à¯à®ªà¯ பà¯à®°à®¿à®¯à®µà®¿à®²à¯à®²à¯ˆà®¯à®¾à®©à®¾à®²à¯, அலà¯à®²à®¤à¯ தனிபà¯à®ªà®¯à®©à¯ பூட௠மென௠உளà¯à®³à¯€à®Ÿà¯à®•à®³à¯ "
+#~ "இலà¯à®²à¯ˆà®¯à®¾à®©à®¾à®²à¯ இநà¯à®¤ செயà¯à®¤à®¿à®¯à¯ˆ உதாசீனம௠செயà¯à®¯à®²à®¾à®®à¯."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "எபà¯à®ªà®Ÿà®¿ இரà¯à®¨à¯à®¤à®¾à®²à¯à®®à¯à®¨à¯€à®™à¯à®•à®³à¯ கà¯à®°à®ªà¯2 ஠எமà¯à®ªà®¿à®†à®°à¯ இலிரà¯à®¨à¯à®¤à¯ நேரடியாக à®à®±à¯à®± விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯ எபà¯à®ªà¯‹à®¤à¯ "
+#~ "வேணà¯à®Ÿà¯à®®à®¾à®©à®¾à®²à¯à®®à¯ ரூட௠ஆக கீழ௠கணà¯à®Ÿ கடà¯à®Ÿà®³à¯ˆ மூலம௠அதை செயà¯à®¯à®²à®¾à®®à¯."
diff --git a/debian/po/templates.pot b/debian/po/templates.pot
new file mode 100644
index 0000000..59edb55
--- /dev/null
+++ b/debian/po/templates.pot
@@ -0,0 +1,364 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the grub2 package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr ""
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
diff --git a/debian/po/th.po b/debian/po/th.po
new file mode 100644
index 0000000..11fcb43
--- /dev/null
+++ b/debian/po/th.po
@@ -0,0 +1,447 @@
+# Thai translation of grub.
+# Copyright (C) 2010-2017 Software in the Public Interest, Inc.
+# This file is distributed under the same license as the grub package.
+# Theppitak Karoonboonyanan <thep@debian.org>, 2010-2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-20 14:46+0700\n"
+"Last-Translator: Theppitak Karoonboonyanan <thep@debian.org>\n"
+"Language-Team: Thai <thai-l10n@googlegroups.com>\n"
+"Language: th\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "จะโหลดà¹à¸šà¸šà¸¥à¸¹à¸à¹‚ซ่จาภmenu.lst หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "สคริปต์ปรับรุ่นของ GRUB ตรวจพบค่าตั้งของ GRUB รุ่นเà¸à¹ˆà¸²à¹ƒà¸™ /boot/grub"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"ในà¸à¸²à¸£à¹à¸—นที่ GRUB รุ่นเà¸à¹ˆà¸²à¹ƒà¸™à¸£à¸°à¸šà¸š ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¸›à¸£à¸±à¸š /boot/grub/menu.lst "
+"ให้โหลดอิมเมจสำหรับบูตของ GRUB 2 จาภGRUB รุ่นเà¸à¹ˆà¸²à¸—ี่มีอยู่ "
+"ขั้นตอนนี้สามารถทำà¹à¸šà¸šà¸­à¸±à¸•à¹‚นมัติได้ในตอนนี้"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¸„ุณตอบรับà¸à¸²à¸£à¹‚หลด GRUB 2 à¹à¸šà¸šà¸¥à¸¹à¸à¹‚ซ่จาภmenu.lst à¹à¸¥à¸°à¸—ดสอบว่าค่าตั้งของ GRUB 2 "
+"ใช้à¸à¸²à¸£à¹„ด้ à¸à¹ˆà¸­à¸™à¸—ี่จะเขียนลง MBR (Master Boot Record) จริง"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"ไม่ว่าคุณจะเลือà¸à¹à¸šà¸šà¹„หน คุณยังสามารถà¹à¸—นที่อิมเมจเà¸à¹ˆà¸²à¹ƒà¸™ MBR ด้วย GRUB 2 เองได้ในภายหลัง "
+"โดยใช้คำสั่งต่อไปนี้ในà¸à¸²à¸™à¸° root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "อุปà¸à¸£à¸“์ที่จะติดตั้ง GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"à¸à¸³à¸¥à¸±à¸‡à¸ˆà¸°à¸›à¸£à¸±à¸šà¸£à¸¸à¹ˆà¸™à¹à¸žà¸à¹€à¸à¸ˆ grub-pc ขึ้น เมนูนี้จะช่วยคุณเลือà¸à¸­à¸¸à¸›à¸à¸£à¸“์ที่คุณต้องà¸à¸²à¸£à¹ƒà¸«à¹‰à¹€à¸£à¸µà¸¢à¸ grub-"
+"install โดยอัตโนมัติเพื่อติดตั้ง GRUB ถ้ามีอุปà¸à¸£à¸“์ดังà¸à¸¥à¹ˆà¸²à¸§"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"โดยทั่วไปà¹à¸¥à¹‰à¸§ ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¹€à¸£à¸µà¸¢à¸ grub-install โดยอัตโนมัติ เพื่อป้องà¸à¸±à¸™à¹„ม่ให้อิมเมจà¹à¸à¸™à¸à¸¥à¸²à¸‡à¸‚อง "
+"GRUB ที่ติดตั้งมีข้อมูลไม่ตรงà¸à¸±à¸šà¸¡à¸­à¸”ูล GRUB ต่างๆ หรือไม่ตรงà¸à¸±à¸š grub.cfg"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ถ้าคุณไม่à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸² BIOS à¸à¸³à¸«à¸™à¸”ไดรว์ไหนไว้สำหรับบูต à¸à¹‡à¸¡à¸±à¸à¹€à¸›à¹‡à¸™à¸„วามคิดที่ดีที่จะติดตั้ง GRUB "
+"ลงในไดรว์ทุà¸à¹„ดรว์"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"หมายเหตุ: เป็นไปได้เหมือนà¸à¸±à¸™à¸—ี่จะติดตั้ง GRUB ลงในบูตเรคอร์ดของพาร์ทิชัน "
+"à¹à¸¥à¸°à¹„ด้à¹à¸ªà¸”งพาร์ทิชันที่เหมาะสมเป็นตัวเลือà¸à¹„ว้ในที่นี้à¹à¸¥à¹‰à¸§ อย่างไรà¸à¹‡à¸”ี à¸à¸²à¸£à¸—ำเช่นนั้นจะเป็นà¸à¸²à¸£à¸šà¸±à¸‡à¸„ับให้ "
+"GRUB ใช้à¸à¸¥à¹„à¸à¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­à¸šà¸¥à¹‡à¸­à¸„ ซึ่งความถูà¸à¸•à¹‰à¸­à¸‡à¹ƒà¸™à¸à¸²à¸£à¸—ำงานอาจลดลง จึงไม่ขอà¹à¸™à¸°à¸™à¸³"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"มีà¸à¸²à¸£à¸•à¸´à¸”ตั้งบูตโหลดเดอร์ GRUB à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰à¹ƒà¸™à¸”ิสà¸à¹Œà¸—ี่ขณะนี้ไม่มีà¹à¸¥à¹‰à¸§ หรือมี "
+"à¹à¸•à¹ˆà¸«à¸¡à¸²à¸¢à¹€à¸¥à¸‚ประจำดิสà¸à¹Œà¹„ด้เปลี่ยนไปด้วยสาเหตุบางอย่าง "
+"จึงจำเป็นต้องทำให้à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¸­à¸´à¸¡à¹€à¸¡à¸ˆà¹à¸à¸™à¸à¸¥à¸²à¸‡à¸‚อง GRUB ที่ติดตั้งไว้นั้นยังมีข้อมูลตรงà¸à¸±à¸šà¸¡à¸­à¸”ูล GRUB ต่างๆ "
+"à¹à¸¥à¸°à¸à¸±à¸š grub.cfg อยู่ à¸à¸£à¸¸à¸“าตรวจสอบอีà¸à¸„รั้งให้à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¸ˆà¸°à¹€à¸‚ียนข้อมูล GRUB ลงในอุปà¸à¸£à¸“์บูตที่เหมาะสม"
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "เขียน GRUB ลงในอุปà¸à¸£à¸“์บูตไม่สำเร็จ - ดำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„ปหรือไม่?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "ติดตั้ง GRUB ลงในอุปà¸à¸£à¸“์ต่อไปนี้ไม่สำเร็จ:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr "คุณยังคงต้องà¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„ปหรือไม่? ถ้าทำต่อ เครื่องของคุณอาจบูตไม่ขึ้นได้"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "เขียน GRUB ลงในอุปà¸à¸£à¸“์บูตไม่สำเร็จ - ลองใหม่หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"คุณอาจสามารถติดตั้ง GRUB ลงในอุปà¸à¸£à¸“์อื่นได้ "
+"โดยคุณควรทดสอบด้วยว่าเครื่องของคุณบูตจาà¸à¸­à¸¸à¸›à¸à¸£à¸“์นั้นขึ้นหรือไม่ ถ้าตอบปà¸à¸´à¹€à¸ªà¸˜ "
+"à¸à¹‡à¸ˆà¸°à¸¢à¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¸›à¸£à¸±à¸šà¸£à¸¸à¹ˆà¸™à¸ˆà¸²à¸ GRUB รุ่นเà¸à¹ˆà¸²"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "จะดำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„ปโดยไม่ติดตั้ง GRUB หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"คุณได้เลือà¸à¸—ี่จะไม่ติดตั้ง GRUB ลงในอุปà¸à¸£à¸“์ใดเลย ถ้าดำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„ป "
+"บูตโหลดเดอร์อาจอยู่ในสภาพที่ไม่ได้ตั้งค่าอย่างสมบูรณ์ à¹à¸¥à¸°à¹€à¸¡à¸·à¹ˆà¸­à¹€à¸›à¸´à¸”เครื่องครั้งต่อไป "
+"à¸à¹‡à¸ˆà¸°à¹ƒà¸Šà¹‰à¸ªà¸´à¹ˆà¸‡à¸—ี่อยู่ในบูตเซà¸à¹€à¸•à¸­à¸£à¹Œà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰ à¹à¸¥à¸°à¸–้าในบูตเซà¸à¹€à¸•à¸­à¸£à¹Œà¸¡à¸µ GRUB 2 รุ่นเà¸à¹ˆà¸²à¸­à¸¢à¸¹à¹ˆ "
+"à¸à¹‡à¸­à¸²à¸ˆà¸ˆà¸°à¹„ม่สามารถโหลดมอดูลหรือใช้à¹à¸Ÿà¹‰à¸¡à¸„่าตั้งปัจจุบันได้"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ถ้าคุณà¸à¸³à¸¥à¸±à¸‡à¹ƒà¸Šà¹‰à¸šà¸¹à¸•à¹‚หลดเดอร์ตัวอื่นอยู่ à¹à¸¥à¸°à¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸•à¹ˆà¸­à¹„ป "
+"หรือถ้าคุณอยู่ในสภาพà¹à¸§à¸”ล้อมที่ไม่ต้องใช้บูตโหลดเดอร์ คุณà¸à¹‡à¸­à¸²à¸ˆà¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„ปได้ มิฉะนั้น "
+"คุณà¸à¹‡à¸„วรติดตั้ง GRUB ลงในที่ใดที่หนึ่ง"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "จะลบ GRUB 2 ออà¸à¸ˆà¸²à¸ /boot/grub หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "คุณต้องà¸à¸²à¸£à¸ˆà¸°à¸¥à¸šà¹à¸Ÿà¹‰à¸¡à¸‚อง GRUB 2 ทั้งหมดออà¸à¸ˆà¸²à¸ /boot/grub หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "à¸à¸²à¸£à¸¥à¸šà¸™à¸µà¹‰à¸ˆà¸°à¸—ำให้ระบบไม่สามารถบูตได้ ยà¸à¹€à¸§à¹‰à¸™à¸¡à¸µà¸šà¸¹à¸•à¹‚หลดเดอร์ตัวอื่นติดตั้งอยู่"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "จะทำขั้นสุดท้ายของà¸à¸²à¸£à¹à¸›à¸¥à¸‡à¹€à¸›à¹‡à¸™ GRUB 2 หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"ระบบนี้มีà¹à¸Ÿà¹‰à¸¡à¸ˆà¸²à¸à¸šà¸¹à¸•à¹‚หลดเดอร์ GRUB รุ่นเà¸à¹ˆà¸²à¸•à¸´à¸”ตั้งอยู่ à¹à¸•à¹ˆà¸•à¸­à¸™à¸™à¸µà¹‰à¸¡à¸µà¸šà¸¹à¸•à¹€à¸£à¸„อร์ดของ GRUB 2 "
+"ติดตั้งไว้ในดิสà¸à¹Œà¸•à¹ˆà¸­à¹„ปนี้เช่นà¸à¸±à¸™:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"ดูเหมือน GRUB รุ่นเà¸à¹ˆà¸²à¸ˆà¸°à¹„ม่มีà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸­à¸µà¸à¸•à¹ˆà¸­à¹„ป à¹à¸¥à¸°à¸”ูเหมือนว่าคุณควรจะปรับรุ่นอิมเมจของ GRUB 2 "
+"ในดิสà¸à¹Œà¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¹à¸—น พร้อมทั้งจบขั้นตอนสุดท้ายของà¸à¸²à¸£à¹à¸›à¸¥à¸‡à¹„ปเป็น GRUB 2 โดยลบà¹à¸Ÿà¹‰à¸¡à¸‚อง GRUB "
+"รุ่นเà¸à¹ˆà¸²à¸—ิ้ง ถ้าคุณไม่ปรับรุ่นอิมเมจ GRUB 2 เหล่านี้ขึ้น อิมเมจà¸à¹‡à¸­à¸²à¸ˆà¹„ม่เข้าà¸à¸±à¸™à¸à¸±à¸šà¹à¸žà¸à¹€à¸à¸ˆà¸£à¸¸à¹ˆà¸™à¹ƒà¸«à¸¡à¹ˆà¹† "
+"à¹à¸¥à¸°à¸—ำให้ระบบของคุณบูตไม่ขึ้นได้"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"โดยทั่วไปà¹à¸¥à¹‰à¸§ คุณควรจะจบขั้นตอนสุดท้ายของà¸à¸²à¸£à¹à¸›à¸¥à¸‡à¹„ปเป็น GRUB 2 นี้ "
+"นอà¸à¹€à¸ªà¸µà¸¢à¸ˆà¸²à¸à¸§à¹ˆà¸²à¸šà¸¹à¸•à¹€à¸£à¸„อร์ดเหล่านี้จะถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¹‚ดย GRUB 2 ที่ติดตั้งในระบบปà¸à¸´à¸šà¸±à¸•à¸´à¸à¸²à¸£à¸­à¸·à¹ˆà¸™"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "พารามิเตอร์สำหรับบูตลินุà¸à¸‹à¹Œ:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"พารามิเตอร์สำหรับบูตลินุà¸à¸‹à¹Œà¸•à¹ˆà¸­à¹„ปนี้ดึงออà¸à¸¡à¸²à¸ˆà¸²à¸ /etc/default/grub หรือพารามิเตอร์ `kopt' ใน "
+"menu.lst ของ GRUB รุ่นเà¸à¹ˆà¸² à¸à¸£à¸¸à¸“าตรวจสอบว่าค่านี้ถูà¸à¸•à¹‰à¸­à¸‡à¸«à¸£à¸·à¸­à¹„ม่ à¹à¸¥à¸°à¸à¸£à¸¸à¸“าà¹à¸à¹‰à¹„ขถ้าจำเป็น "
+"พารามิเตอร์นี้สามารถปล่อยเป็นค่าว่างเปล่าได้"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "พารามิเตอร์สำหรับบูตลินุà¸à¸‹à¹Œà¹à¸šà¸šà¸›à¸à¸•à¸´:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr "พารามิเตอร์ต่อไปนี้จะใช้ในเมนูสำหรับบูตลินุà¸à¸‹à¹Œà¹à¸šà¸šà¸›à¸à¸•à¸´ à¹à¸•à¹ˆà¸ˆà¸°à¹„ม่ใช้à¸à¸±à¸šà¹‚หมดà¸à¸¹à¹‰à¸£à¸°à¸šà¸š"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "จะบังคับติดตั้งส่วนพิเศษเพิ่มเติมลงในพาธของสื่อถอดเสียบของ EFI หรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"ระบบที่อิง EFI บางระบบมีข้อบà¸à¸žà¸£à¹ˆà¸­à¸‡ à¹à¸¥à¸°à¹„ม่ได้จัดà¸à¸²à¸£à¸šà¸¹à¸•à¹‚หลดเดอร์ตัวใหม่ๆ อย่างถูà¸à¸•à¹‰à¸­à¸‡ "
+"ถ้าคุณบังคับติดตั้งส่วนพิเศษเพิ่มเติมของ GRUB ลงในพาธของสื่อถอดเสียบของ EFI "
+"à¸à¹‡à¸ˆà¸°à¸Šà¹ˆà¸§à¸¢à¹ƒà¸«à¹‰à¹à¸™à¹ˆà¹ƒà¸ˆà¹„ด้ว่าระบบนี้จะบูตเดเบียนได้อย่างถูà¸à¸•à¹‰à¸­à¸‡à¹à¸¡à¹‰à¸ˆà¸°à¸¡à¸µà¸›à¸±à¸à¸«à¸²à¸”ังà¸à¸¥à¹ˆà¸²à¸§ อย่างไรà¸à¹‡à¸•à¸²à¸¡ "
+"à¸à¸²à¸£à¸•à¸´à¸”ตั้งดังà¸à¸¥à¹ˆà¸²à¸§à¸­à¸²à¸ˆà¸—ำให้ไม่สามารถบูตระบบปà¸à¸´à¸šà¸±à¸•à¸´à¸à¸²à¸£à¸­à¸·à¹ˆà¸™à¸—ี่อิงอาศัยพาธนี้อยู่ด้วยได้ ซึ่งหาà¸à¹€à¸›à¹‡à¸™à¹€à¸Šà¹ˆà¸™à¸™à¸±à¹‰à¸™ "
+"คุณจะต้องตรวจสอบให้à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸²à¹„ด้ตั้งค่า GRUB "
+"ได้สำเร็จเพื่อให้สามารถบูตระบบปà¸à¸´à¸šà¸±à¸•à¸´à¸à¸²à¸£à¸­à¸·à¹ˆà¸™à¹„ด้อย่างถูà¸à¸•à¹‰à¸­à¸‡à¸”้วย"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "ปรับข้อมูลตัวà¹à¸›à¸£ NVRAM ให้บูตเข้าเดเบียนโดยอัตโนมัติหรือไม่?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB สามารถตั้งค่าตัวà¹à¸›à¸£ NVRAM "
+"ของà¹à¸žà¸¥à¸•à¸Ÿà¸­à¸£à¹Œà¸¡à¸‚องคุณเพื่อให้บูตเข้าสู่เดเบียนโดยอัตโนมัติเมื่อเปิดเครื่องได้ อย่างไรà¸à¹‡à¸”ี "
+"คุณอาจต้องà¸à¸²à¸£à¸›à¸´à¸”à¸à¸²à¸£à¸à¸£à¸°à¸—ำนี้à¹à¸¥à¸°à¹„ม่เปลี่ยนค่าตั้งà¸à¸²à¸£à¸šà¸¹à¸•à¸‚องคุณà¸à¹‡à¹„ด้ ตัวอย่างเช่น ถ้าตัวà¹à¸›à¸£ NVRAM "
+"ของคุณได้ถูà¸à¸•à¸±à¹‰à¸‡à¸„่าไว้ให้ระบบติดต่อไปยังเซิร์ฟเวอร์ PXE ทุà¸à¸„รั้งที่บูต คุณà¸à¹‡à¸­à¸²à¸ˆà¹€à¸¥à¸·à¸­à¸à¹„ม่ปรับตัวà¹à¸›à¸£ "
+"NVRAM นี้ à¹à¸¥à¸°à¸£à¸°à¸šà¸šà¸à¹‡à¸ˆà¸°à¸„งพฤติà¸à¸£à¸£à¸¡à¹€à¸”ิมนั้นไว้"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "พารามิเตอร์สำหรับบูต kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"พารามิเตอร์สำหรับบูต kFreeBSD ต่อไปนี้ดึงออà¸à¸¡à¸²à¸ˆà¸²à¸ /etc/default/grub หรือพารามิเตอร์ "
+"`kopt' ใน menu.lst ของ GRUB รุ่นเà¸à¹ˆà¸² à¸à¸£à¸¸à¸“าตรวจสอบว่าค่านี้ถูà¸à¸•à¹‰à¸­à¸‡à¸«à¸£à¸·à¸­à¹„ม่ "
+"à¹à¸¥à¸°à¸à¸£à¸¸à¸“าà¹à¸à¹‰à¹„ขถ้าจำเป็น พารามิเตอร์นี้สามารถปล่อยเป็นค่าว่างเปล่าได้"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "พารามิเตอร์สำหรับบูต kFreeBSD à¹à¸šà¸šà¸›à¸à¸•à¸´:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr "พารามิเตอร์ต่อไปนี้จะใช้ในเมนูสำหรับบูต kFreeBSD à¹à¸šà¸šà¸›à¸à¸•à¸´ à¹à¸•à¹ˆà¸ˆà¸°à¹„ม่ใช้à¸à¸±à¸šà¹‚หมดà¸à¸¹à¹‰à¸£à¸°à¸šà¸š"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "สร้าง /boot/grub/device.map ใหม่เรียบร้อยà¹à¸¥à¹‰à¸§"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "เขียนà¹à¸Ÿà¹‰à¸¡ /boot/grub/device.map ใหม่เพื่อใช้ชื่ออุปà¸à¸£à¸“์ที่ไม่เปลี่ยนà¹à¸›à¸¥à¸‡à¸‡à¹ˆà¸²à¸¢à¹€à¸£à¸µà¸¢à¸šà¸£à¹‰à¸­à¸¢à¹à¸¥à¹‰à¸§ "
+#~ "โดยส่วนใหà¸à¹ˆà¹à¸¥à¹‰à¸§ ชื่อà¹à¸šà¸šà¸™à¸µà¹‰à¸„วรจะช่วยลดความจำเป็นในà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸‚้อมูลอีà¸à¹ƒà¸™à¸­à¸™à¸²à¸„ตได้อย่างมาภ"
+#~ "à¹à¸¥à¸°à¸£à¸²à¸¢à¸à¸²à¸£à¹€à¸¡à¸™à¸¹à¸šà¸¹à¸•à¸•à¹ˆà¸²à¸‡à¹† ที่สร้างโดย GRUB à¸à¹‡à¹„ม่ควรได้รับผลà¸à¸£à¸°à¸—บ"
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "อย่างไรà¸à¹‡à¸”ี เนื่องจาà¸à¸¡à¸µà¸”ิสà¸à¹Œà¸«à¸¥à¸²à¸¢à¸”ิสà¸à¹Œà¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸°à¸šà¸š จึงเป็นไปได้ที่ระบบจะอาศัยผังอุปà¸à¸£à¸“์à¹à¸šà¸šà¹€à¸à¹ˆà¸² "
+#~ "à¸à¸£à¸¸à¸“าตรวจสอบว่ามีรายà¸à¸²à¸£à¹€à¸¡à¸™à¸¹à¸šà¸¹à¸•à¸—ี่คุณà¸à¸³à¸«à¸™à¸”เองที่อ้างถึงไดรว์ด้วยหมายเลขในรูป (hdN) ของ "
+#~ "GRUB อยู่หรือไม่ à¹à¸¥à¸°à¸à¸£à¸¸à¸“าปรับà¹à¸à¹‰à¸–้าจำเป็น"
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "ถ้าคุณไม่เข้าใจข้อความนี้ หรือถ้าไม่มีรายà¸à¸²à¸£à¹€à¸¡à¸™à¸¹à¸šà¸¹à¸•à¸—ี่คุณà¸à¸³à¸«à¸™à¸”เอง คุณà¸à¹‡à¸ªà¸²à¸¡à¸²à¸£à¸–ข้ามข้อความนี้ไปได้"
diff --git a/debian/po/tr.po b/debian/po/tr.po
new file mode 100644
index 0000000..146c9f3
--- /dev/null
+++ b/debian/po/tr.po
@@ -0,0 +1,456 @@
+# Turkish debconf translation of grub2
+# This file is distributed under the same license as the grub2 package.
+# Mert Dirik <mertdirik@gmail.com>, 2017.
+# Atila KOÇ <koc@artielektronik.com.tr>, 2012, 2014, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-04-21 15:46+0000\n"
+"PO-Revision-Date: 2023-04-30 15:12+0300\n"
+"Last-Translator: Atila KOÇ <koc@artielektronik.com.tr>\n"
+"Language-Team: Debian L10n Turkish <debian-l10n-turkish@lists.debian.org>\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Poedit 2.4.2\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst dosyasından zincirleme yükleme yapılsın mı?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB yükseltme betikleri /boot/grub altında bir GRUB Legacy kurulumu "
+"algıladı."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Sisteminizdeki GRUB'un Legacy sürümünü değiştirmek için, /boot/grub/menu.lst "
+"dosyasının bir GRUB 2 önyükleme görüntüsünü var olan GRUB Legacy "
+"kurulumundan yüklenmesine olanak tanıyacak şekilde değiştirilmesi önerilir. "
+"Bu adım şimdi otomatikman gerçekleştirilebilir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Ana Önyükleme Kaydı'na (MBR) yazılmadan önce GRUB 2'nin menu.lst'den "
+"zincirleme önyüklemesini kabul etmeniz ve GRUB 2 kurulumunun çalıştığını "
+"doğrulamanız önerilir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Seçiminiz ne olursa olsun, root kimliği ile aşağıdaki komutu çalıştırarak "
+"eski MBR görüntüsünü GRUB 2 ile değiştirebilirsiniz:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB kurulacak aygıtlar:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc paketi yükseltiliyor. Bu menü grub-install komutunun, eğer varsalar, "
+"hangi aygıtlar için otomatikman çalıştırılacağını seçmenize olanak tanır."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Sistemde kurulu olan GRUB çekirdek görüntüsünün GRUB modülleri veya grub.cfg "
+"ile uyumunun bozulmasını engellemek için, çoğu durumda grub-install "
+"komutunun otomatikman çalıştırılması önerilir."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Eğer hangi sürücünün BIOS tarafından önyükleme sürücüsü olarak "
+"belirlendiğinden emin değilseniz, GRUB'u tümüne kurmak yerinde olacaktır."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Not: GRUB'u disk bölümlerinin önyükleme kayıtlarına kurmak da mümkündür ve "
+"buna uygun bazı bölümler burada listelenmiştir. Öte yandan, bu seçim GRUB'u "
+"daha az güvenilir kılan engelleme listesi (blocklist) mekanizmasını "
+"kullanmaya zorlayacağından, önerilmemektedir."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB önyükleyici şu anda var olmayan ya da benzersiz tanımlayıcısı bir "
+"şekilde değişmiş olan bir diske kurulmuş. Kurulu olan GRUB çekirdek "
+"görüntüsünün GRUB modülleri ve grub.cfg ile uyum içinde olduğundan emin "
+"olmak önemlidir. Bu nedenle GRUB'un doğru önyükleme aygıtlarına yazılmış "
+"olduÄŸunu yeniden kontrol edin."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr ""
+"GRUB'u önyükleme aygıtına yazma işlemi başarısız oldu, devam edilsin mi?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Aşağıdaki aygıtlara GRUB kurulumu yapılamadı:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Yine de devam edilsin mi? Devam ederseniz bilgisayarınız düzgün "
+"baÅŸlayamayabilir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"GRUB'u önyükleme aygıtına yazma işlemi başarısız oldu, yeniden denensin mi?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"GRUB'u başka bir aygıta kurabilirsiniz, ancak sisteminizin o aygıttan "
+"başlatılabileceğinden emin olmalısınız. Tersi durumda, GRUB Legacy'den "
+"yükseltme iptal edilecektir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB kurulmadan devam edilsin mi?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"GRUB'u hiçbir aygıta kurmamayı seçtiniz. Devam ederseniz önyükleyici düzgün "
+"yapılandırılmayabilir ve bu bilgisayar bir sonraki açılışında önyükleme "
+"sektöründe daha önceden bulunan kayıtları kullanır. Eğer önyükleme "
+"sektöründe GRUB 2'nin eski bir sürümü varsa, güncel yapılandırma dosyasını "
+"kullanamayabilir veya modülleri yükleyemeyebilir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Şu anda farklı bir önyükleyici kullanıyorsanız ve kullanmayı sürdürecekseniz "
+"ya da bu sizin bir önyükleyiciye gerek duymadığınız özel bir ortam ise, bu "
+"şekilde devam edebilirsiniz. Tersi durumda GRUB'u bir yere kurmalısınız."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "GRUB 2, /boot/grub yolundan kaldırılsın mı?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr ""
+"/boot/grub yolundan bütün GRUB 2 dosyalarının kaldırılmasını istiyor musunuz?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Başka bir önyükleyici kurulu değilse yapılan bu işlem sistemi başlatılamaz "
+"kılacaktır."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "GRUB 2'ye dönüşüm tamamlansın mı?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Bu sistemde hala GRUB Legacy kurulumundan kalmış dosyalar var; ama şimdi bir "
+"de şu disklere yazılmış GRUB 2 önyükleme kayıtları var:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Göründüğü kadarı ile eski GRUB kurulumu artık kullanılmıyor, dolayısıyla bu "
+"disklerdeki GRUB Legacy dosyalarını kaldırıp GRUB 2 görüntülerine yükseltme "
+"yaparak dönüşümü tamamlamalısınız. Eğer bu GRUB 2 görüntülerini "
+"yükseltmezseniz, yeni paketlerle uyum sorunları yaşayabilirler ve bu durum "
+"sisteminizin düzgün bir biçimde başlamasına engel olabilir."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Bu önyükleme kayıtları başka bir işletim sistemindeki bir GRUB 2 kurulumu "
+"tarafından oluşturulmamışsa,\n"
+" GRUB 2 kurulumunu tamamlamanız gerekmektedir."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux komut satırı:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Aşağıdaki Linux komut satırı /etc/default/grub dosyasından ya da GRUB Legacy "
+"menu.lst dosyasındaki 'kopt' parametresinden alınmıştır. Lütfen "
+"doğruluğundan emin olun ve gerekirse değiştirin. Komut satırı boş "
+"bırakılabilir."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Öntanımlı Linux komut satırı:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Aşağıdaki dizgi öntanımlı menü öğesinin Linux parametreleri olarak "
+"kullanılacak; fakat kurtarma kipi için kullanılmayacaktır."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "EFI taşınabilir ortam yoluna ek bir kurulum zorlansın mı?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Bazı EFI tabanlı sistemler hatalı olduklarından yeni önyükleyicileri olması "
+"gerektiği gibi yönetmezler. EFI taşınabilir ortam yoluna ek bir GRUB "
+"kurulumu yapılmasını zorlarsanız, bu yaklaşımınız söz konusu soruna rağmen "
+"sisteminizin Debian'ı düzgün bir biçimde başlamasını sağlayacaktır. Öte "
+"yandan bu durum aynı ortam yoluna bağlı başka işletim sistemleri varsa, "
+"onların önyüklenebilirliğini ortadan kaldırabilir. Böyleyse, GRUB'un diğer "
+"işletim sistemlerini de düzgün bir biçimde başlatabilecek şekilde başarı ile "
+"yapılandırıldığından emin olmalısınız."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "NVRAM değişkenleri Debian'ı önyükleyecek şekilde güncellensin mi?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB, NVRAM değişkenlerini sisteminiz açıldığında otomatikman Debian'ı "
+"başlatacak şekilde yapılandırılabilir. Fakat bu davranışı devre dışı "
+"bırakıp, önyükleme yapılandırmasında herhangi bir değişiklik yapılmamasını "
+"yeğleyebilirsiniz. Bu durumda, örneğin NVRAM değişkenleri sisteminiz her "
+"açılışta bir PXE sunucusu ile iletişim kuracak şekilde ayarlanmışsa bu "
+"davranış aynı şekilde sürecektir."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+"os-prober diğer işletim sistemlerini otomatikman bulmak ve önyüklemek için "
+"çalıştırılsın mı?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+"GRUB, bilgisayarınızdaki diğer işletim sistemlerini algılamak ve onları "
+"önyükleme seçenekleri listesine eklemek için os-prober programını "
+"kullanabilir."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+"Eğer bilgisayarınızda birden fazla işletim sistemi kurulu ise, büyük "
+"olasılıkla bunu istersiniz. Fakat bilgisayarınız LVM ya da ham disk "
+"aygıtları ile kurulmuş konuk işletim sistemleri için bir ev sahibi ise, os-"
+"prober bir şeylere bakmak için dosya sistemlerini bağladığı için onu "
+"çalıştımak bu konuk işletim sistemlerine zarar verebilir."
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD komut satırı:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Aşağıdaki kFreeBSD komut satırı /etc/default/grub dosyasından ya da GRUB "
+"Legacy menu.lst dosyasındaki 'kopt' parametresinden alınmıştır. Lütfen "
+"doğruluğundan emin olun ve gerekirse değiştirin. Komut satırı boş "
+"bırakılabilir."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Öntanımlı kFreeBSD komut satırı:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Aşağıdaki dizgi öntanımlı menü öğesinin kFreeBSD parametreleri olarak "
+"kullanılacak; fakat kurtarma kipi için kullanılmayacaktır."
diff --git a/debian/po/ug.po b/debian/po/ug.po
new file mode 100644
index 0000000..5d6d682
--- /dev/null
+++ b/debian/po/ug.po
@@ -0,0 +1,476 @@
+# Uyghur translation for grub_debian.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Sahran <sahran.ug@gmail.com>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub_debian\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-26 21:24-0500\n"
+"Last-Translator: Abduqadir Abliz <sahran.ug@gmail.com>\n"
+"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
+"Language: Uyghur\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.5\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "menu.lst دىن Chainload قىلامدۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"GRUB نەشرىنى يۇقىرىلىتىش قوليازمىسى /boot/grub غا ئورنىتىلغان GRUB Legacy نى "
+"بايقىدى."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"سىستÛمىڭىزدىكى GRUB Legacy نى ئالماشتۇرۇش ئۈچۈن /boot/grub/menu.lst نى "
+"نۆۋەتتىكى مەۋجۇت GRUB Legacy تەڭشىكىدە GRUB 2 قوزغىتىش ÙŠÛتەكلىگۈچ تەسۋىرىنى "
+"يۈكلەڭ. ھازىر بۇ مەشغۇلاتنى ئۆزلۈكىدىن ئىجرا قىلالايدۇ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"سىزنىڭ menu.lst دىكى chainloading GRUB 2 نى قوبۇل قىلىشىڭىزنى تەۋسىيە "
+"قىلىمىز ھەمدە GRUB 2 بىۋاسىتە MBR (ئاساسىي ÙŠÛتەكلەش خاتىرىسى)غا ئورنىتىشتىن "
+"ئىلگىرى ÙŠÛÚ­Ù‰ GRUB 2 تەڭشىكىنىڭ نورمال خىزمەت قىلىدىغانلىقىنى جەزملەڭ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"قانداق Ú¾Û†ÙƒÛˆÙ… چىقىرىشىڭىزدىن قەتئىينەزەر، سىز ÙƒÛيىن root سالاھىيىتىدە "
+"تۆۋەندىكى بۇيرۇقنى ئىجرا قىلىپ GRUB 2 بىلەن كونا MBR تەسۋىرىنى "
+"ئالماشتۇرالايسىز:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB ئورنىتىش ئۈسكۈنىسى:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc بوغچىسى ÙŠÛڭىلاندى. بۇ تىزىملىك سىزنىڭ قايسى ئۈسكۈنىدە grub-install "
+"نى ئۆزلۈكىدىن ئىجرا قىلىشنى تاللىشىڭىزغا يول قويىدۇ، ئەگەر بار بولسا."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"كۆپىنچە ئەھۋاللاردا grub-install نى ئۆزلۈكىدىن ئىجرا قىلىش تەۋسىيە قىلىنىپ، "
+"ئورنىتىلغان GRUB نىڭ يادرولۇق تەسۋىرى بىلەن GRUB بۆلىكى ياكى grub.cfg نىڭ "
+"قەدەمداش بولماسلىقىنىڭ ئالدى ئÛلىنىدۇ."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"ئەگەر BIOS نىڭ قايسى قوزغاتقۇچنى ئاساسىي ÙŠÛتەكلىگۈچ سۈپىتىدە "
+"ئىشلىتىدىغانلىقىنى جەزملىيەلمىسىڭىز، GRUB نى بۇ قوزغاتقۇچلارنىڭ ھەممىسىگە "
+"ئورنىتىش ئادەتتە ياخشى چارە بولالايدۇ."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"دىققەت: GRUB نى رايوننىڭ ÙŠÛتەكلەش خاتىرىسىگە ئورناتسىڭىزمۇ بولىدۇ، بۇ جايدا "
+"مۇۋاپىق بولغان رايونلار تەمىنلەندى. ئەمما بۇنداق بولغاندا GRUB مەجبۇرىي قارا "
+"تىزىملىك Ù…Ûخانىزمىنى ئىشلىتىپ، ئىشەنچلىكلىكىنىڭ تۆۋەنلەپ ÙƒÛتىشىنى كەلتۈرۈپ "
+"چىقىرىدۇ، شۇڭلاشقا ئىشلىتىش تەۋسىيە قىلىنمايدۇ."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB قوزغىتىش ÙŠÛتەكلىگۈچ يوقالغان دىسكىدىن بىرىگە ئورنىتىلغان ياكى ئۇنىڭ "
+"بىردىنبىر بەلگىسى مەلۇم سەۋەبلەردىن ئۆزگەرگەن. ئورنىتىلغان GRUB نىڭ يادرولۇق "
+"تەسۋىرى ۋە GRUB بۆلىكى شۇنداقلا grub.cfg نى قەدەمداشلاش ناھايىتى مۇھىم. "
+"قايتا بىر Ù‚Ûتىم تەكشۈرۈپ GRUB نىڭ مۇۋاپىق قوزغىتىش ئۈسكۈنىسىگە "
+"ئورنىتىلغانلىقىغا كاپالەتلىك قىلىڭ."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB, ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB, ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "GRUB نى قوزغىتىش ئۈسكۈنىسىگە يازالمىدى - داۋاملاشتۇرامدۇ؟"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB نى تۆۋەندىكى ئۈسكۈنىگە ئورنىتالمىدى:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"داۋاملاشتۇرۇۋÛرەمسىز؟ ئەگەر مۇشۇنداق قىلسىڭىز، كومپيۇتÛرىڭىز توغرا "
+"قوزغىلالماسلىقى مۇمكىن."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "GRUB نى قوزغىتىش ئۈسكۈنىسىگە ÙŠÛزىش مەغلۇپ بولدى - قايتا سىنامدۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"سىز GRUB نى باشقا ئۈسكۈنىگە ئورنىتالىشىڭىز مۇمكىن، تەكشۈرۈشنى جەزملىشىڭىز "
+"زۆرۈر بولسىمۇ سىستÛمىڭىز Ø´Û‡ ئۈسكۈنىدىن قوزغىلىدۇ. بولمىسا GRUB Legacy دىن "
+"ÙŠÛڭىلاشتىن ۋاز ÙƒÛچىدۇ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "GRUB نى ئورناتماي داۋاملاشتۇرامدۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"سىز Ú¾Ûچقانداق ئۈسكۈنىگە GRUB ئورنىتىشنى تاللىمىدىڭىز. ئەگەر "
+"داۋاملاشتۇرسىڭىز، قوزغىتىش ÙŠÛتەكلىگۈچنى توغرا سەپلىيەلمەسلىكىڭىز مۇمكىن، "
+"كومپيۇتÛرىڭىز ÙƒÛيىنكى Ù‚Ûتىم قوزغالغاندا ئۇ ÙŠÛتەكلەش سÛكتورىدىكى ئىلگىرىكى "
+"مەزمۇننى ئىشلىتىدۇ. ئەگەر ÙŠÛتەكلەش سÛكتورىدا ئىلگىرىكى نەشرىدىكى GRUB 2 "
+"بولسا ئۇنىڭ بۆلەكلىرىنى ياكى نۆۋەتتىكى سەپلىمە ھۆججەتنى يۈكلىگىلى بولماسلىقى "
+"مۇمكىن."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"ئەگەر سىز باشقا بىر قوزغىتىش ÙŠÛتەكلىگۈچ ئىشلەتكەن ھەمدە داۋاملىق مۇشۇنداق "
+"قىلماقچى بولسىڭىز ياكى ئەگەر بۇ بىر ئالاھىدە قوزغىتىش ÙŠÛتەكلىگۈچ تەلەپ "
+"قىلمايدىغان مۇھىت بولسا، بۇ خىل ئەھۋالدا يەنىلا داۋاملاشتۇرۇشقا بولىدۇ. "
+"ئۇنداق بولمىسا سىز مەلۇم جايغا GRUB ئورنىتىشىڭىز لازىم."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "/boot/grub دىن GRUB 2 نى چىقىرىۋÛتەمدۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "/boot/grub تىن GRUB 2 نىڭ ھەممە ھۆججەتلىرىنى چىقىرىۋÛتەمسىز؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"بۇنداق بولغاندا سىستÛمىنى ÙŠÛتەكلىگىلى بولمايدۇ، باشقا قوزغىتىش ÙŠÛتەكلىگۈچ "
+"ئورنىتىلسا بۇ باشقا گەپ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "ھازىر GRUB 2 نىڭ ئايلاندۇرۇشىنى تاماملىدىمۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"بۇ سىستÛمىدا يەنىلا GRUB Legacy قوزغىتىش ÙŠÛتەكلىگۈچ ئورناتقان ھۆججەت مەۋجۇت "
+"ئەمما ھازىرمۇ دىسكىغا GRUB 2 ÙŠÛتەكلەش خاتىرىسىنى ئورناتتى:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"قارىغاندا GRUB Legacy ئىشلىتىلمىگەندەك تۇرىدۇ، ھەمدە سىز بۇ دىسكىلاردا GRUB "
+"2 تەسۋىرىگە ÙŠÛڭىلىشىڭىز لازىم، كونا GRUB Legacy ھۆججەتلىرىنى ئۆچۈرۈش "
+"ئارقىلىق GRUB 2 تەسۋىرىنى ئايلاندۇرۇشنى تاماملايدۇ. ئەگەر بۇ GRUB 2 "
+"تەسۋىرىنى ÙŠÛڭىلىمىغاندا ئۇلار ÙŠÛÚ­Ù‰ بوغچا بىلەن ماسلاشمىغانلىقتىن "
+"سىستÛمىڭىزنىڭ نورمال ÙŠÛتەكلىنىپ قوزغالماسلىقىنى كەلتۈرۈپ چىقىرىدۇ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"سىز ئادەتتە GRUB 2 نىڭ ئايلاندۇرۇشىنى تاماملىشىڭىز لازىم، بۇ ÙŠÛتەكلەش "
+"خاتىرىسى باشقا مەشغۇلات سىستÛمىسىغا ئورنىتىلغان GRUB 2 قۇرغان بولسا بۇ باشقا "
+"Ú¯Û•Ù¾."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux بۇيرۇق قۇرى:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"تۆۋەندىكى Linux بۇيرۇق قۇرى /etc/default/grub ياكى GRUB Legacy نىڭ menu.lst "
+"دىكى `kopt' پارامÛتىرىدىن ئاجرىتىدۇ. ئۇنىڭ توغرىلىقىنى جەزملەپ، ئÛھتىياجغا "
+"ئاساسەن ئۆزگەرتىڭ.بۇيرۇق قۇرىنىڭ بوش قالدۇرۇلۇشىغا يول قويۇلىدۇ."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux كۆڭۈلدىكى بۇيرۇق قۇرى:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"تۆۋەندىكى ھەرپ تىزىقى كۆڭۈلدىكى تىزىملىك تۈرىنىڭ Linux پارامÛتىرىغا "
+"ئىشلىتىلىدۇ ئەمما ئەسلىگە كەلتۈرۈش ھالىتىگە قوللىنىلمايدۇ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+"مەزكۇر EFI كۆچمە ۋاسىتە يولىنى مەجبۇرىي ھالدا نورمىدىن ئارتۇق ئورنىتامدۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"بىر قىسىم EFI ئاساسىدىكى سىستÛمىلاردا مەسىلە بار ئۇنىڭ ئۈستىگە ÙŠÛÚ­Ù‰ "
+"ÙŠÛتەكلەشنى يۈكلەش پىروگراممىسىنى توغرا بىر تەرەپ قىلالمايدۇ. ئەگەر GRUB نى "
+"EFI كۆچمە ۋاسىتە يولىغا مەجبۇرىي ھالدا نورمىدىن ئارتۇق ئورناتقاندا، بۇ "
+"سىستÛمىنىڭ Debian نى نورمال قوزغىتىشقا كاپالەتلىك قىلىش ÙƒÛرەك، گەرچە بۇنداق "
+"مەسىلە بولسىمۇ ئەمما ئۇ باشقا مەشغۇلات سىستÛمىسى ÙŠÛتەكلەشتە تايىنىدىغان "
+"يولنى ئۆچۈرۈۋÛتىشى مۇمكىن. ئەگەر شۇنداق بولسا، باشقا مەشغۇلات سىستÛمىسىنى "
+"ئورنىتىشنى نورمال قوزغىتىش ئۈچۈن GRUB نىڭ مۇۋەپپەقىيەتلىك سەپلەنگەنلىكىگە "
+"كاپالەتلىك قىلىڭ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+"مەزكۇر NVRAM ئۆزگەرگۈچى قىممىتىنى ÙŠÛڭىلاپ Debian Ú¯Û• ئۆزلۈكىدىن ÙŠÛتەكلەمدۇ؟"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"مەزكۇر GRUB سۇپىڭىزنىڭ NVRAM قىممىتىنى سەپلەپ، توك چاتقاندا Debian گە "
+"ئۆزلۈكىدىن ÙŠÛتەكلەشكە قولايلىق يارىتىدۇ. ئەمما ÙŠÛتەكلەش سەپلىمىسىنى "
+"ئۆزگەرتىشتىن ساقلىنىش ئۈچۈن بۇ قىلمىشنى چەكلەشنى ئۈمىد قىلىشىڭىز مۇمكىن. "
+"مەسىلەن، ئەگەر سىزنىڭ NVRAM ئۆزگەرگۈچى قىممىتىڭىز سىستÛما ھەر Ù‚Ûتىم "
+"قوزغالغاندا PXE مۇلازىمÛتىر بىلەن باغلىنىدىغان قىلىپ تەڭشەلگەن بولسا، بۇ "
+"قىلمىشنى ساقلاپ قالىدۇ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD بۇيرۇق قۇرى:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"تۆۋەندىكى kFreeBSD بۇيرۇق قۇرى /etc/default/grub ياكى GRUB Legacy نىڭ menu."
+"lst دىكى `kopt' پارامÛتىرىدىن ئاجرىتىدۇ. ئۇنىڭ توغرىلىقىنى جەزملەپ، "
+"ئÛھتىياجغا ئاساسەن ئۆزگەرتىڭ. بۇيرۇق قۇرىنىڭ بوش قالدۇرۇلۇشىغا يول قويۇلىدۇ."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD كۆڭۈلدىكى بۇيرۇق قۇرى:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"تۆۋەندىكى ھەرپ تىزىقى كۆڭۈلدىكى تىزىملىك تۈرىنىڭ kFreeBSD پارامÛتىرىغا "
+"ئىشلىتىلىدۇ ئەمما ئەسلىگە كەلتۈرۈش ھالىتىگە قوللىنىلمايدۇ."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map ھاسىل قىلىندى"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "مۇقىم ئۈسكۈنە ئىسمىنى ئىشلىتىش ئۈچۈن /boot/grub/device.map ھۆججىتى قايتا "
+#~ "ÙŠÛزىلدى. ÙƒÛ†Ù¾ قىسىم ئەھۋالدا بۇ ئۇنى قايتا ئۆزگەرتىش ئÛھتىياجىنى ئازايتىشى "
+#~ "لازىم، GRUB ھاسىل قىلغان ÙŠÛتەكلەش تىزىملىكى تەسىرگە ئۇچرىماسلىقى لازىم."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "ھالبۇكى، سىستÛمىڭىزدا قانچە دىسكا بار، سىستÛما كونا ئۈسكۈنە تەسۋىرىگە "
+#~ "تايىنىشى مۇمكىن. ئۆزىڭىز بەلگىلىگەن ھەر قانداق GRUB نىڭ (hdN) قوزغاتقۇچ "
+#~ "نومۇرىنىڭ ÙŠÛتەكلەش تىزىملىكى بار يوقلۇقىنى تەكشۈرۈڭ، ئەگەر ئÛھتىياجلىق "
+#~ "بولسىڭىز ئۇلارنى ÙŠÛڭىلاڭ."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "ئەگەر بۇ ئۇچۇرنى چۈشەنمىسىڭىز ياكى ھەر قانداق ئۆزلەشتۈرگەن ÙŠÛتەكلەش "
+#~ "تىزىملىكى بولمىسا بۇ ئۇچۇرغا پەرۋا قىلمىسىڭىزمۇ بولىدۇ."
diff --git a/debian/po/uk.po b/debian/po/uk.po
new file mode 100644
index 0000000..bb6854e
--- /dev/null
+++ b/debian/po/uk.po
@@ -0,0 +1,478 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# ОлекÑандр Яценко, 2010.
+# Yatsenko Alexandr <yatsenko.alexandr@gmail.com>, 2010.
+# Anton Gladky <gladky.anton@gmail.com>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-23 16:36+0200\n"
+"Last-Translator: Yatsenko Alexandr <yatsenko.alexandr@gmail.com>\n"
+"Language-Team: Ukrainian <translation@linux.org.ua>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.11\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Завантажити поÑлідовно з menu.lst? "
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "Скрипт Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ GRUB знайшов попередню Legacy верÑÑ–ÑŽ в /boot/grub."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Перед повною заміною попередньої верÑÑ–Ñ— GRUB у вашій ÑиÑтемі рекомендовано "
+"приєднати GRUB 2 Ñк варіант Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ наÑвному меню GRUB Legacy. Цей "
+"крок може бути виконано автоматично зараз."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Рекомендовано Ñпробувати поÑлідовне Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ GRUB 2 з menu.lst щоб "
+"переконатиÑÑ, що ваш новий GRUB 2 функціонує, до того Ñк вÑтановити його "
+"напрÑму до MBR (Головного завантажувального Ñектору)"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Залежно від вашого бажаннÑ, можна замінити Ñтарий завантажувач в MBR на GRUB "
+"2 пізніше увівши наÑтупну команду кориÑтувачем root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "ДиÑкові приÑтрої Ð´Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Пакунок grub-pc було оновлено. Це меню дозволить вам обрати диÑкові приÑтрої "
+"з Ñких grub-install буде автоматично запуÑкатиÑÑ."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Ðвтоматичний запуÑк grub-install рекомендовано в більшоÑÑ‚Ñ– випадків, щоб "
+"запобігти розÑинхронізації вÑтановленого базового Ñдра GRUB з його модулÑми "
+"чи grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Якщо ви не знаєте напевне, Ñкий диÑковий приÑтрій призначено "
+"завантажувальним у вашому BIOS, можете вÑтановити GRUB на вÑÑ– наÑвні."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Увага: Ñ” можливим вÑтановити GRUB до завантажувальних запиÑів диÑкових "
+"розділів Ñ– деÑкі підходÑщі розділи запропоновано нижче. Проте, це заÑтавить "
+"GRUB вжити механізм блокуваннÑ, що зробить його менш надійним, а тому не "
+"рекомендуєтьÑÑ."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Завантажувач GRUB раніше було вÑтановлено на диÑковий приÑтрій, що наразі "
+"відÑутній, або його унікальний ідентифікатор з ÑкихоÑÑŒ причин було змінено. "
+"Важливо переконатиÑÑ, що вÑтановлене базове Ñдро GRUB відповідає наÑвним "
+"модулÑм та grub.cfg. Будь лаÑка, перевірте знову чи GRUB запиÑано на "
+"відповідні завантажувальні диÑкові розділи."
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} МБ; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} МБ; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати GRUB до завантажувального приÑтрою. Продовжити?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "Ðе вдалоÑÑ Ð²Ñтановити GRUB до наÑтупних диÑкових приÑтроїв:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Ви вÑеодно бажаєте продовжити? Ðе виключено, що ваш комп'ютер не зможе "
+"завантажитиÑÑ Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð¾."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr ""
+"Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати GRUB до завантажувальних приÑтроїв. Спробувати знову?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Ви можете вÑтановити GRUB до іншого завантажувального приÑтрою, але Ð´Ð»Ñ "
+"цього потрібно переконатиÑÑ, що ÑиÑтема завантажитьÑÑ Ð· нього. Інакше, "
+"Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð· GRUB Legacy не буде виконано."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Продовжити без вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Ви обрали не вÑтановлювати GRUB на жоден приÑтрій. Якщо так продовжувати, "
+"завантажувач може бути не до ÐºÑ–Ð½Ñ†Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚Ð¾Ð²Ð°Ð½Ð¸Ð¹ Ñ– при наÑтупному запуÑку "
+"комп'ютера буде викориÑтано те, що Ñ” наразі у завантажувальному Ñекторі. "
+"Якщо там виÑвитьÑÑ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñ GRUB 2, вона, можливо, не зможе "
+"завантажити модулі чи опрацювати поточний конфігураційний файл."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Якщо ви викориÑтовуєте інший завантажувач Ñ– хочете залишити його, або маєте "
+"оÑобливе оточеннÑ, де немає потреби в завантажувачі, можете продовжити, "
+"інакше маєте вÑтановити GRUB."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Вилучити GRUB 2 з /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Ви бажаєте вилучити вÑÑ– файли GRUB 2 з /boot/grub?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Ð¦Ñ Ð´Ñ–Ñ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚ÑŒ ÑиÑтему не здатною завантажитиÑÑ, доки інший завантажувач не "
+"буде вÑтановлено."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Завершити перехід до GRUB 2 зараз?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Ваша ÑиÑтема міÑтить вÑтановлені файли з GRUB Legacy, але на наÑтупних "
+"диÑках приÑутній завантажувач GRUB 2:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Схоже, GRUB 2 більше не викориÑтовуєтьÑÑ, тому ви можете замінити його, "
+"оновивши образи GRUB 2 на цих диÑках та завершити перехід до GRUB 2, "
+"вилучивши Ñтарі файли від GRUB Legacy. Якщо ви не оновите ці образи, вони "
+"можуть бути неÑуміÑні з новими пакунками Ñ– ваша ÑиÑтема не зможе нормально "
+"завантажуватиÑÑ."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Ви маєте повніÑÑ‚ÑŽ завершити перехід на GRUB 2, Ñкщо ці завантажувальні "
+"запиÑи було Ñтворено GRUB 2 іншої операційної ÑиÑтеми."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "РÑдок параметрів Ñдра Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ÐаÑтупний Ñ€Ñдок параметрів Ñдра Linux було взÑто із /etc/default/grub чи з "
+"параметру 'kopt' в menu.lst із GRUB Legacy. Перевірте будь лаÑка його "
+"правильніÑÑ‚ÑŒ Ñ–, за потреби, внеÑÑ–Ñ‚ÑŒ зміни. РÑдок параметрів Ñдра може бути "
+"порожнім."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Типовий Ñ€Ñдок параметрів Ñдра Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Даний Ñ€Ñдок буде викориÑтано Ñк параметри Ñдра Linux Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð²Ð¾Ð³Ð¾ пункту "
+"меню, проте не Ð´Ð»Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ відновленнÑ."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+"ЗдійÑнити примуÑове вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ EFI, розташованого на змінному ноÑÑ–Ñ—?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"ДеÑкі EFI-ÑиÑтеми мають вади, що не дають їм коректно працювати із новими "
+"завантажувачами. Якщо ви виконаєте примуÑове вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ GRUB на змінний "
+"ноÑій із EFI, то Debian буде завантажуватиÑÑ Ð½ÐµÐ·Ð²Ð°Ð¶Ð°ÑŽÑ‡Ð¸ на цю проблему. "
+"Проте ви можете втратити можливіÑÑ‚ÑŒ завантажувати інші операційні ÑиÑтеми, "
+"що залежать від цього розташуваннÑ. Якщо так, то переконайтеÑÑ, що GRUB "
+"налаштовано належним чином щоб завантажувати правильно інші ОС."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Оновити змінні NVRAM Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB може налаштувати змінні NVRAM вашої платформи так, щоб завантажувати "
+"Debian автоматично відразу піÑÐ»Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ. Проте ви можете "
+"заборонити це щоб уникнути змін ваших налаштувань завантаженнÑ. Ð”Ð»Ñ "
+"прикладу, Ñкщо ваші змінні NVRAM налаштовані на автоматичне з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ "
+"ÑиÑтеми із PXE-Ñервером при кожному завантаженні, то ви збережете Ñ—Ñ…."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "РÑдок параметрів Ñдра kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"ÐаÑтупний Ñ€Ñдок параметрів Ñдра kFreeBSD було взÑто із /etc/default/grub чи "
+"з параметру 'kopt' в menu.lst із GRUB Legacy. Перевірте будь лаÑка його "
+"правильніÑÑ‚ÑŒ Ñ–, за потреби, внеÑÑ–Ñ‚ÑŒ зміни. РÑдок параметрів Ñдра може бути "
+"порожнім."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Типовий Ñ€Ñдок параметрів Ñдра kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Даний Ñ€Ñдок буде викориÑтано Ñк параметри Ñдра kFreeBSD Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð²Ð¾Ð³Ð¾ пункту "
+"меню, проте не Ð´Ð»Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ відновленнÑ."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map було Ñтворено наново"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Файл /boot/grub/device.map було перепиÑано з викориÑтаннÑм Ñталих імен "
+#~ "приÑтроїв. Ð’ більшоÑÑ‚Ñ– випадків це значно зменшить потребу змінювати його "
+#~ "в майбутньому Ñ– пункти меню завантажувача GRUB не будуть змінюватиÑÑ."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Якщо в ÑиÑтемі наÑвний більше, ніж один диÑковий приÑтрій, можливо вона "
+#~ "налаштована на Ñтару карту приÑтроїв. Будь лаÑка, перевірте, чи не "
+#~ "викориÑтано в кориÑтувацьких пунктах меню завантажувача нумерації диÑків "
+#~ "типу hdN, та оновіть Ñ—Ñ…, Ñкщо потрібно."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Якщо ви не розумієте цього повідомленнÑ, або не маєте кориÑтувацьких "
+#~ "пунктів меню завантажувача, проігноруйте це повідомленнÑ."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Ð’ іншому випадку, Ñкщо ви бажаєте завантажити GRUB 2 прÑмо до MBR, ви "
+#~ "можете зробити це, задавши (з правами root) наÑтупну команду:"
diff --git a/debian/po/vi.po b/debian/po/vi.po
new file mode 100644
index 0000000..5b5798c
--- /dev/null
+++ b/debian/po/vi.po
@@ -0,0 +1,481 @@
+# Vietnamese translation for Grub2_Debian.
+# Copyright © 2010 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2010.
+# Hai Lang <hailangvn@gmail.com>, 2012.
+# Trần Ngá»c Quân <vnwildman@gmail.com>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2017-01-21 08:26+0700\n"
+"Last-Translator: Trần Ngá»c Quân <vnwildman@gmail.com>\n"
+"Language-Team: Vietnamese <debian-l10n-vietnamese@lists.debian.org>\n"
+"Language: vi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Gtranslator 2.91.7\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "Nạp dãy (chainload) từ menu.lst?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr ""
+"Văn lệnh nâng cấp GRUB phát hiện được một thiết lập GRUB Cũ (GRUB Legacy) "
+"trong “/boot/grubâ€."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"Äể thay thế phiên bản CÅ© của GRUB trong hệ thống này, nên Ä‘iá»u chỉnh /boot/"
+"grub/menu.lst để nạp ảnh khởi động GRUB 2 từ thiết lập GRUB Cũ đã có. Bước "
+"này có thể được tá»± Ä‘á»™ng thá»±c hiện ngay bây giá»."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"Bạn nên đồng ý việc nạp dãy GRUB 2 từ menu.lst, và kiểm tra rằng thiết lập "
+"GRUB 2 mới có thể làm việc được trước khi nó được ghi vào MBR (Mục ghi Khởi "
+"động Chủ)."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"Dù bạn quyết định thế nào, sau này bạn vẫn có thể thay thế ảnh MBR cũ bởi "
+"GRUB 2 bằng cách thá»±c hiện câu lệnh sau vá»›i quyá»n root:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "Những thiết bị cài đặt GRUB:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"Gói grub-pc sắp được cập nhật. Trình Ä‘Æ¡n này cho bạn chá»n thiết bị nào, nếu "
+"có, mà bạn muốn grub-install tự động chạy trên đó."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"Nên chạy grub-install má»™t cách tá»± Ä‘á»™ng trong hầu hết các trÆ°á»ng hợp, để "
+"tránh sự mất đồng bộ giữa ảnh lõi GRUB đã được cài đặt với các mô-đun GRUB "
+"hay grub.cfg."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"Nếu bạn không chắc ổ Ä‘Ä©a nào được chỉ định làm ổ Ä‘Ä©a khởi trá»ng trong BIOS "
+"của bạn, tốt nhất là cài đặt GRUB vào tất cả các ổ đĩa."
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"Ghi chú: vẫn có thể cài GRUB vào các bản ghi khởi động của phân vùng, và một "
+"vài phân vùng phù hợp được đưa ra ở đây. Tuy nhiên, việc này bắt buộc GRUB "
+"dùng cơ chế danh sách ngăn chặn, làm cho nó ít tin cậy hơn, và do đó không "
+"nên dùng."
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"Trình nạp khởi động GRUB trước đây đã được cài đặt trên một đĩa không còn "
+"tồn tại, hay số định danh duy nhất của đĩa đó đã thay đổi vì lý do nào đó. "
+"Quan trá»ng là phải chắc chắn rằng ảnh lõi GRUB đã được cài còn đồng bá»™ vá»›i "
+"các mô-đun GRUB và grub.cfg. Vui lòng kiểm tra lại để chắc chắn rằng GRUB "
+"được ghi vào các thiết bị khởi động phù hợp."
+
+# Variable: don't translate; Biến: đừng dịch
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+# Variable: don't translate; Biến: đừng dịch
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "Việc ghi GRUB vào thiết bị khởi động bị lỗi - tiếp tục không?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB gặp lỗi khi cài đặt vào những thiết bị sau đây:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr ""
+"Bạn vẫn muốn tiếp tục không? Nếu có thì máy tính có thể không khởi động được."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "Gặp lỗi khi ghi GRUB vào thiết bị khởi động - thử lại nhé?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"Có thể là bạn cài đặt được GRUB vào một thiết bị khác (trước tiên nên kiểm "
+"tra nếu hệ thống sẽ khởi động từ thiết bị đó). Không thì tiến trình nâng cấp "
+"từ GRUB CÅ© (Legacy) sẽ bị bãi bá»."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "Tiếp tục lại mà không cài đặt GRUB?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"Bạn đã chá»n không cài đặt GRUB vào thiết bị nào. Nếu tiếp tục thì bá»™ nạp "
+"khởi động có thể bị cấu hình sai, và khi máy tính khởi động lại nó sẽ sử "
+"dụng dữ liệu bất kỳ trước đây có trong rãnh ghi khởi động. Nếu rãnh ghi khởi "
+"động chứa một phiên bản GRUB 2 cũ, nó có thể không nạp được mô-đun hoặc "
+"không xá»­ lý được tập tin cấu hình hiện thá»i."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"Nếu bạn đã dùng một bộ nạp khởi động khác và muốn tiếp tục dùng, hoặc nếu "
+"đây là má»™t môi trÆ°á»ng đặc biệt mà không cần thiết bá»™ nạp khởi Ä‘á»™ng, thì bạn "
+"nên tiếp tục. Nếu không thì bạn nên cài đặt GRUB vào một nơi nào đó."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "Gỡ bá» GRUB 2 khá»i /boot/grub không?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "Bạn có muốn gỡ bá» tất cả tập tin GRUB 2 khá»i /boot/grub không?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr ""
+"Việc này làm cho hệ thống không khởi động được trừ khi trình nạp khởi động "
+"khác được cài đặt."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "Kết thúc chuyển đổi sang GRUB2 ngay bây gi�"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"Hệ thống này vẫn còn có tập tin được cài đặt bởi bộ nạp khởi động GRUB Cũ "
+"(Legacy), nhưng mà cũng có mục ghi GRUB2 được cài đặt vào những đĩa này:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"Rất có thể là GRUB Cũ (Legacy) không còn được sử dụng, vì thế bạn nên nâng "
+"cấp các ảnh GRUB2 trên những đĩa này và kết thúc chuyển đổi sang GRUB2 bằng "
+"cách gỡ bỠtất cả các tập tin GRUB Cũ. Không nâng cấp các ảnh GRUB2 thì "
+"chúng có thể không tương thích với gói mới và gây ra hệ thống này không khởi "
+"động đúng."
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"Nói chung bạn nên kết thúc chuyển đổi sang GRUB2 nếu các mục ghi khởi động "
+"này không được tạo bởi má»™t bản cài đặt GRUB2 trên má»™t hệ Ä‘iá»u hành khác."
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Dòng lệnh Linux:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Dòng lệnh Linux theo đây đã được trích ra từ /etc/default/grub hoặc từ tham "
+"số “kopt†trong menu.lst của GRUB Cũ. Hãy kiểm tra rằng nó vẫn đúng, và sửa "
+"đổi nó nếu cần. Dòng lệnh có thể được để trống."
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Dòng lệnh Linux mặc định:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"Chuỗi theo đây sẽ được sử dụng làm các tham số Linux cho mục nhập trình đơn "
+"mặc định, mà không phải cho chế độ phục hồi."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "Buá»™c cài đặt thêm cho Ä‘Æ°á»ng dẫn thiết bị di Ä‘á»™ng Ä‘a phÆ°Æ¡ng tiện EFI?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"Một số hệ thống dựa trên EFI có lỗi và không thể xử lý bootloader mới một "
+"cách chính xác. Nếu bạn buá»™c cài đặt GRUB thêm vào Ä‘Æ°á»ng dẫn thiết bị di "
+"động đa phương tiện EFI, nó có thể đảm bảo rằng hệ thống này sẽ khởi động "
+"Debian một cách đúng đắn bất chấp trục trặc. Tuy vậy, nó có thể làm mất đi "
+"khả năng khởi Ä‘á»™ng các hệ Ä‘iá»u hành khác cái mà cÅ©ng phụ thuá»™c vào Ä‘Æ°á»ng dẫn "
+"này. Nếu thế, bạn sẽ cần chắc chắn là GRUB được cấu hình thành công để có "
+"thể khới động bất kỳ OS đã cài đặt nào một cách chính xác."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr "Cập nhật các biến NVRAM để tự động khởi động vào Debian?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+"GRUB có thể cấu hình các biến NVRAM của ná»n tảng vậy thì nó khởi Ä‘á»™ng vào "
+"Debian một cách tự động không bật máy. Tuy nhiên, bạn có lẽ ưa thích tắt "
+"cách hành xử này và tránh thay đổi đến cấu hình khởi động của bạn. Ví dụ, "
+"nếu biến NVRAM của bạn đã được cài đặt như thế hệ thống liên lạc với máy "
+"phục vụ PXE má»—i lần khởi Ä‘á»™ng, Ä‘iá»u này sẽ ngăn ngừa cách hành xá»­ đó."
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "Dòng lệnh kFreeBSD:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"Dòng lệnh kFreeBSD sau đây đã được trích ra từ /etc/default/grub hoặc từ "
+"tham số “kopt†trong menu.lst của GRUB Cũ. Hãy kiểm tra rằng nó vẫn đúng, và "
+"sửa đổi nó nếu cần. Dòng lệnh có thể được để trống."
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "Dòng lệnh kFreeBSD mặc định:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"Chuỗi theo đây sẽ được sử dụng làm các tham số kFreeBSD cho mục nhập trình "
+"đơn mặc định, mà không phải cho chế độ phục hồi."
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "Tập tin /boot/grub/device.map đã được tạo lại."
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "Tập tin /boot/grub/device.map đã được ghi lại để sử dụng tên thiết bị "
+#~ "kiểu ổn định. Trong phần lá»›n các trÆ°á»ng hợp, bản cập nhật này nên giảm "
+#~ "một cách đáng kể sự cần sửa đổi vỠsau, và không nên tác động trình đơn "
+#~ "khởi động được GRUB tạo."
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "Tuy nhiên, vì bạn có nhiá»u hÆ¡n má»™t ổ Ä‘Ä©a trong hệ thống, có thể là hệ "
+#~ "thống này vẫn còn phụ thuộc vào sơ đồ thiết bị cũ. Hãy kiểm tra xem có "
+#~ "những mục trình đơn khởi động tùy thích nào dựa vào số thứ tự ổ đĩa của "
+#~ "GRUB (hdN), và cập nhật chúng nếu cần."
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "Nếu bạn không hiểu thông điệp này, hoặc nếu không có mục trình đơn khởi "
+#~ "động tùy thích nào, thì bạn có thể bỠqua thông điệp này."
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "Trong cả hai trÆ°á»ng hợp, khi nào bạn muốn nạp GRUB2 má»™t cách trá»±c tiếp từ "
+#~ "MBR, chỉ cần chạy (dÆ°á»›i ngÆ°á»i chủ) câu lệnh theo đây:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "Lỗi cài đặt GRUB. Tiếp tục?"
diff --git a/debian/po/zh_CN.po b/debian/po/zh_CN.po
new file mode 100644
index 0000000..1a73451
--- /dev/null
+++ b/debian/po/zh_CN.po
@@ -0,0 +1,438 @@
+# Chinese translations for grub2 po-debconf
+# PACKAGE 软件包的简体中文翻译.
+# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# YunQiang Su <wzssyqa@gmail.com>, 2010, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2-po-debconf master\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2011-05-28 17:29+0800\n"
+"Last-Translator: YunQiang Su <wzssyqa@gmail.com>\n"
+"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bits\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "从 menu.lst 进行 chainload?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "GRUB å‡çº§è„šæœ¬åœ¨ /boot/grub 探测到了已安装的 GRUB Legacy。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"为了å–代您系统上的 GRUB Legacy,推è调整 /boot/grub/menu.lst 为从现有的 GRUB "
+"Legacy 设置中加载 GRUB 2 引导镜åƒã€‚现在å¯ä»¥è‡ªåŠ¨æ‰§è¡Œè¿™ä¸ªæ“作。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"推è您接å—从 menu.lst 中 chainload GRUB 2,并且在将 GRUB 2 直接安装到 MBR (主"
+"引导记录,Master Boot Record) 之å‰ç¡®å®šæ–°çš„ GRUB 2 设置å¯ä»¥å·¥ä½œã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"无论现在åšä»€ä¹ˆæ ·çš„决定,您以åŽéƒ½å¯ä»¥ä½¿ç”¨ root 身份æ¥è¿è¡Œå¦‚下命令æ¥ä½¿ç”¨ GRUB "
+"2 æ¥ä»£æ›¿æ—§çš„ MBR 映åƒï¼š"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB 安装设备:"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc 包已ç»å‡çº§ã€‚æ­¤èœå•å…许您选择在哪个设备上自动è¿è¡Œ grub-install,如果有"
+"çš„è¯ã€‚"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"在大多数情况下推è自动è¿è¡Œ grub-install,以é¿å…安装的 GRUB 核心映åƒä¸Ž GRUB 模"
+"å—或 grub.cfg ä¸åŒæ­¥ã€‚"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"如果ä¸ç¡®å®š BIOS 使用哪个驱动器作为主引导,将 GRUB 安装到所有这些驱动器是一个"
+"ä¸é”™çš„主æ„。"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"注æ„:也å¯ä»¥å°† GRUB 安装到分区的引导记录,这里æ供了一些适当的分区。然而,这"
+"强制 GRUB 使用黑åå•æœºåˆ¶ï¼Œä¼šé€ æˆå¯é æ€§é™ä½Žï¼Œå› æ­¤ä¸æŽ¨è使用。"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB 引导器先å‰å®‰è£…到了一个消失了的ç£ç›˜ä¸Šï¼Œæˆ–者它的唯一标识符由于æŸäº›åŽŸå› å˜åŒ–"
+"了。确ä¿å®‰è£…çš„ GRUB 核心映åƒå’Œ GRUB 模å—åŠ grub.cfg çš„åŒæ­¥éžå¸¸é‡è¦ã€‚请å†æ¬¡æ£€"
+"æŸ¥ä»¥ç¡®ä¿ GRUB 安装到了适当的引导设备。"
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "å°† GRUB 写入引导设备失败 - è¦ç»§ç»­å—?"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "GRUB 安装到如下设备时失败。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr "ä»ç„¶æƒ³è¦ç»§ç»­ï¼Ÿå¦‚果这样,您的计算机å¯èƒ½ä¸èƒ½æ­£å¸¸å¯åŠ¨ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "å°† GRUB 写入引导设备失败 - è¦é‡æ–°å°è¯•å—?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"您å¯èƒ½å¯ä»¥å®‰è£… GRUB 到其它设备,尽管您需è¦æ˜Žç¡®ï¼Œæ‚¨çš„系统将从那个设备å¯åŠ¨ã€‚å¦"
+"则,从 GRUB Legacy çš„å‡çº§å°†è¢«å–消。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "ä¸å®‰è£… GRUB 并且继续?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"您没有选择å‘任何设备安装 GRUB。如果继续,引导器å¯èƒ½ä¸èƒ½æ­£ç¡®é…置,当您的计算机"
+"下次å¯åŠ¨æ—¶ï¼Œå®ƒå°†ä½¿ç”¨å¼•å¯¼æ‰‡åŒºä¸­å…ˆå‰çš„内容。如果引导扇区中有早期版本的 GRUB 2,"
+"å…¶å¯èƒ½ä¸èƒ½åŠ è½½æ¨¡å—或者处ç†å½“å‰é…置文件。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"如果您已ç»ä½¿ç”¨äº†å¦å¤–一个引导器并且想继续这样åšï¼Œæˆ–者如果这是一个特殊的ä¸éœ€è¦"
+"引导器的环境,这样您å¯ä»¥ä»ç„¶ç»§ç»­ã€‚å¦åˆ™ï¼Œæ‚¨åº”该在æŸå¤„安装 GRUB。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "从 /boot/grub 移除 GRUB 2 ?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "确定想从 /boot/grub 移除全部 GRUB 2 文件å—?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "这会使系统ä¸èƒ½å¼•å¯¼ï¼Œé™¤éžå¦å¤–安装其它引导器。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "现在完æˆåˆ° GRUB 2 的转æ¢ï¼Ÿ"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"此系统ä»ç„¶æœ‰ GRUB Legacy 引导器安装的文件,但是现在也在ç£ç›˜ä¸Šå®‰è£…了 GRUB 2 引"
+"导记录:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"å¥½åƒ GRUB Legacy å·²ç»ä¸å†ä½¿ç”¨äº†ï¼Œå¹¶ä¸”您应该在这些ç£ç›˜ä¸Šè½¬è€Œå‡çº§åˆ° GRUB 2 映"
+"åƒï¼Œå¹¶ä¸”通过删除旧的 GRUB Legacy 文件æ¥å®Œæˆåˆ° GRUB 2 的转æ¢ã€‚如果ä¸å‡çº§è¿™äº› "
+"GRUB 2 映åƒï¼Œä»–们将å¯èƒ½ä¸èƒ½ä¸Žæ–°åŒ…兼容而造æˆæ‚¨çš„系统ä¸èƒ½æ­£å¸¸å¼•å¯¼ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"您通常应该完æˆåˆ° GRUB 2 的转æ¢ï¼Œé™¤éžè¿™äº›å¼•å¯¼è®°å½•æ˜¯ç”±å®‰è£…到其它æ“作系统上的 "
+"GRUB 2 创建的。"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux 命令行:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"已从 /etc/default/grub 或 GRUB Legacy çš„ menu.lst 中的 `kopt' å‚数中æå–如下 "
+"Linux 命令行。请检查是å¦æ­£ç¡®çš„,并且根æ®éœ€è¦è¿›è¡Œä¿®æ”¹ã€‚此命令行å¯ä»¥ä¸ºç©ºã€‚"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux 默认命令行:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr "如下字符串将被用于默认èœå•é¡¹çš„ Linux å‚数,但是ä¸ä¼šç”¨äºŽæ¢å¤æ¨¡å¼ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD å‚数:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"已从 /etc/default/grub 或者 GRUB Legacy çš„ menu.lst 中的 `kopt' å‚数中æå–如"
+"下 kFreeBSD 命令行å‚数。请请检查是å¦æ­£ç¡®ï¼Œå¹¶ä¸”æ ¹æ®éœ€è¦è¿›è¡Œä¿®æ”¹ã€‚此命令行å¯ä»¥"
+"为空。"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD 默认命令行:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr "如下字符串将用于默认èœå•é¡¹çš„ kFreeBSD å‚数,但ä¸ä¼šç”¨äºŽæ¢å¤æ¨¡å¼ã€‚"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "/boot/grub/device.map å·²ç»ç”Ÿæˆ"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "文件 /boot/grub/device.map å·²ç»é‡å†™ä»¥ä½¿ç”¨ç¨³å®šçš„设备å。多数情况下,这应该"
+#~ "显著地å‡å°‘以åŽä¿®æ”¹å®ƒçš„需è¦ï¼Œå¹¶ä¸” GRUB 产生的引导èœå•é¡¹ä¸ä¼šå—å½±å“。"
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "然而,因为您的系统上有多个ç£ç›˜ï¼Œç³»ç»Ÿå¯èƒ½ä¾èµ–旧的设备映射。请检查您是å¦æœ‰ä»»"
+#~ "何自定义的ä¾èµ– GRUB çš„ (hdN) 驱动器å·çš„引导èœå•é¡¹ï¼Œå¦‚果需è¦è¯·æ›´æ–°å®ƒä»¬ã€‚"
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "如果您ä¸ç†è§£æ­¤æ¶ˆæ¯ï¼Œæˆ–者没有任何自定义的引导èœå•é¡¹ï¼Œæ‚¨å¯ä»¥å¿½ç•¥æ­¤æ¶ˆæ¯ã€‚"
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "无论何ç§æƒ…况,当您想直接从 MBR 加载 GRUB 2 时,您å¯ä»¥é€šè¿‡ä»¥ root 身份执行"
+#~ "如下命令æ¥å®žçŽ°ï¼š"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "GRUB 安装失败。ä»ç„¶ç»§ç»­ï¼Ÿ"
diff --git a/debian/po/zh_TW.po b/debian/po/zh_TW.po
new file mode 100644
index 0000000..39892b4
--- /dev/null
+++ b/debian/po/zh_TW.po
@@ -0,0 +1,445 @@
+# Copyright (C) 2009 Tetralet
+# This file is distributed under the same license as the grub2 package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: grub2\n"
+"Report-Msgid-Bugs-To: grub2@packages.debian.org\n"
+"POT-Creation-Date: 2023-10-02 14:23+0000\n"
+"PO-Revision-Date: 2014-12-17 17:08-0800\n"
+"Last-Translator: Vincent Chen <vinmun@gmail.com>\n"
+"Language-Team: Debian-user in Chinese [Big5] <debian-chinese-big5@lists."
+"debian.org>\n"
+"Language: zh_TW\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "Chainload from menu.lst?"
+msgstr "是å¦ä½¿ç”¨ä¾†è‡ª menu.list çš„ chainload 項目?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid "GRUB upgrade scripts have detected a GRUB Legacy setup in /boot/grub."
+msgstr "GRUB å‡ç´šç¨‹å¼å·²åœ¨ /boot/grub 裡找到了 GRUB Legacy 的設定。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"In order to replace the Legacy version of GRUB in your system, it is "
+"recommended that /boot/grub/menu.lst is adjusted to load a GRUB 2 boot image "
+"from your existing GRUB Legacy setup. This step can be automatically "
+"performed now."
+msgstr ""
+"為了è¦èƒ½å–代您系統上 Legacy 版的 GRUB,建議能修改 /boot/grub/menu.lst 來讓您"
+"原本的 GRUB Legacy 設定能載入 GRUB 2 å½±åƒæª”。ç¾åœ¨å°‡è¦è‡ªå‹•é€²è¡Œé€™å€‹æ­¥é©Ÿã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"It's recommended that you accept chainloading GRUB 2 from menu.lst, and "
+"verify that the new GRUB 2 setup works before it is written to the MBR "
+"(Master Boot Record)."
+msgstr ""
+"在直接將 GRUB 2 安è£åˆ° MBR(主è¦é–‹æ©Ÿè¨˜éŒ„)之å‰ï¼Œå»ºè­°æ‚¨èƒ½åŒæ„在 menu.lst 裡先"
+"以 chainload çš„æ–¹å¼å•Ÿå‹• GRUB 2,以確èªæ–°çš„ GRUB 2 設定能正常é‹ä½œã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:2001
+msgid ""
+"Whatever your decision, you can replace the old MBR image with GRUB 2 later "
+"by issuing the following command as root:"
+msgstr ""
+"ä¸ç®¡æ‚¨çš„決定為何,您å¯ä»¥éš¨æ™‚讓 GRUB 2 å–代舊有的 MBR å½±åƒæª”利用 root 身份執行"
+"以下指令:"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid "GRUB install devices:"
+msgstr "GRUB 安è£è£ç½®ï¼š"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"The grub-pc package is being upgraded. This menu allows you to select which "
+"devices you'd like grub-install to be automatically run for, if any."
+msgstr ""
+"grub-pc 套件正在å‡ç´šã€‚這個é¸å–®è®“您é¸æ“‡ grub-install è¦åœ¨å“ªä¸€å€‹è£ç½®ä¸Šè‡ªå‹•åŸ·"
+"行,如果有的話。"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001
+msgid ""
+"Running grub-install automatically is recommended in most situations, to "
+"prevent the installed GRUB core image from getting out of sync with GRUB "
+"modules or grub.cfg."
+msgstr ""
+"在大多情æ³ä¸‹å»ºè­°è‡ªå‹•åŸ·è¡Œ grub-installï¼Œä»¥å¿…å… GRUB 核心影åƒå’Œ GRUB 模組或 "
+"grub.cfg 拖步。"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"If you're unsure which drive is designated as boot drive by your BIOS, it is "
+"often a good idea to install GRUB to all of them."
+msgstr ""
+"如果您ä¸ç¢ºå®š BIOS 用哪個ç£ç¢Ÿä½œç‚ºé–‹æ©Ÿç£ç¢Ÿï¼Œé€šå¸¸å®‰è£ GRUB 到所有ç£ç¢Ÿæ˜¯å€‹ä¸éŒ¯çš„"
+"é¸æ“‡ã€‚"
+
+#. Type: multiselect
+#. Description
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:3001 ../grub-pc.templates.in:4001
+msgid ""
+"Note: it is possible to install GRUB to partition boot records as well, and "
+"some appropriate partitions are offered here. However, this forces GRUB to "
+"use the blocklist mechanism, which makes it less reliable, and therefore is "
+"not recommended."
+msgstr ""
+"注æ„:也å¯ä»¥å°‡ GRUB 安è£åˆ°åˆ†å‰²çš„開機記錄,這裡也æ供了一些é©ç•¶çš„分割é¸é …。但"
+"是,GRUB 將被迫使用黑å單機制,導致å¯é æ€§é™ä½Žï¼Œå› æ­¤ä¸å»ºè­°ä½¿ç”¨ã€‚"
+
+#. Type: multiselect
+#. Description
+#: ../grub-pc.templates.in:4001
+msgid ""
+"The GRUB boot loader was previously installed to a disk that is no longer "
+"present, or whose unique identifier has changed for some reason. It is "
+"important to make sure that the installed GRUB core image stays in sync with "
+"GRUB modules and grub.cfg. Please check again to make sure that GRUB is "
+"written to the appropriate boot devices."
+msgstr ""
+"GRUB 的開機程å¼å…ˆå‰å®‰è£åˆ°ä¸€å€‹æ¶ˆå¤±çš„ç£ç¢Ÿä¸Šï¼Œæˆ–者它的唯一標識符因æŸç¨®åŽŸå› æ”¹è®Šã€‚"
+"確ä¿å®‰è£çš„ GRUB 核心映åƒå’Œ GRUB æ¨¡çµ„åŠ grub.cfg çš„åŒæ­¥æ˜¯éžå¸¸é‡è¦çš„。請å†æ¬¡æª¢"
+"æŸ¥ä»¥ç¢ºä¿ GRUB 安è£åˆ°é©ç•¶çš„é–‹æ©Ÿè£ç½®ã€‚"
+
+#. Type: text
+#. Description
+#. Disk sizes are in decimal megabytes, to match how disk manufacturers
+#. usually describe them.
+#: ../grub-pc.templates.in:5001
+msgid "${DEVICE} (${SIZE} MB; ${MODEL})"
+msgstr "${DEVICE} (${SIZE} MB; ${MODEL})"
+
+#. Type: text
+#. Description
+#. The "-" is used to indicate indentation. Leading spaces may not work.
+#: ../grub-pc.templates.in:6001
+msgid "- ${DEVICE} (${SIZE} MB; ${PATH})"
+msgstr "- ${DEVICE} (${SIZE} MB; ${PATH})"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid "Writing GRUB to boot device failed - continue?"
+msgstr "å°‡ GRUB 寫入開機è£ç½®å¤±æ•—了。是å¦ç¹¼çºŒï¼Ÿ"
+
+#. Type: boolean
+#. Description
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001 ../grub-pc.templates.in:8001
+msgid "GRUB failed to install to the following devices:"
+msgstr "在將 GRUB 安è£è‡³ä»¥ä¸‹è£ç½®æ™‚失敗了:"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:7001
+msgid ""
+"Do you want to continue anyway? If you do, your computer may not start up "
+"properly."
+msgstr "是å¦ç„¡è«–如何ä»ç„¶ç¹¼çºŒï¼Ÿä½†é€™æ¨£è©±ï¼Œæ‚¨çš„電腦å¯èƒ½æœƒç„¡æ³•æ­£å¸¸é–‹æ©Ÿã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid "Writing GRUB to boot device failed - try again?"
+msgstr "å°‡ GRUB 寫入開機è£ç½®å¤±æ•—了。å†è©¦ä¸€æ¬¡ï¼Ÿ"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:8001
+msgid ""
+"You may be able to install GRUB to some other device, although you should "
+"check that your system will boot from that device. Otherwise, the upgrade "
+"from GRUB Legacy will be canceled."
+msgstr ""
+"您也許å¯ä»¥æŠŠ GRUB 安è£è‡³å…¶å®ƒçš„è£ç½®ï¼Œåªæ˜¯æ‚¨å¾—設定好您的系統會從該è£ç½®é–‹æ©Ÿã€‚å¦"
+"則,將中止 GRUB Legacy çš„å‡ç´šã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid "Continue without installing GRUB?"
+msgstr "是å¦ä¸å®‰è£ GRUB 並繼續?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"You chose not to install GRUB to any devices. If you continue, the boot "
+"loader may not be properly configured, and when this computer next starts up "
+"it will use whatever was previously in the boot sector. If there is an "
+"earlier version of GRUB 2 in the boot sector, it may be unable to load "
+"modules or handle the current configuration file."
+msgstr ""
+"您決定了ä¸å°‡ GRUB 安è£è‡³ä»»ä½•è£ç½®ã€‚如果您繼續,開機程å¼å¯èƒ½æœªç¶“é©ç•¶å¾—設定,且"
+"當您電腦下次開機時,它會使用原本就ä½æ–¼é–‹æ©Ÿç£å€ä¸Šçš„æ±è¥¿ï¼Œè€Œé€™å¯èƒ½æœƒå°Žè‡³æ¨¡çµ„ç„¡"
+"法載入,或是無法處ç†ç›®å‰æ‰€ä½¿ç”¨çš„設定檔。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:9001
+msgid ""
+"If you are already using a different boot loader and want to carry on doing "
+"so, or if this is a special environment where you do not need a boot loader, "
+"then you should continue anyway. Otherwise, you should install GRUB "
+"somewhere."
+msgstr ""
+"如果您已在使用其它的開機程å¼ï¼Œä¸¦ä¸”打算繼續使用;或是您的環境å分特殊所以ä¸éœ€"
+"è¦é–‹æ©Ÿç¨‹å¼ï¼Œæ‚¨å¯ä»¥ä¸åœ¨æ„並繼續進行。å¦å‰‡ï¼Œæ‚¨æ‡‰ç•¶æ‰¾å€‹åœ°æ–¹å®‰è£ GRUB。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Remove GRUB 2 from /boot/grub?"
+msgstr "是å¦å°‡ GRUB 2 從 /boot/grub 移除?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid "Do you want to have all GRUB 2 files removed from /boot/grub?"
+msgstr "您是å¦æƒ³å°‡æ‰€æœ‰ GRUB 2 的檔案從 /boot/grub 移除?"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:10001
+msgid ""
+"This will make the system unbootable unless another boot loader is installed."
+msgstr "除éžå®‰è£å¦ä¸€å€‹é–‹æ©Ÿç¨‹å¼ï¼Œå¦å‰‡å°‡æœƒé€ æˆç³»çµ±ç„¡æ³•é–‹æ©Ÿã€‚"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid "Finish conversion to GRUB 2 now?"
+msgstr "是å¦è¦çµæŸ GRUB 2 的轉æ›éŽç¨‹ï¼Ÿ"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"This system still has files from the GRUB Legacy boot loader installed, but "
+"it now also has GRUB 2 boot records installed on these disks:"
+msgstr ""
+"這個系統上ä»ä¿æœ‰ä¹‹å‰å®‰è£ GRUB Legacy 所éºç•™ä¸‹ä¾†çš„檔案,但它已有 GRUB 2 安è£æ–¼"
+"以下ç£ç¢Ÿçš„é–‹æ©Ÿç£å€ï¼š"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"It seems likely that GRUB Legacy is no longer in use, and that you should "
+"instead upgrade the GRUB 2 images on these disks and finish the conversion "
+"to GRUB 2 by removing old GRUB Legacy files. If you do not upgrade these "
+"GRUB 2 images, then they may be incompatible with the new packages and cause "
+"your system to stop booting properly."
+msgstr ""
+"這很å¯èƒ½è¡¨ç¤ºå†ä¹Ÿç”¨ä¸åˆ° GRUB Legacy 了,您應該替而å‡ç´šé€™äº›è£ç½®ä¸Šçš„ GRUB 2 å½±åƒ"
+"檔,並移除這些 GRUB Legacy 所éºç•™ä¸‹ä¾†çš„檔案,以çµæŸ GRUB 2 的轉æ›éŽç¨‹ã€‚如果您"
+"æ²’å‡ç´šé€™äº› GRUB 2 å½±åƒæª”的話,它們å¯èƒ½å’Œæ–°çš„套件ä¸ç›¸å®¹ï¼Œä¸”會導致您的系統無法"
+"正常開機。"
+
+#. Type: boolean
+#. Description
+#: ../grub-pc.templates.in:11001
+msgid ""
+"You should generally finish the conversion to GRUB 2 unless these boot "
+"records were created by a GRUB 2 installation on some other operating system."
+msgstr ""
+"您應當é€æ¼¸å¾—çµæŸ GRUB 2 的轉æ›éŽç¨‹ï¼Œé™¤éžé€™äº›é–‹æ©Ÿè¨˜éŒ„是由其它的作業系統所安è£"
+"的 GRUB 2 建立的。"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid "Linux command line:"
+msgstr "Linux 命令列:"
+
+#. Type: string
+#. Description
+#: ../templates.in:1001
+msgid ""
+"The following Linux command line was extracted from /etc/default/grub or the "
+"`kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"以下的 Linux 命令列是由 /etc/default/grub,或是由 GRUB Legacy 的 menu.lst 中"
+"çš„ `kopt' åƒæ•¸æ‰€æ“·å–出來的。請確èªå®ƒæ˜¯å¦æ­£ç¢ºï¼Œè‹¥æœ‰å¿…è¦è«‹åŠ ä»¥ä¿®æ”¹ã€‚此命令列å¯"
+"以留空。"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid "Linux default command line:"
+msgstr "Linux é è¨­å‘½ä»¤åˆ—:"
+
+#. Type: string
+#. Description
+#: ../templates.in:2001
+msgid ""
+"The following string will be used as Linux parameters for the default menu "
+"entry but not for the recovery mode."
+msgstr ""
+"以下的字串將會用在é è¨­çš„é¸å–®é …目中åšç‚º Linux åƒæ•¸ï¼Œä½†ä¸æœƒç”¨æ–¼å›žå¾©æ¨¡å¼ã€‚"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid "Force extra installation to the EFI removable media path?"
+msgstr "強制é¡å¤–的安è£åˆ° EFI å¯ç§»å‹•åª’體的路徑?"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:3001
+msgid ""
+"Some EFI-based systems are buggy and do not handle new bootloaders "
+"correctly. If you force an extra installation of GRUB to the EFI removable "
+"media path, this should ensure that this system will boot Debian correctly "
+"despite such a problem. However, it may remove the ability to boot any other "
+"operating systems that also depend on this path. If so, you will need to "
+"make sure that GRUB is configured successfully to be able to boot any other "
+"OS installations correctly."
+msgstr ""
+"一些基於 EFI 的系統是ä¸ç©©å®šçš„,無法正確處ç†æ–°çš„引導程åºã€‚如果強制é¡å¤–å®‰è£ "
+"GRUB 到å¯ç§»å‹• EFI 媒體路徑,應該å¯ä»¥ç¢ºä¿é€™å€‹ç³»çµ±å°‡æ­£å¸¸å•Ÿå‹• Debian。但是,它å¯"
+"能會移除其它需è¦é€™å€‹è·¯å¾‘的作業系統的啟動能力。如果是這樣,您需è¦ç¢ºä¿ GRUB 設"
+"定æˆåŠŸï¼Œé€™æ¨£å…¶å®ƒçš„作業系統æ‰èƒ½æ­£å¸¸é–‹æ©Ÿã€‚"
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid "Update NVRAM variables to automatically boot into Debian?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:4001
+msgid ""
+"GRUB can configure your platform's NVRAM variables so that it boots into "
+"Debian automatically when powered on. However, you may prefer to disable "
+"this behavior and avoid changes to your boot configuration. For example, if "
+"your NVRAM variables have been set up such that your system contacts a PXE "
+"server on every boot, this would preserve that behavior."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid "Run os-prober automatically to detect and boot other OSes?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"GRUB can use the os-prober tool to attempt to detect other operating systems "
+"on your computer and add them to its list of boot options automatically."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../templates.in:5001
+msgid ""
+"If your computer has multiple operating systems installed, then this is "
+"probably what you want. However, if your computer is a host for guest OSes "
+"installed via LVM or raw disk devices, running os-prober can cause damage to "
+"those guest OSes as it mounts filesystems to look for things."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid "kFreeBSD command line:"
+msgstr "kFreeBSD 命令列:"
+
+#. Type: string
+#. Description
+#: ../templates.in:6001
+msgid ""
+"The following kFreeBSD command line was extracted from /etc/default/grub or "
+"the `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is "
+"correct, and modify it if necessary. The command line is allowed to be empty."
+msgstr ""
+"以下的 kFreeBSD 命令列是由 /etc/default/grub,或是由 GRUB Legacy 的 menu.lst "
+"中的 `kopt' åƒæ•¸æ‰€æ“·å–出來的。請確èªå®ƒæ˜¯å¦æ­£ç¢ºï¼Œè‹¥æœ‰å¿…è¦è«‹åŠ ä»¥ä¿®æ”¹ã€‚此命令列"
+"å¯ä»¥ç•™ç©ºã€‚"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid "kFreeBSD default command line:"
+msgstr "kFreeBSD é è¨­å‘½ä»¤åˆ—:"
+
+#. Type: string
+#. Description
+#: ../templates.in:7001
+msgid ""
+"The following string will be used as kFreeBSD parameters for the default "
+"menu entry but not for the recovery mode."
+msgstr ""
+"以下的字串將會用在é è¨­çš„é¸å–®é …目中åšç‚º kFreeBSD åƒæ•¸ï¼Œä½†ä¸æœƒç”¨æ–¼å›žå¾©æ¨¡å¼ã€‚"
+
+#~ msgid "/boot/grub/device.map has been regenerated"
+#~ msgstr "å·²é‡æ–°ç”¢ç”Ÿ /boot/grub/device.map"
+
+#~ msgid ""
+#~ "The file /boot/grub/device.map has been rewritten to use stable device "
+#~ "names. In most cases, this should significantly reduce the need to change "
+#~ "it in future, and boot menu entries generated by GRUB should not be "
+#~ "affected."
+#~ msgstr ""
+#~ "/boot/grub/device.map 這個檔案已使用ä¸è®Šçš„è£ç½®å稱é‡æ–°å¯«å…¥ã€‚在大多數的狀æ³"
+#~ "之下,如此å¯ä»¥æœ‰æ•ˆå¾—é¿å…在日後還會有什麼變動,且也ä¸æœƒå½±éŸ¿åˆ° GRUB 所產生的"
+#~ "é¸å–®é …目。"
+
+#~ msgid ""
+#~ "However, since more than one disk is present in the system, it is "
+#~ "possible that the system is depending on the old device map. Please check "
+#~ "whether there are any custom boot menu entries that rely on GRUB's (hdN) "
+#~ "drive numbering, and update them if necessary."
+#~ msgstr ""
+#~ "但由於您的系統上ä¸åªå®‰è£äº†ä¸€é¡†ç¡¬ç¢Ÿï¼ŒèˆŠçš„è£ç½®å°æ‡‰è¡¨å¯èƒ½é‚„在使用中。請檢視您"
+#~ "是å¦æœ‰é‚„在使用著 GRUB çš„ (hdN) ç£ç¢Ÿå‘½åè¦å‰‡çš„自訂開機項目,若有必è¦è«‹åŠ ä»¥"
+#~ "更新。"
+
+#~ msgid ""
+#~ "If you do not understand this message, or if there are no custom boot "
+#~ "menu entries, you can ignore this message."
+#~ msgstr ""
+#~ "如果您ä¸äº†è§£é€™äº›è¨Šæ¯ï¼Œæˆ–著沒有任何自訂的開機項目,您å¯ä»¥å¿½ç•¥é€™å€‹è¨Šæ¯ã€‚"
+
+#~ msgid ""
+#~ "In either case, whenever you want GRUB 2 to be loaded directly from MBR, "
+#~ "you can do so by issuing (as root) the following command:"
+#~ msgstr ""
+#~ "ä¸ç®¡æ‚¨è¦æŽ¡å–何種方å¼ï¼Œç•¶æ‚¨æƒ³è®“ GRUB 2 å¯ä»¥ç”± MBR 直接啟動的話,您å¯ä»¥ï¼ˆä»¥ "
+#~ "root 身份)執行以下的指令:"
+
+#~ msgid "GRUB installation failed. Continue?"
+#~ msgstr "GRUB 安è£å¤±æ•—了。是å¦ç¹¼çºŒï¼Ÿ"
diff --git a/debian/postinst.in b/debian/postinst.in
new file mode 100644
index 0000000..68f635b
--- /dev/null
+++ b/debian/postinst.in
@@ -0,0 +1,796 @@
+#!/bin/bash
+set -e
+
+# Apply a sed expression using extended regular expressions in place to a
+# file, if it exists. The file is the first argument in order to work
+# neatly with apply_conf_tweaks.
+sed_conf()
+{
+ if [ -e "$1" ]; then
+ sed -i -re "$2" "$1"
+ fi
+}
+
+# Substitute a debconf answer into a configuration file with the syntax of
+# /etc/default/grub.
+merge_debconf_into_conf()
+{
+ local tmpfile; tmpfile="$1"
+ local setting; setting="$2"
+ local template; template="$3"
+
+ db_get "$template"
+ local value; value="$(echo "$RET" | sed -e 's,[$`"\],\\&,g')"
+ if grep -q "^${setting}=" "$tmpfile"; then
+ value="$(echo "$value" | sed -e 's,[\@],\\&,g')"
+ sed -i -re "s@^(${setting}=).*@\1\"${value}\"@" "$tmpfile"
+ else
+ echo >> "$tmpfile"
+ echo "${setting}=\"${value}\"" >> "$tmpfile"
+ fi
+}
+
+# Apply the same configuration tweak to multiple files.
+apply_conf_tweaks()
+{
+ local files; files="$1"
+ local cmd; cmd="$2"
+ local file
+ shift 2
+
+ for file in $files; do
+ if [ -e "$file" ]; then
+ "$cmd" "$file" "$@"
+ fi
+ done
+}
+
+get_wubi_device()
+{
+ if [ ! -x /usr/share/lupin-support/grub-mkimage ] || \
+ ! /usr/share/lupin-support/grub-mkimage --test; then
+ return 1
+ fi
+
+ local bootdev="$(grub-probe --target=device /boot)" || true
+ local loop_file=
+ case $bootdev in
+ /dev/loop/*|/dev/loop[0-9])
+ loop_file="$(losetup "$bootdev" | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/")"
+ # If it's loop-mounted from another device, it isn't Wubi.
+ case $loop_file in
+ /dev/*) return 1 ;;
+ esac
+ ;;
+ *) return 1 ;;
+ esac
+
+ echo "$bootdev"
+}
+
+# This only works on a Linux system with udev running. This is probably the
+# vast majority of systems where we need any of this, though, and we fall
+# back reasonably gracefully if we don't have it.
+cached_available_ids=
+available_ids()
+{
+ local id path
+
+ if [ "$cached_available_ids" ]; then
+ echo "$cached_available_ids"
+ return
+ fi
+
+ [ -d /dev/disk/by-id ] || return
+ cached_available_ids="$(
+ for path in /dev/disk/by-id/*; do
+ [ -e "$path" ] || continue
+ printf '%s %s\n' "$path" "$(readlink -f "$path")"
+ done | sort -k2 -s -u | cut -d' ' -f1
+ )"
+ echo "$cached_available_ids"
+}
+
+# Returns non-zero and no output if no mapping can be found.
+device_to_id()
+{
+ local id
+ for id in $(available_ids); do
+ if [ "$(readlink -f "$id")" = "$(readlink -f "$1")" ]; then
+ echo "$id"
+ return 0
+ fi
+ done
+ # Fall back to the plain device name if there's no by-id link for it.
+ if [ -e "$1" ]; then
+ echo "$1"
+ return 0
+ fi
+ return 1
+}
+
+all_disks()
+{
+ local id
+ for id in $(available_ids); do
+ case $id in
+ *-part*) ;;
+ *) echo "$id" ;;
+ esac
+ done
+}
+
+all_partitions()
+{
+ local id ids
+ ids=
+ for id in $(available_ids); do
+ if [ "$id" != "$1" ] && [ "${id%-part*}" = "$1" ]; then
+ ids="${ids:+$ids }$id"
+ fi
+ done
+ echo "$ids"
+}
+
+# In order to determine whether we accidentally ran grub-install without
+# upgrade-from-grub-legacy on versions older than 1.98+20100617-1, we need
+# to be able to scan a disk to determine whether GRUB 2 was installed in its
+# boot sector. This is specific to i386-pc (but that's the only platform
+# where we need it).
+scan_grub2()
+{
+ if ! dd if="$1" bs=512 count=1 2>/dev/null | grep -aq GRUB; then
+ # No version of GRUB is installed.
+ return 1
+ fi
+
+ # The GRUB boot sector always starts with a JMP instruction.
+ initial_jmp="$(dd if="$1" bs=2 count=1 2>/dev/null | od -Ax -tx1 | \
+ head -n1 | cut -d' ' -f2,3)"
+ [ "$initial_jmp" ] || return 1
+ initial_jmp_opcode="${initial_jmp%% *}"
+ [ "$initial_jmp_opcode" = eb ] || return 1
+ initial_jmp_operand="${initial_jmp#* }"
+ case $initial_jmp_operand in
+ 47|4b|4c|63)
+ # I believe this covers all versions of GRUB 2 up to the package
+ # version where we gained a more explicit mechanism. GRUB Legacy
+ # always had 48 here.
+ return 0
+ ;;
+ esac
+
+ return 1
+}
+
+# for Linux
+sysfs_size()
+{
+ local num_sectors sector_size size
+ # Try to find out the size without relying on a partitioning tool being
+ # installed. This isn't too hard on Linux 2.6 with sysfs, but we have to
+ # try a couple of variants on detection of the sector size.
+ if [ -e "$1/size" ]; then
+ num_sectors="$(cat "$1/size")"
+ sector_size=512
+ if [ -e "$1/queue/logical_block_size" ]; then
+ sector_size="$(cat "$1/queue/logical_block_size")"
+ elif [ -e "$1/queue/hw_sector_size" ]; then
+ sector_size="$(cat "$1/queue/hw_sector_size")"
+ fi
+ size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
+ fi
+ [ "$size" ] || size='???'
+ echo "$size"
+}
+
+# for kFreeBSD
+camcontrol_size()
+{
+ local num_sectors sector_size size=
+
+ if num_sectors="$(camcontrol readcap "$1" -q -s -N)"; then
+ sector_size="$(camcontrol readcap "$1" -q -b)"
+ size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
+ fi
+
+ [ "$size" ] || size='???'
+ echo "$size"
+}
+
+maybe_udevadm()
+{
+ if command -v udevadm >/dev/null 2>&1; then
+ udevadm "$@" || true
+ fi
+}
+
+# Returns value in $RET, like a debconf command.
+describe_disk()
+{
+ local disk id sysfs_path disk_basename size model
+ disk="$1"
+ id="$2"
+
+ model=
+ case $(uname -s) in
+ Linux)
+ sysfs_path="$(maybe_udevadm info -n "$disk" -q path)"
+ if [ -z "$sysfs_path" ]; then
+ sysfs_path="/block/$(printf %s "${disk#/dev/}" | sed 's,/,!,g')"
+ fi
+ size="$(sysfs_size "/sys$sysfs_path")"
+
+ model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^ID_MODEL=//p')"
+ if [ -z "$model" ]; then
+ model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^DM_NAME=//p')"
+ if [ -z "$model" ]; then
+ model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^MD_NAME=//p')"
+ if [ -z "$model" ] && command -v dmsetup >/dev/null 2>&1; then
+ model="$(dmsetup info -c --noheadings -o name "$disk" 2>/dev/null || true)"
+ fi
+ fi
+ fi
+ ;;
+ GNU/kFreeBSD)
+ disk_basename=$(basename "$disk")
+ size="$(camcontrol_size "$disk_basename")"
+ model="$(camcontrol inquiry "$disk_basename" | sed -ne "s/^pass0: <\([^>]*\)>.*/\1/p")"
+ ;;
+ esac
+
+ [ "$model" ] || model='???'
+
+ db_subst grub-pc/disk_description DEVICE "$disk"
+ db_subst grub-pc/disk_description SIZE "$size"
+ db_subst grub-pc/disk_description MODEL "$model"
+ db_metaget grub-pc/disk_description description
+}
+
+# Returns value in $RET, like a debconf command.
+describe_partition()
+{
+ local disk part id path sysfs_path diskbase partbase size
+ disk="$1"
+ part="$2"
+ id="$3"
+ path="$4"
+
+ sysfs_path="$(maybe_udevadm info -n "$part" -q path)"
+ if [ -z "$sysfs_path" ]; then
+ diskbase="${disk#/dev/}"
+ diskbase="$(printf %s "$diskbase" | sed 's,/,!,g')"
+ partbase="${part#/dev/}"
+ partbase="$(printf %s "$partbase" | sed 's,/,!,g')"
+ sysfs_path="/block/$diskbase/$partbase"
+ fi
+ size="$(sysfs_size "/sys$sysfs_path")"
+
+ db_subst grub-pc/partition_description DEVICE "$part"
+ db_subst grub-pc/partition_description SIZE "$size"
+ db_subst grub-pc/partition_description PATH "$path"
+ db_metaget grub-pc/partition_description description
+}
+
+usable_partitions()
+{
+ local last_partition path partition partition_id
+
+ last_partition=
+ for path in / /boot /boot/grub; do
+ partition="$(grub-probe -t device "$path" || true)"
+ if [ -z "$partition" ] || [ "$partition" = "$last_partition" ]; then
+ continue
+ fi
+ partition_id="$(device_to_id "$partition" || true)"
+ echo "$path:$partition_id"
+ last_partition="$partition"
+ done | sort -t: -k2
+}
+
+get_mountpoint()
+{
+ local relpath boot_mountpoint
+
+ relpath="$(grub-mkrelpath "$1")"
+ boot_mountpoint="${1#$relpath}"
+ echo "${boot_mountpoint:-/}"
+}
+
+config_item()
+{
+ for x in /etc/default/grub /etc/default/grub.d/*.cfg; do
+ if [ -e "$x" ]; then
+ # Lose any output here so we don't confuse our
+ # caller. The xen packages echo stuff here, Aargh!
+ . "$x" > /dev/null
+ fi
+ done
+ if [ "$(eval echo "\${$1+set}")" = set ]; then
+ eval echo "\$$1"
+ else
+ return
+ fi
+}
+
+running_in_container()
+{
+ type systemd-detect-virt >/dev/null 2>&1 && systemd-detect-virt --quiet --container
+}
+
+no_nvram_arg() {
+ db_get grub2/update_nvram
+ if [ "$RET" = false ]; then
+ echo "--no-nvram"
+ fi
+}
+
+run_grub_install()
+{
+ if ! grub-install $@ ; then
+ echo "Failed: grub-install $@" >&2
+ echo "WARNING: Bootloader is not properly installed, system may not be bootable" >&2
+ fi
+}
+
+case "$1" in
+ configure)
+ . /usr/share/debconf/confmodule
+
+ devicemap_regenerated=
+
+ if egrep -q '^[[:space:]]*post(inst|rm)_hook[[:space:]]*=[[:space:]]*(/sbin/|/usr/sbin/)?update-grub' /etc/kernel-img.conf 2>/dev/null; then
+ echo 'Removing update-grub hooks from /etc/kernel-img.conf in favour of' >&2
+ echo '/etc/kernel/ hooks.' >&2
+ sed -ri /etc/kernel-img.conf -e '\%^[[:space:]]*post(inst|rm)_hook[[:space:]]*=[[:space:]]*(/sbin/|/usr/sbin/)?update-grub%d'
+ fi
+
+ mkdir -p /boot/grub
+
+ case @PACKAGE@ in
+ grub-pc)
+ if test -e /boot/grub/device.map && ! test -e /boot/grub/core.img && \
+ ! test -e /boot/grub/@FIRST_CPU_PLATFORM@/core.img; then
+ # Looks like your device.map was generated by GRUB Legacy, which
+ # used to generate broken device.map (see #422851). Avoid the risk
+ # by regenerating it.
+ grub-mkdevicemap --no-floppy
+ devicemap_regenerated=1
+ fi
+ ;;
+ esac
+
+ if test -z "$devicemap_regenerated" && \
+ dpkg --compare-versions "$2" lt-nl 1.99~20101210-2 && \
+ grep -qs /md-uuid- /boot/grub/device.map; then
+ echo "Removing MD devices from device.map, since the BIOS cannot read from these." >&2
+ sed -i '/\/md-uuid-/d' /boot/grub/device.map
+ fi
+
+ tmp_default_grub="$(mktemp -t grub.XXXXXXXXXX)"
+ trap "rm -f ${tmp_default_grub}" EXIT
+ cp -p /usr/share/grub/default/grub ${tmp_default_grub}
+
+ # Apply configuration from debconf to both the template configuration
+ # file (so that any ucf conflict resolution is shown with the configured
+ # values in place) and to /etc/default/grub (in order that debconf
+ # changes are effective even if we have to use UCF_FORCE_CONFFOLD=1).
+ #
+ # The config script takes care to read current values from
+ # /etc/default/grub before possibly prompting the user to change them,
+ # so this should comply with policy's strictures on configuration file
+ # handling: the debconf prompts constitute an explicit administrator
+ # request to change the configuration file.
+ #
+ # If the administrator changes their answers to any of these debconf
+ # questions in the same run as a change to the template, then they'll
+ # get a spurious ucf conflict. To fix this, we'd need to keep track of
+ # the old answers, substitute the old answers into $tmp_default_grub,
+ # and substitute the new answers into /etc/default/grub. Fortunately,
+ # debconf won't normally ask these questions again during an upgrade, so
+ # this should be rare in practice.
+
+ conf_files="$tmp_default_grub /etc/default/grub"
+
+ apply_conf_tweaks "$conf_files" merge_debconf_into_conf GRUB_CMDLINE_LINUX grub2/linux_cmdline
+ apply_conf_tweaks "$conf_files" merge_debconf_into_conf GRUB_CMDLINE_LINUX_DEFAULT grub2/linux_cmdline_default
+
+ # Horrible stuff here, as the os-prober option is a negative
+ # setting (GRUB_DISABLE_OS_PROBER). To not confuse people with
+ # double negative questions in templates, invert it here.
+ db_get grub2/enable_os_prober
+ if [ "$RET" = false ]; then
+ # enable == false -> put in place the commented-out default
+ # #GRUB_DISABLE_OS_PROBER=false that we ship with
+ apply_conf_tweaks "$conf_files" sed_conf 's/^.*GRUB_DISABLE_OS_PROBER.*$/#GRUB_DISABLE_OS_PROBER=false/'
+ else
+ # enable == true -> put in place a valid GRUB_DISABLE_OS_PROBER=false
+ apply_conf_tweaks "$conf_files" sed_conf 's/^.*GRUB_DISABLE_OS_PROBER.*$/GRUB_DISABLE_OS_PROBER=false/'
+ fi
+
+ case @PACKAGE@ in
+ grub-pc)
+ apply_conf_tweaks "$conf_files" merge_debconf_into_conf GRUB_TIMEOUT grub-pc/timeout
+ apply_conf_tweaks "$conf_files" sed_conf 's/^(GRUB_TIMEOUT=)"([0-9][0-9]*)"/\1\2/'
+ db_get grub-pc/hidden_timeout
+ if [ "$RET" = false ]; then
+ apply_conf_tweaks "$conf_files" sed_conf 's/^GRUB_HIDDEN_TIMEOUT=/#&/'
+ fi
+ ;;
+ esac
+
+ # If the template configuration file hasn't changed, then no conflict is
+ # possible. ucf can't figure this out for itself since we apply
+ # debconf-based customisations on top of the template configuration
+ # file.
+ if [ -e /var/lib/grub/ucf/grub.previous ] && \
+ cmp -s /usr/share/grub/default/grub /var/lib/grub/ucf/grub.previous && \
+ [ -e /etc/default/grub ]; then
+ ucf_env=UCF_FORCE_CONFFOLD=1
+ else
+ ucf_env=
+ fi
+
+ env $ucf_env ucf --three-way --debconf-ok --sum-file=/usr/share/grub/default/grub.md5sum "$tmp_default_grub" /etc/default/grub
+ cp -aZ /usr/share/grub/default/grub /var/lib/grub/ucf/grub.previous
+ package="$(ucfq --with-colons /etc/default/grub | cut -d : -f 2)"
+ if echo $package | grep -q "^grub-" ; then
+ ucfr --force @PACKAGE@ /etc/default/grub
+ else
+ ucfr @PACKAGE@ /etc/default/grub
+ fi
+
+ case @PACKAGE@ in
+ grub-pc)
+
+ fix_mixed_system=
+ if test -e /boot/grub/stage2 && test -e /boot/grub/menu.lst && \
+ ! test -e /boot/grub/grub2-installed && \
+ test -z "$UPGRADE_FROM_GRUB_LEGACY"; then
+ # Unfortunately, it's still possible that the user upgraded fully
+ # to GRUB 2 in some way other than running
+ # upgrade-from-grub-legacy; perhaps they ran grub-install by hand
+ # for some reason. It's really quite difficult to detect this
+ # situation, because the only difference between this and a
+ # working chainloaded setup is that in this case grub-setup has
+ # been run. So, to try to tell the difference, we scan the boot
+ # sectors of all disks for a GRUB 2 boot sector. Hopefully this
+ # won't cause too much to explode, since I can't think of a better
+ # method.
+ grub2_disks=
+ for disk in $(all_disks); do
+ if scan_grub2 "$disk"; then
+ grub2_disks="${grub2_disks:+$grub2_disks }$(readlink -f "$disk")"
+ fi
+ done
+ if [ "$grub2_disks" ]; then
+ # No || true here; it's vital that the user sees this, and it's
+ # better to throw an error than to do the wrong thing.
+ db_subst grub-pc/mixed_legacy_and_grub2 DISKS "$grub2_disks"
+ db_fset grub-pc/mixed_legacy_and_grub2 seen false
+ db_input critical grub-pc/mixed_legacy_and_grub2
+ db_go
+ db_get grub-pc/mixed_legacy_and_grub2
+ if [ "$RET" = true ]; then
+ db_reset grub-pc/install_devices
+ UPGRADE_FROM_GRUB_LEGACY=1
+ fix_mixed_system=1
+ # Fall through to normal installation logic.
+ fi
+ fi
+ fi
+
+ # Make sure that Wubi users never see confusing device prompts.
+ # Wubi is a very specialised hack that does complicated things with
+ # grub-install diversions to create an image that's chained from the
+ # Windows boot loader to boot an operating system from a file on a
+ # Windows file system. In these circumstances, prompting for where
+ # to install GRUB is not going to help anyone.
+ wubi_device="$(get_wubi_device)" || true
+ if [ "$wubi_device" ]; then
+ db_set grub-pc/install_devices "$wubi_device"
+ db_fset grub-pc/install_devices seen true
+ fi
+
+ if test -e /boot/grub/stage2 && test -e /boot/grub/menu.lst && \
+ ! test -e /boot/grub/grub2-installed && \
+ test -z "$UPGRADE_FROM_GRUB_LEGACY"; then
+ db_get grub-pc/chainload_from_menu.lst
+ if $RET ; then
+ # Create core.img (but do not risk writing to MBR).
+ # Using grub-probe instead of "(hd0)" avoids (UUID=) hack slowness
+ # in case /boot/grub is not on (hd0) in device.map.
+ echo "Generating core.img" >&2
+ grub-install --target=i386-pc --no-floppy --grub-setup=/bin/true "$(grub-probe -t drive /boot/grub)" > /dev/null
+
+ # Update menu.lst to reflect that:
+ # - core.img is present now
+ # - core.img has to be the first option
+ echo "Saving menu.lst backup in /boot/grub/menu.lst_backup_by_grub2_postinst" >&2
+ cp /boot/grub/menu.lst{,_backup_by_grub2_postinst}
+ echo "Running update-grub Legacy to hook our core.img in it" >&2
+ LET_US_TRY_GRUB_2=true /usr/lib/grub-legacy/update-grub 2>&1 | sed -e "s/^/ /g" >&2
+ # We just hooked GRUB 2 in menu.lst; then also generate grub.cfg.
+ touch /boot/grub/grub.cfg
+ fi
+ elif running_in_container; then
+ # Skip grub-install in containers.
+ :
+ elif test -e /boot/grub/core.img || \
+ test -e /boot/grub/@FIRST_CPU_PLATFORM@/core.img || \
+ test "$UPGRADE_FROM_GRUB_LEGACY" || test "$wubi_device"; then
+ question=grub-pc/install_devices
+ priority=high
+ device_map="$(grub-mkdevicemap -m - | grep -v '^(fd[0-9]\+)' || true)"
+ devices="$(echo "$device_map" | cut -f2)"
+ db_get grub-pc/install_devices
+ valid=1
+ for device in $RET; do
+ if [ ! -e "${device%,}" ]; then
+ valid=0
+ break
+ fi
+ done
+ if [ "$valid" = 0 ]; then
+ question=grub-pc/install_devices_disks_changed
+ priority=critical
+ db_set "$question" "$RET"
+ db_fset "$question" seen false
+ db_fset grub-pc/install_devices_empty seen false
+ fi
+
+ while :; do
+ ids=
+ descriptions=
+ partitions="$(usable_partitions)"
+ for device in $devices; do
+ disk_id="$(device_to_id "$device" || true)"
+ if [ "$disk_id" ]; then
+ ids="${ids:+$ids, }$disk_id"
+ describe_disk "$(readlink -f "$device")" "$disk_id"
+ RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
+ descriptions="${descriptions:+$descriptions, }$RET"
+ for partition_pair in $partitions; do
+ partition_id="${partition_pair#*:}"
+ if [ "${partition_id#$disk_id-part}" != "$partition_id" ]; then
+ ids="${ids:+$ids, }$partition_id"
+ describe_partition "$(readlink -f "$device")" "$(readlink -f "$partition_id")" "$partition_id" "$(get_mountpoint "${partition_pair%%:*}")"
+ RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
+ descriptions="${descriptions:+$descriptions, }$RET"
+ fi
+ done
+ fi
+ done
+ # Some "partitions" may in fact be at the disk level, e.g. RAID.
+ # List these as well if they haven't already been listed.
+ for partition_pair in $partitions; do
+ partition_id="${partition_pair#*:}"
+ if [ "${partition_id#*-part}" = "$partition_id" ]; then
+ case ", $ids, " in
+ ", $partition_id, ") ;;
+ *)
+ ids="${ids:+$ids, }$partition_id"
+ describe_disk "$(readlink -f "$partition_id")" "$partition_id"
+ RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
+ descriptions="${descriptions:+$descriptions, }$RET"
+ ;;
+ esac
+ fi
+ done
+ db_subst "$question" RAW_CHOICES "$ids"
+ db_subst "$question" CHOICES "$descriptions"
+ db_input "$priority" "$question" || true
+ db_go
+ db_get "$question"
+ failed_devices=
+ echo "@PACKAGE@: Running grub-install ..."
+ for i in $RET; do
+ real_device="$(readlink -f "${i%,}")"
+ if [ ! -e "$real_device" ]; then
+ echo "$real_device does not exist, so cannot grub-install to it!" >&2
+ failed_devices="$failed_devices $real_device"
+ else
+ if grub-install --target=i386-pc --force --no-floppy $real_device ; then
+ echo " grub-install success for $real_device"
+ # We just installed GRUB 2; then also generate grub.cfg.
+ touch /boot/grub/grub.cfg
+ else
+ echo " grub-install failure for $real_device"
+ failed_devices="$failed_devices $real_device"
+ fi
+ fi
+ done
+
+ if [ "$question" != grub-pc/install_devices ] && [ "$RET" ]; then
+ # XXX cjwatson 2019-02-26: The description of
+ # grub-pc/install_devices_disks_changed ought to explain that
+ # selecting no devices will leave the configuration unchanged
+ # so that you'll be prompted again next time, but it's a bit
+ # close to the Debian 10 release to be introducing new
+ # translatable text. For now, it should be sufficient to
+ # avoid losing configuration data.
+ db_set grub-pc/install_devices "$RET"
+ db_fset grub-pc/install_devices seen true
+ fi
+
+ if [ "$failed_devices" ]; then
+ if [ "$UPGRADE_FROM_GRUB_LEGACY" ]; then
+ db_subst grub-pc/install_devices_failed_upgrade FAILED_DEVICES "$failed_devices"
+ db_fset grub-pc/install_devices_failed_upgrade seen false
+ if db_input critical grub-pc/install_devices_failed_upgrade; then
+ db_go
+ db_get grub-pc/install_devices_failed_upgrade
+ if [ "$RET" = true ]; then
+ db_fset "$question" seen false
+ db_fset grub-pc/install_devices_failed_upgrade seen false
+ continue
+ else
+ exit 1
+ fi
+ else
+ echo "You must correct your GRUB install devices before proceeding:" >&2
+ echo >&2
+ echo " DEBIAN_FRONTEND=dialog dpkg --configure grub-pc" >&2
+ echo " dpkg --configure -a" >&2
+ exit 1 # noninteractive
+ fi
+ else
+ db_subst grub-pc/install_devices_failed FAILED_DEVICES "$failed_devices"
+ db_fset grub-pc/install_devices_failed seen false
+ if db_input critical grub-pc/install_devices_failed; then
+ db_go
+ db_get grub-pc/install_devices_failed
+ if [ "$RET" = true ]; then
+ break
+ else
+ db_fset "$question" seen false
+ db_fset grub-pc/install_devices_failed seen false
+ continue
+ fi
+ else
+ echo "You must correct your GRUB install devices before proceeding:" >&2
+ echo >&2
+ echo " DEBIAN_FRONTEND=dialog dpkg --configure grub-pc" >&2
+ echo " dpkg --configure -a" >&2
+ exit 1 # noninteractive
+ fi
+ fi
+ fi
+
+ db_get "$question"
+ if [ -z "$RET" ]; then
+ # Reset the seen flag if the current answer is false, since
+ # otherwise we'll loop with no indication of why.
+ db_get grub-pc/install_devices_empty
+ if [ "$RET" = false ]; then
+ db_fset grub-pc/install_devices_empty seen false
+ fi
+ if db_input critical grub-pc/install_devices_empty; then
+ db_go
+ db_get grub-pc/install_devices_empty
+ if [ "$RET" = true ]; then
+ break
+ else
+ db_fset "$question" seen false
+ db_fset grub-pc/install_devices_empty seen false
+ fi
+ else
+ db_get grub-pc/install_devices_empty
+ if [ "$RET" = true ]; then
+ break
+ else
+ echo "You must correct your GRUB install devices before proceeding:" >&2
+ echo >&2
+ echo " DEBIAN_FRONTEND=dialog dpkg --configure grub-pc" >&2
+ echo " dpkg --configure -a" >&2
+ exit 1 # noninteractive
+ fi
+ fi
+ else
+ break
+ fi
+ done
+ fi
+
+ # /boot/grub/ has more chances of being accessible by GRUB
+ for i in /usr/share/grub/unicode.pf2 ; do
+ if test -e $i ; then
+ cp $i /boot/grub/
+ fi
+ done
+
+ if [ "$fix_mixed_system" ]; then
+ # These never contain any valuable information, and they aren't
+ # useful for boot any more, since we just overwrote MBR/PBR.
+ rm -f /boot/grub/{{xfs,reiserfs,e2fs,fat,jfs,minix}_stage1_5,stage{1,2}}
+ # Remove marker file used to indicate that grub-install was run
+ # rather than upgrade-from-grub-legacy. Since stage2 has been
+ # removed, we don't need this any more.
+ rm -f /boot/grub/grub2-installed
+ fi
+ ;;
+
+ grub-efi-ia32|grub-efi-amd64|grub-efi-ia64|grub-efi-arm|grub-efi-arm64)
+ bootloader_id="$(config_item GRUB_DISTRIBUTOR | tr A-Z a-z | \
+ cut -d' ' -f1)"
+ case $bootloader_id in
+ kubuntu) bootloader_id=ubuntu ;;
+ devuan) bootloader_id=debian ;;
+ esac
+ if [ "$bootloader_id" ] && [ -d "/boot/efi/EFI/$bootloader_id" ]; then
+ case @PACKAGE@ in
+ grub-efi-ia32) target=i386-efi ;;
+ grub-efi-amd64) target=x86_64-efi ;;
+ grub-efi-ia64) target=ia64-efi ;;
+ grub-efi-arm) target=arm-efi ;;
+ grub-efi-arm64) target=arm64-efi ;;
+ esac
+ db_get grub2/force_efi_extra_removable
+ if [ "$RET" = true ]; then
+ FORCE_EXTRA_REMOVABLE="--force-extra-removable"
+ fi
+ NO_NVRAM="$(no_nvram_arg)"
+ run_grub_install --target="$target" "$FORCE_EXTRA_REMOVABLE" "$NO_NVRAM"
+ fi
+
+ # /boot/grub/ has more chances of being accessible by GRUB
+ for i in /usr/share/grub/unicode.pf2 ; do
+ if test -e $i ; then
+ cp $i /boot/grub/
+ fi
+ done
+
+ if type update-secureboot-policy >/dev/null 2>&1; then
+ update-secureboot-policy || true
+ fi
+ ;;
+
+ grub-ieee1275)
+ case $(dpkg --print-architecture) in
+ powerpc|ppc64|ppc64el)
+ # Output may be empty; if so, just update the core image but
+ # don't install it to any PReP partition.
+ prep_bootdev="$(/usr/lib/grub/powerpc-ieee1275/prep-bootdev)"
+ NO_NVRAM="$(no_nvram_arg)"
+ run_grub_install --target=powerpc-ieee1275 $prep_bootdev "$NO_NVRAM"
+ ;;
+ esac
+ ;;
+
+ grub-yeeloong)
+ run_grub_install --target=mipsel-loongson
+ ;;
+
+ grub-xen)
+ # Install for x86_64 regardless of arch, since a 32-bit userspace can still boot with a 64-bit kernel.
+ mkdir -p /boot/xen
+ run_grub_install --target=x86_64-xen
+ case $(dpkg --print-architecture) in
+ i386)
+ run_grub_install --target=i386-xen
+ ;;
+ esac
+ # Similarly, the PVH boot loader is usable regardless of arch.
+ run_grub_install --target=i386-xen_pvh
+ ;;
+ esac
+
+ # If grub.cfg has been generated, update it.
+ if test -e /boot/grub/grub.cfg && ! running_in_container; then
+ update-grub 3>&-
+ fi
+ ;;
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/postrm.in b/debian/postrm.in
new file mode 100644
index 0000000..018dba8
--- /dev/null
+++ b/debian/postrm.in
@@ -0,0 +1,66 @@
+#!/bin/sh
+set -e
+
+case "$1" in
+ purge)
+ rm -f /etc/default/grub
+
+ if command -v ucf >/dev/null ; then
+ ucf --purge /etc/default/grub
+ fi
+ if command -v ucfr >/dev/null ; then
+ ucfr --purge @PACKAGE@ /etc/default/grub || true
+ fi
+ rm -f /var/lib/grub/ucf/grub.previous
+
+ case @PACKAGE@ in
+ grub-pc)
+ # debconf could have been purged
+ if [ -e /usr/share/debconf/confmodule ] ; then
+ . /usr/share/debconf/confmodule
+ fi
+
+ db_input high grub-pc/postrm_purge_boot_grub || true
+ db_go || true
+ db_get grub-pc/postrm_purge_boot_grub || true
+ if [ "$RET" = "true" ] ; then
+ rm -f /boot/grub/grub.cfg \
+ /boot/grub/ascii.pf2 \
+ /boot/grub/unicode.pf2 \
+ /boot/grub/moreblue-orbit-grub.png \
+ /boot/grub/*.mod \
+ /boot/grub/*.lst \
+ /boot/grub/*.img \
+ /boot/grub/efiemu32.o \
+ /boot/grub/efiemu64.o \
+ /boot/grub/device.map \
+ /boot/grub/grubenv \
+ /boot/grub/installed-version \
+ /boot/grub/.background_cache.jpeg \
+ /boot/grub/.background_cache.png \
+ /boot/grub/.background_cache.tga || true
+ rm -rf /boot/grub/locale
+ rmdir --ignore-fail-on-non-empty /boot/grub || true
+ fi
+ ;;
+
+ grub-efi-ia32|grub-efi-amd64)
+ rm -f /boot/grub/unicode.pf2
+ ;;
+ esac
+
+ ;;
+ remove|upgrade|failed-upgrade|abort-upgrade|abort-install)
+ ;;
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/preinst.in b/debian/preinst.in
new file mode 100644
index 0000000..9d67cec
--- /dev/null
+++ b/debian/preinst.in
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+
+case "$1" in
+ install|upgrade)
+ if dpkg --compare-versions "$2" lt 1.98+20100804-2 && \
+ test -h /etc/kernel/postrm.d/zz-update-grub; then
+ rm -f /etc/kernel/postrm.d/zz-update-grub
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/prep-bootdev.c b/debian/prep-bootdev.c
new file mode 100644
index 0000000..700a486
--- /dev/null
+++ b/debian/prep-bootdev.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <parted/parted.h>
+
+int
+main(int argc, char *argv[])
+{
+ PedDevice *dev;
+
+ ped_exception_fetch_all();
+ ped_device_probe_all();
+ for (dev = ped_device_get_next(NULL); dev;
+ dev = ped_device_get_next(dev)) {
+ PedDisk *disk;
+ PedPartition *part;
+
+ disk = ped_disk_new(dev);
+ if (!disk)
+ continue;
+
+ for (part = ped_disk_next_partition(disk, NULL); part;
+ part = ped_disk_next_partition(disk, part)) {
+ if (ped_partition_is_active(part) &&
+ ped_partition_get_flag(part, PED_PARTITION_PREP)) {
+ char *path;
+
+ path = ped_partition_get_path(part);
+ if (path) {
+ printf("%s\n", path);
+ free(path);
+ return 0;
+ }
+ free(path);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..d974316
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,589 @@
+#!/usr/bin/make -f
+SHELL := bash
+
+deb_version := $(shell dpkg-parsechangelog | sed -ne "s/^Version: \(.*\)/\1/p")
+upstream_version := $(shell echo $(deb_version) | sed -e "s/-[^-]*$$//")
+
+package := grub2
+
+DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH 2>/dev/null)
+DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS 2>/dev/null)
+DEB_HOST_ARCH_CPU ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_CPU 2>/dev/null)
+
+export DEB_BUILD_MAINT_OPTIONS = optimize=-lto
+
+HOST_CPPFLAGS := $(shell dpkg-buildflags --get CPPFLAGS)
+# -O3 (default on Ubuntu ppc64el) introduces various -Werror failures, and
+# isn't worth it here.
+HOST_CFLAGS := -Wall -Wno-error=unused-result $(shell dpkg-buildflags --get CFLAGS | perl -pe 's/-O3\b/-O2/')
+HOST_LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS)
+
+export DEB_HOST_ARCH
+export HOST_CPPFLAGS
+export HOST_CFLAGS
+export HOST_LDFLAGS
+export TARGET_CPPFLAGS := -Wno-unused-but-set-variable
+export TARGET_LDFLAGS := -no-pie
+
+# Ensure that debhelper doesn't try to set these; we need to be careful
+# about HOST_* vs. TARGET_*.
+export CPPFLAGS :=
+export CFLAGS :=
+export LDFLAGS :=
+
+ifeq (,$(shell command -v qemu-system-i386))
+with_check := no
+else
+with_check := yes
+endif
+
+CC := gcc-12
+
+confflags = \
+ PACKAGE_VERSION="$(deb_version)" PACKAGE_STRING="GRUB $(deb_version)" \
+ CC=$(CC) TARGET_CC=$(CC) \
+ --libdir=\$${prefix}/lib --libexecdir=\$${prefix}/lib \
+ --enable-grub-mkfont \
+ --disable-grub-emu-usb
+substvars =
+
+AUTOGEN_DEB_FILES = config templates preinst postinst postrm dirs install links maintscript bash-completion
+
+BUILD_PACKAGES := $(strip $(shell dh_listpackages))
+# REAL_PACKAGES build an actual grub variant (and therefore have both configure
+# and build stages). EXTRA_PACKAGES do not build grub but may depend on a
+# REAL_PACKAGE (and therefore only have a build stage)
+REAL_PACKAGES = grub-common grub-emu grub-pc grub-coreboot grub-efi-ia32 grub-efi-amd64 grub-efi-ia64 grub-efi-arm grub-efi-arm64 grub-ieee1275 grub-firmware-qemu grub-uboot grub-xen grub-yeeloong
+EXTRA_PACKAGES = grub-rescue-pc grub-xen-host
+
+ifneq (,$(filter i386 amd64,$(DEB_HOST_ARCH_CPU)))
+COMMON_PLATFORM := pc
+else ifneq (,$(filter powerpc ppc64 ppc64el sparc sparc64,$(DEB_HOST_ARCH_CPU)))
+COMMON_PLATFORM := ieee1275
+else ifeq (mipsel,$(DEB_HOST_ARCH_CPU))
+COMMON_PLATFORM := yeeloong
+else ifeq (ia64,$(DEB_HOST_ARCH_CPU))
+COMMON_PLATFORM := efi-ia64
+else ifeq (arm,$(DEB_HOST_ARCH_CPU))
+COMMON_PLATFORM := uboot
+else ifeq (arm64,$(DEB_HOST_ARCH_CPU))
+COMMON_PLATFORM := efi-arm64
+else
+COMMON_PLATFORM := none
+BUILD_PACKAGES += grub-none
+endif
+
+ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes))
+DEFAULT_CMDLINE := quiet splash
+DEFAULT_TIMEOUT := 10
+ifeq ($(DEB_HOST_ARCH_CPU),ppc64el)
+FLICKER_FREE_BOOT := no
+else
+FLICKER_FREE_BOOT := yes
+endif
+confflags += --enable-ubuntu-recovery
+else ifeq (yes,$(shell dpkg-vendor --derives-from Tanglu && echo yes))
+DEFAULT_CMDLINE := quiet splash
+DEFAULT_TIMEOUT := 10
+FLICKER_FREE_BOOT := yes
+else
+DEFAULT_CMDLINE := quiet
+DEFAULT_TIMEOUT := 5
+FLICKER_FREE_BOOT := no
+endif
+
+ifeq ($(FLICKER_FREE_BOOT),yes)
+DEFAULT_HIDDEN_TIMEOUT := 0
+DEFAULT_HIDDEN_TIMEOUT_BOOL := true
+confflags += \
+ --enable-quiet-boot \
+ --enable-quick-boot \
+ --enable-gfxpayload-dynamic \
+ --enable-vt-handoff
+substvars += \
+ -Vlsb-base-depends="lsb-base (>= 3.0-6)" \
+ -Vgfxpayload-depends="grub-gfxpayload-lists [any-i386 any-amd64]"
+else
+DEFAULT_HIDDEN_TIMEOUT :=
+DEFAULT_HIDDEN_TIMEOUT_BOOL := false
+endif
+
+# Secure Boot
+debian/stamps/build-grub-efi-ia32 install/grub-efi-ia32: export SB_PLATFORM := i386-efi
+debian/stamps/build-grub-efi-ia32 install/grub-efi-ia32: export SB_EFI_NAME := ia32
+debian/stamps/build-grub-efi-amd64 install/grub-efi-amd64: export SB_PLATFORM := x86_64-efi
+debian/stamps/build-grub-efi-amd64 install/grub-efi-amd64: export SB_EFI_NAME := x64
+debian/stamps/build-grub-efi-arm64 install/grub-efi-arm64: export SB_PLATFORM := arm64-efi
+debian/stamps/build-grub-efi-arm64 install/grub-efi-arm64: export SB_EFI_NAME := aa64
+SB_PACKAGE :=
+ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes))
+ifeq ($(DEB_HOST_ARCH),amd64)
+SB_PACKAGE := grub-efi-amd64
+endif
+ifeq ($(DEB_HOST_ARCH),arm64)
+SB_PACKAGE := grub-efi-arm64
+endif
+endif
+
+# Downstream distributions that want to support SB and build images, but do not
+# rebuild grub, need a programmatic way to get the vendor, as it's used by build-efi-images
+# to create the monolithic Grub image and thus is needed to create the partitions on the EFI
+# media. Add it to the control file user metadata: XB-Efi-Vendor: $vendor
+SB_EFI_VENDOR ?= $(shell dpkg-vendor --query vendor | tr '[:upper:]' '[:lower:]')
+
+%:
+ dh $@ --with=bash_completion
+
+override_dh_auto_configure: $(patsubst %,configure/%,$(BUILD_PACKAGES))
+
+override_dh_auto_build: $(patsubst %,build/%,$(BUILD_PACKAGES))
+
+override_dh_auto_install: $(patsubst %,install/%,$(BUILD_PACKAGES))
+
+$(patsubst %,configure/%,$(REAL_PACKAGES)) :: configure/% : debian/stamps/configure-%
+$(patsubst %,build/%,$(REAL_PACKAGES) $(EXTRA_PACKAGES)) :: build/% : debian/stamps/build-%
+
+debian/stamps/configure-%: package = $(subst debian/stamps/configure-,,$@)
+debian/stamps/configure-%: export DH_OPTIONS = -p$(package) -Bobj/$(package)
+
+debian/stamps/build-%: package = $(subst debian/stamps/build-,,$@)
+debian/stamps/build-%: export DH_OPTIONS = -p$(package) -Bobj/$(package)
+
+install/%: package = $(subst install/,,$@)
+install/%: package_bin = $(package)-bin
+install/%: package_dbg = $(package)-dbg
+install/grub-emu: package_bin = grub-emu
+install/grub-emu: package_dbg = grub-emu-dbg
+install/%: export DH_OPTIONS = -p$(package) -Bobj/$(patsubst grub-common,grub-$(COMMON_PLATFORM),$(package))
+
+override_dh_autoreconf:
+ mkdir -p debian/stamps
+ rm -rf debian/grub-extras-enabled
+ mkdir debian/grub-extras-enabled
+ set -e; for extra in 915resolution ntldr-img; do \
+ cp -a debian/grub-extras/$$extra debian/grub-extras-enabled/; \
+ done
+ env -u DH_OPTIONS GRUB_CONTRIB=$(CURDIR)/debian/grub-extras-enabled \
+ PYTHON=python3 \
+ dh_autoreconf -- ./autogen.sh
+
+debian/stamps/configure-grub-common: debian/stamps/configure-grub-$(COMMON_PLATFORM)
+ touch $@
+
+debian/stamps/build-grub-common: debian/stamps/build-grub-$(COMMON_PLATFORM)
+ touch $@
+
+debian/stamps/configure-grub-none debian/stamps/configure-grub-pc debian/stamps/configure-grub-ieee1275 debian/stamps/configure-grub-coreboot debian/stamps/configure-grub-emu debian/stamps/configure-grub-uboot debian/stamps/configure-grub-yeeloong:
+ mkdir -p debian/stamps obj/$(package)
+ dh_auto_configure -- $(confflags) --with-platform=$(subst grub-,,$(package))
+ touch $@
+
+# This name scheme leaves room for things like amd32 someday
+debian/stamps/configure-grub-efi-ia32:
+ mkdir -p debian/stamps obj/$(package)
+ dh_auto_configure -- $(confflags) --with-platform=efi --target=i386-pe --program-prefix=""
+ touch $@
+debian/stamps/configure-grub-efi-amd64:
+ mkdir -p debian/stamps $(subst debian/stamps/configure-,obj/,$@)
+ dh_auto_configure -- $(confflags) --with-platform=efi --target=amd64-pe --program-prefix=""
+ touch $@
+debian/stamps/configure-grub-efi-ia64 debian/stamps/configure-grub-efi-arm debian/stamps/configure-grub-efi-arm64:
+ mkdir -p debian/stamps $(subst debian/stamps/configure-,obj/,$@)
+ dh_auto_configure -- $(confflags) --with-platform=efi
+ touch $@
+
+debian/stamps/configure-grub-xen-i386 debian/stamps/configure-grub-xen-amd64:
+ mkdir -p debian/stamps obj/$(package)
+ dh_auto_configure -- $(confflags) --with-platform=xen --target=$(subst debian/stamps/configure-grub-xen-,,$@) --program-prefix=""
+ touch $@
+debian/stamps/configure-grub-xen-pvh-i386:
+ mkdir -p debian/stamps obj/$(package)
+ dh_auto_configure -- $(confflags) --with-platform=xen_pvh --target=i386 --program-prefix=""
+ touch $@
+debian/stamps/configure-grub-xen: debian/stamps/configure-grub-xen-i386 debian/stamps/configure-grub-xen-amd64 debian/stamps/configure-grub-xen-pvh-i386
+ touch $@
+
+debian/stamps/configure-grub-firmware-qemu:
+ mkdir -p debian/stamps $(subst debian/stamps/configure-,obj/,$@)
+ dh_auto_configure -- $(confflags) --with-platform=qemu
+ touch $@
+
+debian/stamps/build-grub-none debian/stamps/build-grub-efi-ia64 debian/stamps/build-grub-efi-arm debian/stamps/build-grub-coreboot debian/stamps/build-grub-emu debian/stamps/build-grub-uboot debian/stamps/build-grub-xen-i386 debian/stamps/build-grub-xen-amd64 debian/stamps/build-grub-xen-pvh-i386 debian/stamps/build-grub-yeeloong: debian/stamps/build-%: debian/stamps/configure-%
+ dh_auto_build
+ touch $@
+
+debian/stamps/build-grub-efi-ia32 debian/stamps/build-grub-efi-amd64 debian/stamps/build-grub-efi-arm64: debian/stamps/build-%: debian/stamps/configure-% debian/stamps/build-grub-$(COMMON_PLATFORM)
+ dh_auto_build
+ grub_dir=`mktemp -d` ; \
+ sed -e "s/@DEB_VERSION@/$(deb_version)/g" \
+ -e "s/@UPSTREAM_VERSION@/$(upstream_version)/g" \
+ <debian/sbat.$(SB_EFI_VENDOR).csv.in \
+ >$${grub_dir}/sbat.$(SB_EFI_VENDOR).csv; \
+ debian/build-efi-images \
+ obj/grub-$(COMMON_PLATFORM)/grub-mkimage \
+ obj/$(package)/grub-core \
+ obj/monolithic/$(package) \
+ $(DEB_HOST_ARCH) $(SB_PLATFORM) $(SB_EFI_NAME) \
+ $${grub_dir}/sbat.$(SB_EFI_VENDOR).csv $(SB_EFI_VENDOR)
+ touch $@
+
+debian/stamps/build-grub-xen-host-i386: PVBOOT_ARCH := i386
+debian/stamps/build-grub-xen-host-i386: debian/stamps/build-grub-xen-i386
+debian/stamps/build-grub-xen-host-amd64: PVBOOT_ARCH := x86_64
+debian/stamps/build-grub-xen-host-amd64: debian/stamps/build-grub-xen-amd64
+debian/stamps/build-grub-xen-host-i386 debian/stamps/build-grub-xen-host-amd64:
+ target=$(subst debian/stamps/build-grub-xen-host-,,$@) ; \
+ obj_dir=$(CURDIR)/obj/grub-xen-$${target} ; \
+ grub_dir=`mktemp -d` ; \
+ grub_memdisk=`mktemp` ; \
+ trap "rm -rf $${grub_dir} $${grub_memdisk}" EXIT HUP INT QUIT TERM ; \
+ mkdir -p $${grub_dir}/boot/grub ; \
+ mkdir -p $(CURDIR)/obj/$(package) ; \
+ sed -e "s/@@PVBOOT_ARCH@@/$(PVBOOT_ARCH)/g" \
+ <debian/grub-xen-host_grub.cfg \
+ >$${grub_dir}/grub.cfg ; \
+ tar -cf - -C $${grub_dir} grub.cfg > $${grub_memdisk} ; \
+ $${obj_dir}/grub-mkimage \
+ -O $(PVBOOT_ARCH)-xen \
+ -c $(CURDIR)/debian/grub-xen-host_grub-bootstrap.cfg \
+ -d $${obj_dir}/grub-core \
+ $${obj_dir}/grub-core/*.mod \
+ -m $${grub_memdisk} \
+ -o $(CURDIR)/obj/$(package)/grub-$(PVBOOT_ARCH)-xen.bin
+ touch $@
+
+debian/stamps/build-grub-xen-host-pvh-i386: debian/stamps/build-grub-xen-pvh-i386
+ target=$(subst debian/stamps/build-grub-xen-host-,,$@) ; \
+ obj_dir=$(CURDIR)/obj/grub-xen-$${target} ; \
+ grub_dir=`mktemp -d` ; \
+ grub_memdisk=`mktemp` ; \
+ trap "rm -rf $${grub_dir} $${grub_memdisk}" EXIT HUP INT QUIT TERM ; \
+ mkdir -p $${grub_dir}/boot/grub ; \
+ mkdir -p $(CURDIR)/obj/$(package) ; \
+ cp -a debian/grub-xen-host_grub-pvh.cfg $${grub_dir}/grub.cfg ; \
+ tar -cf - -C $${grub_dir} grub.cfg > $${grub_memdisk} ; \
+ $${obj_dir}/grub-mkimage \
+ -O i386-xen_pvh \
+ -c $(CURDIR)/debian/grub-xen-host_grub-bootstrap.cfg \
+ -d $${obj_dir}/grub-core \
+ $${obj_dir}/grub-core/*.mod \
+ -m $${grub_memdisk} \
+ -o $(CURDIR)/obj/$(package)/grub-i386-xen_pvh.bin
+ touch $@
+
+debian/stamps/build-grub-xen-host: debian/stamps/build-grub-xen-host-i386 debian/stamps/build-grub-xen-host-amd64 debian/stamps/build-grub-xen-host-pvh-i386
+ touch $@
+
+debian/stamps/build-grub-pc: debian/stamps/configure-grub-pc
+ dh_auto_build
+ifeq ($(with_check), yes)
+ LC_MESSAGES=C.UTF-8 LC_CTYPE=C.UTF-8 PATH="$$PATH:/sbin:/usr/sbin" VERBOSE=1 dh_auto_test --max-parallel=1
+endif
+ touch $@
+
+debian/stamps/build-grub-ieee1275: debian/stamps/configure-grub-ieee1275
+ dh_auto_build
+ifneq (,$(filter powerpc ppc64 ppc64el,$(DEB_HOST_ARCH_CPU)))
+ $(CC) $(HOST_CFLAGS) debian/prep-bootdev.c -o debian/prep-bootdev -lparted
+endif
+ touch $@
+
+debian/stamps/build-grub-xen: debian/stamps/build-grub-xen-i386 debian/stamps/build-grub-xen-amd64 debian/stamps/build-grub-xen-pvh-i386
+ touch $@
+
+debian/stamps/build-grub-firmware-qemu: debian/stamps/configure-grub-firmware-qemu
+ dh_auto_build
+ grub_dir=`mktemp -d` ; \
+ grub_memdisk=`mktemp` ; \
+ trap "rm -rf $${grub_dir} $${grub_memdisk}" EXIT HUP INT QUIT TERM ; \
+ mkdir -p $${grub_dir}/boot/grub ; \
+ cp debian/grub-firmware-qemu_grub.cfg $${grub_dir}/boot/grub/grub.cfg ; \
+ tar -cf - -C $${grub_dir} boot > $${grub_memdisk} ; \
+ obj/$(package)/grub-mkimage \
+ -O i386-qemu \
+ -d $(CURDIR)/obj/$(package)/grub-core \
+ $(CURDIR)/obj/$(package)/grub-core/*.mod \
+ -m $${grub_memdisk} \
+ -o $(CURDIR)/obj/$(package)/grub.bin
+ touch $@
+
+debian/stamps/build-grub-rescue-pc: debian/stamps/build-grub-pc
+ mkdir -p obj/grub-rescue-pc/rescue-disk/boot/grub
+ cp docs/grub.cfg obj/grub-rescue-pc/rescue-disk/boot/grub/
+ rm -rf obj/grub-rescue-pc/grub-core
+ cp -a obj/grub-pc/grub-core obj/grub-rescue-pc/grub-core
+ cp -a obj/grub-pc/unicode.pf2 obj/grub-rescue-pc/
+ pkgdatadir=$(CURDIR)/obj/grub-rescue-pc \
+ obj/grub-pc/grub-mkrescue \
+ --directory=$(CURDIR)/obj/grub-rescue-pc/grub-core \
+ --locale-directory=$(CURDIR)/obj/grub-rescue-pc/grub-core/po \
+ --output=$(CURDIR)/obj/grub-rescue-pc/grub-rescue-cdrom.iso \
+ $(CURDIR)/obj/grub-rescue-pc/rescue-disk
+ # save space for floppy image
+ rm -rf obj/grub-rescue-pc/grub-core/po obj/grub-rescue-pc/unicode.pf2
+ pkgdatadir=$(CURDIR)/obj/grub-rescue-pc \
+ obj/grub-pc/grub-mkrescue \
+ --directory=$(CURDIR)/obj/grub-rescue-pc/grub-core \
+ --locale-directory=$(CURDIR)/obj/grub-rescue-pc/grub-core/po \
+ --output=$(CURDIR)/obj/grub-rescue-pc/grub-rescue-floppy.img \
+ --compress=xz \
+ -no-pad \
+ $(CURDIR)/obj/grub-rescue-pc/rescue-disk
+ touch $@
+
+platform_subst = \
+ if [ -e debian/$(1) ]; then \
+ debian/platform-subst \
+ PACKAGE="$(2)" \
+ DEFAULT_CMDLINE="$(DEFAULT_CMDLINE)" \
+ DEFAULT_TIMEOUT="$(DEFAULT_TIMEOUT)" \
+ DEFAULT_HIDDEN_TIMEOUT_BOOL="$(DEFAULT_HIDDEN_TIMEOUT_BOOL)" \
+ debian/$(1) >> debian/$(2).$(3); \
+ fi
+
+install/grub-none:
+ dh_auto_install --destdir=debian/tmp-$(package)
+
+ # Avoid failures later if we're building from a tree with no .po
+ # files.
+ mkdir -p debian/tmp-$(package)/usr/share/locale
+
+install/grub-pc install/grub-efi-ia32 install/grub-efi-amd64 install/grub-efi-ia64 install/grub-efi-arm install/grub-efi-arm64 install/grub-ieee1275 install/grub-coreboot install/grub-emu install/grub-uboot install/grub-xen install/grub-yeeloong:
+ set -e ; \
+ if [ "$@" = "install/grub-xen" ] ; then \
+ dh_auto_install -Bobj/grub-xen-i386 --destdir=debian/tmp-$(package); \
+ dh_auto_install -Bobj/grub-xen-amd64 --destdir=debian/tmp-$(package); \
+ dh_auto_install -Bobj/grub-xen-pvh-i386 --destdir=debian/tmp-$(package); \
+ else \
+ dh_auto_install --destdir=debian/tmp-$(package); \
+ fi
+
+ set -e ; \
+ if [ -d "obj/monolithic/$(package)" ] ; then \
+ install -m 0755 -d debian/$(package_bin)/usr/lib/grub/$(SB_PLATFORM)/monolithic ; \
+ install -m 0644 -t debian/$(package_bin)/usr/lib/grub/$(SB_PLATFORM)/monolithic obj/monolithic/$(package)/*.efi ; \
+ debian/signing-template.generate "$(package)" ; \
+ fi
+
+ set -e ; \
+ for i in $(AUTOGEN_DEB_FILES) ; do \
+ > debian/$(package).$$i; \
+ if [ "$@" != "install/grub-emu" ] ; then \
+ $(call platform_subst,$$i.in,$(package),$$i); \
+ fi ; \
+ $(call platform_subst,$(package).$$i.in,$(package),$$i); \
+ $(call platform_subst,$(package).$$i.$(DEB_HOST_ARCH_CPU).in,$(package),$$i); \
+ $(call platform_subst,$(package).$$i.$(DEB_HOST_ARCH_OS).in,$(package),$$i); \
+ $(call platform_subst,$(package).$$i.$(DEB_HOST_ARCH_OS)-$(DEB_HOST_ARCH_CPU).in,$(package),$$i); \
+ [ -s debian/$(package).$$i ] || rm -f debian/$(package).$$i; \
+ if [ "$@" != "install/grub-emu" ] ; then \
+ > debian/$(package_bin).$$i; \
+ $(call platform_subst,$$i-bin.in,$(package_bin),$$i); \
+ $(call platform_subst,$(package_bin).$$i.in,$(package_bin),$$i); \
+ $(call platform_subst,$(package_bin).$$i.$(DEB_HOST_ARCH_CPU).in,$(package_bin),$$i); \
+ $(call platform_subst,$(package_bin).$$i.$(DEB_HOST_ARCH_OS).in,$(package_bin),$$i); \
+ $(call platform_subst,$(package_bin).$$i.$(DEB_HOST_ARCH_OS)-$(DEB_HOST_ARCH_CPU).in,$(package_bin),$$i); \
+ [ -s debian/$(package_bin).$$i ] || rm -f debian/$(package_bin).$$i; \
+ fi ; \
+ > debian/$(package_dbg).$$i; \
+ if [ "$@" != "install/grub-emu" ] ; then \
+ $(call platform_subst,$$i-dbg.in,$(package_dbg),$$i); \
+ fi ; \
+ $(call platform_subst,$(package_dbg).$$i.in,$(package_dbg),$$i); \
+ $(call platform_subst,$(package_dbg).$$i.$(DEB_HOST_ARCH_CPU).in,$(package_dbg),$$i); \
+ $(call platform_subst,$(package_dbg).$$i.$(DEB_HOST_ARCH_OS).in,$(package_dbg),$$i); \
+ $(call platform_subst,$(package_dbg).$$i.$(DEB_HOST_ARCH_OS)-$(DEB_HOST_ARCH_CPU).in,$(package_dbg),$$i); \
+ [ -s debian/$(package_dbg).$$i ] || rm -f debian/$(package_dbg).$$i; \
+ done
+
+ find debian/tmp-$(package)/usr/lib/grub -name modinfo.sh -print0 | \
+ xargs -0r chmod +x
+ find debian/tmp-$(package)/usr/lib/grub -name gdb_grub -print0 | \
+ xargs -0r chmod -x
+ find debian/tmp-$(package)/usr/lib/grub -name gmodule.pl -print0 | \
+ xargs -0r chmod -x
+
+ mkdir -p debian/$(package_bin)/usr/share/lintian/overrides
+ echo "$(package_bin): unstripped-binary-or-object *.mod" \
+ >> debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin)
+ cd debian/tmp-$(package) && find usr/lib/grub -name kernel.img \
+ | sed -e "s%.*%$(package_bin): statically-linked-binary &%g" \
+ >> $(CURDIR)/debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin)
+ cd debian/tmp-$(package) && find usr/lib/grub -name kernel.img \
+ | sed -e "s%.*%$(package_bin): unstripped-binary-or-object &%g" \
+ >> $(CURDIR)/debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin)
+ if ([ "$@" = "install/grub-efi-amd64" ] && [ "$(DEB_HOST_ARCH_CPU)" = "i386" ]) || \
+ ([ "$@" != "install/grub-emu" ] && [ "$(DEB_HOST_ARCH_CPU):$(DEB_HOST_ARCH_BITS)" = "amd64:32" ]) || \
+ [ "$@" = "install/grub-xen" ]; then \
+ echo "$(package_bin): binary-from-other-architecture *.mod" \
+ >> debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin) ; \
+ cd debian/tmp-$(package) && find usr/lib/grub -name kernel.img \
+ | sed -e "s%.*%$(package_bin): binary-from-other-architecture &%g" \
+ >> $(CURDIR)/debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin) ; \
+ fi
+ if ([ "$@" = "install/grub-pc" ] || \
+ [ "$@" = "install/grub-ieee1275" ] || \
+ [ "$@" = "install/grub-coreboot" ] || \
+ [ "$@" = "install/grub-xen" ] || \
+ [ "$@" = "install/grub-emu" ]) && \
+ [ "$(DEB_HOST_ARCH_OS)" = "linux" ] && \
+ [ "$(DEB_HOST_ARCH_CPU):$(DEB_HOST_ARCH_BITS)" != "amd64:64" ] ; then \
+ echo "$(package_bin): binary-from-other-architecture *efiemu64.o" \
+ >> debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin) ; \
+ fi
+ case $@ in \
+ install/grub-efi*) \
+ (echo "# These aren't Windows executables, and these features wouldn't be very useful." \
+ echo "$(package_bin): portable-executable-missing-security-features *.efi ASLR DEP/NX") \
+ >> debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin) ;; \
+ esac
+ if [ "$@" = "install/grub-emu" ]; then \
+ (echo "# This seems to be due to a readelf bug: https://bugs.debian.org/929585"; \
+ echo "$(package_bin): binary-or-shlib-defines-rpath usr/lib/grub/*-emu/macho.mod 0x0") \
+ >> debian/$(package_bin)/usr/share/lintian/overrides/$(package_bin); \
+ fi
+
+ mkdir -p debian/$(package_dbg)/usr/share/lintian/overrides
+ echo "$(package_dbg): unstripped-binary-or-object *.module" \
+ >> debian/$(package_dbg)/usr/share/lintian/overrides/$(package_dbg)
+ echo "$(package_dbg): statically-linked-binary *.image" \
+ >> debian/$(package_dbg)/usr/share/lintian/overrides/$(package_dbg)
+ cd debian/tmp-$(package) && find usr/lib/grub -name kernel.exec \
+ | sed -e "s%.*%$(package_dbg): statically-linked-binary &%g" \
+ >> $(CURDIR)/debian/$(package_dbg)/usr/share/lintian/overrides/$(package_dbg)
+ if ([ "$@" = "install/grub-efi-amd64" ] && [ "$(DEB_HOST_ARCH_CPU)" = "i386" ]) || \
+ ([ "$@" != "install/grub-emu" ] && [ "$(DEB_HOST_ARCH_CPU):$(DEB_HOST_ARCH_BITS)" = "amd64:32" ]) || \
+ [ "$@" = "install/grub-xen" ] ; then \
+ echo "$(package_dbg): binary-from-other-architecture *.module" \
+ >> debian/$(package_dbg)/usr/share/lintian/overrides/$(package_dbg) ; \
+ cd debian/tmp-$(package) && find usr/lib/grub -name kernel.exec \
+ | sed -e "s%.*%$(package_dbg): binary-from-other-architecture &%g" \
+ >> $(CURDIR)/debian/$(package_dbg)/usr/share/lintian/overrides/$(package_dbg) ; \
+ fi
+
+ # Avoid failures later if we're building from a tree with no .po
+ # files.
+ mkdir -p debian/tmp-$(package)/usr/share/locale
+
+common_subst = \
+ if [ -e debian/grub-common.$(1) ]; then \
+ sed 's/@COMMON_PLATFORM@/$(COMMON_PLATFORM)/g' \
+ debian/grub-common.$(1) >> debian/grub-common.$(2).new; \
+ fi
+
+install/grub-common:
+ set -e ; for i in $(AUTOGEN_DEB_FILES) ; do \
+ > debian/grub-common.$$i.new; \
+ $(call common_subst,$$i.in,$$i); \
+ $(call common_subst,$$i.$(DEB_HOST_ARCH_CPU).in,$$i); \
+ $(call common_subst,$$i.$(DEB_HOST_ARCH_OS).in,$$i); \
+ if [ -s debian/grub-common.$$i.new ] ; then \
+ mv debian/grub-common.$$i.new debian/grub-common.$$i; \
+ else \
+ rm -f debian/grub-common.$$i.new; \
+ fi; \
+ done
+ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes))
+ install -D -m 0755 debian/grub-common.pm-sleep \
+ $(CURDIR)/debian/$(package)/etc/pm/sleep.d/10_grub-common
+endif
+
+NON_PLATFORM_PACKAGES = $(filter grub2 grub-linuxbios grub-efi grub-rescue-pc grub-firmware-qemu grub-xen-host,$(BUILD_PACKAGES))
+COMMON_PLATFORM_PACKAGES = $(filter grub-common grub2-common grub-theme-starfield grub-mount-udeb,$(BUILD_PACKAGES))
+PLATFORM_PACKAGES = $(filter grub-pc grub-efi-ia32 grub-efi-amd64 grub-efi-ia64 grub-efi-arm grub-efi-arm64 grub-ieee1275 grub-coreboot grub-uboot grub-xen grub-yeeloong,$(BUILD_PACKAGES))
+
+override_dh_install:
+ifneq (,$(NON_PLATFORM_PACKAGES))
+ dh_install $(patsubst %,-p%,$(NON_PLATFORM_PACKAGES))
+endif
+ dh_install $(patsubst %,-p%,$(COMMON_PLATFORM_PACKAGES)) --sourcedir=debian/tmp-grub-$(COMMON_PLATFORM)
+ rm -f debian/grub2-common/usr/share/info/dir*
+ rm -f debian/grub-theme-starfield/usr/share/grub/themes/starfield/COPYING.CC-BY-SA-3.0
+ifneq (,$(PLATFORM_PACKAGES))
+ set -e; for package in $(PLATFORM_PACKAGES); do \
+ dh_install -p$$package --sourcedir=debian/tmp-$$package; \
+ dh_install -p$$package-bin --sourcedir=debian/tmp-$$package; \
+ dh_install -p$$package-dbg --sourcedir=debian/tmp-$$package; \
+ done
+endif
+ifneq (,$(filter grub-emu,$(BUILD_PACKAGES)))
+ dh_install -pgrub-emu --sourcedir=debian/tmp-grub-emu
+ dh_install -pgrub-emu-dbg --sourcedir=debian/tmp-grub-emu
+endif
+ifneq (,$(filter grub2-common,$(BUILD_PACKAGES)))
+ sed -i \
+ -e "s/@DEFAULT_CMDLINE@/$(DEFAULT_CMDLINE)/g" \
+ -e "s/@DEFAULT_TIMEOUT@/$(DEFAULT_TIMEOUT)/g" \
+ debian/grub2-common/usr/share/grub/default/grub
+ifneq (,$(DEFAULT_HIDDEN_TIMEOUT))
+ perl -pi -e 's/^GRUB_TIMEOUT=.*/GRUB_HIDDEN_TIMEOUT=0\nGRUB_HIDDEN_TIMEOUT_QUIET=true\n$$&/' \
+ debian/grub2-common/usr/share/grub/default/grub
+endif
+endif
+ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes))
+ifneq (,$(filter grub-pc,$(BUILD_PACKAGES)))
+ patch debian/grub-pc/usr/lib/grub-legacy/update-grub \
+ < debian/legacy/update-grub.ubuntu.patch
+endif
+endif
+
+override_dh_installdocs:
+ dh_installdocs $(patsubst %,-p%,$(filter grub-common grub-rescue-pc grub-firmware-qemu grub-xen-host,$(BUILD_PACKAGES))) -A AUTHORS NEWS README THANKS TODO
+ dh_installdocs $(patsubst %,-p%,$(filter grub-efi-%-signed-template,$(BUILD_PACKAGES)))
+ dh_installdocs --remaining-packages --link-doc=grub-common
+
+ifeq ($(FLICKER_FREE_BOOT),yes)
+override_dh_installinit:
+ dh_installinit -- start 99 2 3 4 5 .
+else
+override_dh_installinit:
+ :
+endif
+
+override_dh_bugfiles:
+ dh_bugfiles $(patsubst %,-N%,$(filter grub-efi-%-signed-template,$(BUILD_PACKAGES))) -A
+
+override_dh_strip:
+ dh_strip -X/usr/bin/grub-emu -X/usr/lib/grub-xen/grub-x86_64-xen.bin -X/usr/lib/grub-xen/grub-i386-xen_pvh.bin -X/usr/lib/grub-xen/grub-i386-xen.bin
+
+override_dh_shlibdeps:
+ dh_shlibdeps -X.module
+
+ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes))
+LEGACY_DOC_BR := grub-doc (<< 0.97-29ubuntu60), grub-legacy-doc (<< 0.97-29ubuntu60)
+else
+LEGACY_DOC_BR := grub-doc (<< 0.97-32), grub-legacy-doc (<< 0.97-59)
+endif
+
+override_dh_gencontrol:
+ dh_gencontrol -- -Vlegacy-doc-br="$(LEGACY_DOC_BR)" -V"efi:Vendor=$(SB_EFI_VENDOR)" $(substvars)
+
+TARNAME := grub2_$(deb_version)_$(DEB_HOST_ARCH).tar.gz
+
+override_dh_builddeb:
+ dh_builddeb
+ifneq (,$(SB_PACKAGE))
+ echo $(deb_version) > obj/monolithic/$(SB_PACKAGE)/version
+ tar -c -f ../$(TARNAME) -a -C obj/monolithic/$(SB_PACKAGE) -v .
+ dpkg-distaddfile $(TARNAME) raw-uefi -
+endif
+
+override_dh_auto_clean:
+ -rm -rf debian/grub-extras-enabled debian/stamps obj
+ -rm -f contrib grub-core/contrib
+
+override_dh_clean:
+ dh_clean
+
+ chmod +x debian/{bug-script,grub.d/*,legacy/*,kernel/*}
+
+ for i in $(AUTOGEN_DEB_FILES) ; do \
+ rm -f debian/grub-{pc,efi-*,ieee1275,coreboot,uboot,xen,yeeloong,emu}{,-bin,-dbg}.$$i ; \
+ done
+ rm -f debian/grub-common.bash-completion debian/grub-common.maintscript
+ rm -rf debian/tmp-*/
+
+ # make sure PO files are always up-to-date
+ debconf-updatepo
+
+.PHONY: $(patsubst %,configure/%,$(BUILD_PACKAGES)) $(patsubst %,build/%,$(BUILD_PACKAGES)) $(patsubst %,install/%,$(BUILD_PACKAGES))
diff --git a/debian/sbat.debian.csv.in b/debian/sbat.debian.csv.in
new file mode 100644
index 0000000..401e51c
--- /dev/null
+++ b/debian/sbat.debian.csv.in
@@ -0,0 +1,3 @@
+sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
+grub,4,Free Software Foundation,grub,@UPSTREAM_VERSION@,https://www.gnu.org/software/grub/
+grub.debian,4,Debian,grub2,@DEB_VERSION@,https://tracker.debian.org/pkg/grub2
diff --git a/debian/signing-template.generate b/debian/signing-template.generate
new file mode 100755
index 0000000..4718eab
--- /dev/null
+++ b/debian/signing-template.generate
@@ -0,0 +1,49 @@
+#!/bin/sh
+set -e -u
+
+pkg_base="${1?:missing binary package name}"
+pkg_unsigned="${pkg_base}-bin"
+pkg_signed="${pkg_base}-signed"
+pkg_tmpl="${pkg_signed}-template"
+
+distribution="$(dpkg-parsechangelog -S Distribution)"
+urgency="$(dpkg-parsechangelog -S Urgency)"
+date="$(dpkg-parsechangelog -S Date)"
+version_binary="$(dpkg-parsechangelog -S Version)"
+version_mangled="$(dpkg-parsechangelog -S Version | tr '-' '+')"
+
+subst () {
+ sed \
+ -e "s/@pkg_unsigned@/${pkg_unsigned}/g" \
+ -e "s/@pkg_signed@/${pkg_signed}/g" \
+ -e "s/@pkg_tmpl@/${pkg_tmpl}/g" \
+ -e "s/@efi@/${SB_EFI_NAME}/g" \
+ -e "s/@efi_platform@/${SB_PLATFORM}/g" \
+ -e "s/@arch@/${DEB_HOST_ARCH}/g" \
+ -e "s/@version_binary@/${version_binary}/g" \
+ -e "s/@version_mangled@/${version_mangled}/g" \
+ -e "s/@distribution@/${distribution}/g" \
+ -e "s/@urgency@/${urgency}/g" \
+ -e "s/@date@/${date}/g" \
+ "$@"
+}
+
+template='./debian/signing-template'
+pkg_dir="debian/${pkg_tmpl}/usr/share/code-signing/${pkg_tmpl}"
+pkg_deb="${pkg_dir}/source-template/debian"
+
+install -m 0755 -d "${pkg_dir}"
+subst < ./debian/signing-template.json.in > "${pkg_dir}/files.json"
+
+find "${template}" -type f -printf '%P\n' |
+while read path
+do
+ src="${template}/${path}"
+ dst="${pkg_deb}/${path}"
+
+ install -m 0755 -d "${dst%/*}"
+ subst < "${src}" > "${dst%.in}"
+ chmod --reference="${src}" "${dst%.in}"
+done
+
+exit 0
diff --git a/debian/signing-template.json.in b/debian/signing-template.json.in
new file mode 100644
index 0000000..bd72396
--- /dev/null
+++ b/debian/signing-template.json.in
@@ -0,0 +1,14 @@
+{
+ "version": "2",
+ "packages": {
+ "@pkg_unsigned@": {
+ "trusted_certs": [],
+ "files": [
+ {"sig_type": "efi", "file": "usr/lib/grub/@efi_platform@/monolithic/gcd@efi@.efi"},
+ {"sig_type": "efi", "file": "usr/lib/grub/@efi_platform@/monolithic/grubnet@efi@.efi"},
+ {"sig_type": "efi", "file": "usr/lib/grub/@efi_platform@/monolithic/grubnet@efi@-installer.efi"},
+ {"sig_type": "efi", "file": "usr/lib/grub/@efi_platform@/monolithic/grub@efi@.efi"}
+ ]
+ }
+ }
+}
diff --git a/debian/signing-template/README.source b/debian/signing-template/README.source
new file mode 100644
index 0000000..116a66b
--- /dev/null
+++ b/debian/signing-template/README.source
@@ -0,0 +1,4 @@
+This source package is generated by the Debian signing service from a
+template built by the grub2 package. It should never be updated directly.
+
+ -- Philipp Matthias Hahn <pmhahn@debian.org> Sat, 07 Apr 2018 16:26:11 +0200
diff --git a/debian/signing-template/bug-control.in b/debian/signing-template/bug-control.in
new file mode 100644
index 0000000..ef95218
--- /dev/null
+++ b/debian/signing-template/bug-control.in
@@ -0,0 +1 @@
+Submit-As: @pkg_unsigned@
diff --git a/debian/signing-template/changelog.in b/debian/signing-template/changelog.in
new file mode 100644
index 0000000..3b4df18
--- /dev/null
+++ b/debian/signing-template/changelog.in
@@ -0,0 +1,11 @@
+@pkg_signed@ (1+@version_mangled@) @distribution@; urgency=@urgency@
+
+ * Update to grub2 @version_binary@
+
+ -- Debian signing service <ftpmaster@debian.org> @date@
+
+@pkg_signed@ (1) unstable; urgency=medium
+
+ * Add template source package for signing
+
+ -- Philipp Matthias Hahn <pmhahn@debian.org> Sat, 07 Apr 2018 17:16:27 +0200
diff --git a/debian/signing-template/compat b/debian/signing-template/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/signing-template/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/signing-template/control.in b/debian/signing-template/control.in
new file mode 100644
index 0000000..cd928c6
--- /dev/null
+++ b/debian/signing-template/control.in
@@ -0,0 +1,28 @@
+Source: @pkg_signed@
+Section: admin
+Priority: optional
+Maintainer: GRUB Maintainers <pkg-grub-devel@alioth-lists.debian.net>
+Uploaders: Felix Zielcke <fzielcke@z-51.de>, Jordi Mallach <jordi@debian.org>, Colin Watson <cjwatson@debian.org>, Ian Campbell <ijc@debian.org>
+Standards-Version: 3.9.8
+Build-Depends: debhelper (>= 10.1~),
+ sbsigntool [amd64 arm64 i386],
+ @pkg_unsigned@ (= @version_binary@),
+Rules-Requires-Root: no
+
+Package: @pkg_signed@
+Architecture: @arch@
+Depends: grub-common (>= @version_binary@)
+Recommends: shim-signed
+Built-Using: grub2 (= @version_binary@)
+Description: GRand Unified Bootloader, version 2 (@arch@ UEFI signed by Debian)
+ GRUB is a portable, powerful bootloader. This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+ - Scripting in grub.cfg using BASH-like syntax.
+ - Support for modern partition maps such as GPT.
+ - Modular generation of grub.cfg via update-grub. Packages providing GRUB
+ add-ons can plug in their own script rules and trigger updates by invoking
+ update-grub.
+ .
+ This package contains the binaries signed by the Debian UEFI CA to be used by
+ shim-signed.
diff --git a/debian/signing-template/copyright b/debian/signing-template/copyright
new file mode 100644
index 0000000..d94e00b
--- /dev/null
+++ b/debian/signing-template/copyright
@@ -0,0 +1,51 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Comment:
+ This file describes only the grub2-signed source package.
+
+Files: debian/signatures/*
+License: public-domain
+ Digital signatures and certificates are presumed not to be
+ copyrightable works, and no copyright is claimed for them.
+Comment:
+ The signatures and certificates in this package cannot be regenerated
+ as-is without the associated private key material, but they can be
+ replaced using alternate private keys.
+
+Files: debian/rules
+Copyright: 2018 Philipp Matthias Hahn <pmhahn@debian.org>
+License: GPL-2
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ .
+ On Debian systems, the complete text of the GNU General Public
+ License version 2 can be found in `/usr/share/common-licenses/GPL-2'.
+
+Files: debian/*
+Copyright: 2018 Philipp Matthias Hahn <pmhahn@debian.org>
+License: GPL-2+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ .
+ On Debian systems, the complete text of the GNU General Public
+ License version 2 can be found in `/usr/share/common-licenses/GPL-2'.
diff --git a/debian/signing-template/rules.in b/debian/signing-template/rules.in
new file mode 100755
index 0000000..fec6ca5
--- /dev/null
+++ b/debian/signing-template/rules.in
@@ -0,0 +1,19 @@
+#!/usr/bin/make -f
+
+SIG_DIR := debian/signatures/@pkg_unsigned@
+
+%:
+ dh $@
+
+override_dh_auto_install:
+ set -e ; \
+ find "$(SIG_DIR)" -name '*.sig' -printf '%P\n' | \
+ while read sig; do \
+ dst="debian/tmp/$${sig%/monolithic/*}-signed/$${sig##*/}ned" ; \
+ install -m 0755 -d "$${dst%/*}" ; \
+ install -m 0644 "/$${sig%.sig}" "$$dst" ; \
+ sbattach --attach "$(SIG_DIR)/$$sig" "$$dst" ; \
+ done
+
+override_dh_install:
+ dh_install --sourcedir=debian/tmp .
diff --git a/debian/signing-template/source/format b/debian/signing-template/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/signing-template/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/include-binaries b/debian/source/include-binaries
new file mode 100644
index 0000000..95a390b
--- /dev/null
+++ b/debian/source/include-binaries
@@ -0,0 +1 @@
+debian/upstream-signing-key.pgp
diff --git a/debian/templates.in b/debian/templates.in
new file mode 100644
index 0000000..ec83fe7
--- /dev/null
+++ b/debian/templates.in
@@ -0,0 +1,65 @@
+Template: grub2/linux_cmdline
+Type: string
+_Description: Linux command line:
+ The following Linux command line was extracted from /etc/default/grub or the
+ `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is correct,
+ and modify it if necessary. The command line is allowed to be empty.
+
+Template: grub2/linux_cmdline_default
+Type: string
+Default: @DEFAULT_CMDLINE@
+_Description: Linux default command line:
+ The following string will be used as Linux parameters for the default menu
+ entry but not for the recovery mode.
+
+Template: grub2/force_efi_extra_removable
+Type: boolean
+Default: false
+_Description: Force extra installation to the EFI removable media path?
+ Some EFI-based systems are buggy and do not handle new bootloaders correctly.
+ If you force an extra installation of GRUB to the EFI removable media path,
+ this should ensure that this system will boot Debian correctly despite such a
+ problem. However, it may remove the ability to boot any other operating
+ systems that also depend on this path. If so, you will need to make sure that
+ GRUB is configured successfully to be able to boot any other OS installations
+ correctly.
+
+Template: grub2/update_nvram
+Type: boolean
+Default: true
+_Description: Update NVRAM variables to automatically boot into Debian?
+ GRUB can configure your platform's NVRAM variables so that it boots into
+ Debian automatically when powered on. However, you may prefer to disable
+ this behavior and avoid changes to your boot configuration. For example,
+ if your NVRAM variables have been set up such that your system contacts a
+ PXE server on every boot, this would preserve that behavior.
+
+Template: grub2/enable_os_prober
+Type: boolean
+Default: false
+_Description: Run os-prober automatically to detect and boot other OSes?
+ GRUB can use the os-prober tool to attempt to detect other
+ operating systems on your computer and add them to its list of boot
+ options automatically.
+ .
+ If your computer has multiple operating systems installed, then this
+ is probably what you want. However, if your computer is a host for
+ guest OSes installed via LVM or raw disk devices, running os-prober
+ can cause damage to those guest OSes as it mounts filesystems to look
+ for things.
+
+# still unused
+Template: grub2/kfreebsd_cmdline
+Type: string
+_Description: kFreeBSD command line:
+ The following kFreeBSD command line was extracted from /etc/default/grub or the
+ `kopt' parameter in GRUB Legacy's menu.lst. Please verify that it is correct,
+ and modify it if necessary. The command line is allowed to be empty.
+
+# still unused
+Template: grub2/kfreebsd_cmdline_default
+Type: string
+Default: @DEFAULT_CMDLINE@
+_Description: kFreeBSD default command line:
+ The following string will be used as kFreeBSD parameters for the default menu
+ entry but not for the recovery mode.
diff --git a/debian/update-grub b/debian/update-grub
new file mode 100644
index 0000000..0c43327
--- /dev/null
+++ b/debian/update-grub
@@ -0,0 +1,3 @@
+#!/bin/sh
+set -e
+exec grub-mkconfig -o /boot/grub/grub.cfg "$@"
diff --git a/debian/update-grub.8 b/debian/update-grub.8
new file mode 100644
index 0000000..b715f87
--- /dev/null
+++ b/debian/update-grub.8
@@ -0,0 +1,14 @@
+.\" Copyright 2009 Felix Zielcke
+.\" Lincensed under GPL3+
+.TH UPDATE-GRUB "8" "April 2009"
+.SH NAME
+update-grub, update-grub2 \- stub for grub-mkconfig
+.SH SYNOPSIS
+.B update-grub
+.SH DESCRIPTION
+.B update-grub
+is a stub for running
+.B grub-mkconfig -o /boot/grub/grub.cfg
+to generate a grub2 config file.
+.SH "SEE ALSO"
+.BR grub-mkconfig (8)
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
new file mode 100644
index 0000000..50fca13
--- /dev/null
+++ b/debian/upstream/metadata
@@ -0,0 +1,4 @@
+---
+Bug-Submit: bug-grub@gnu.org
+Repository: https://git.savannah.gnu.org/git/grub.git
+Repository-Browse: https://git.savannah.gnu.org/cgit/grub.git
diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc
new file mode 100644
index 0000000..207deda
--- /dev/null
+++ b/debian/upstream/signing-key.asc
@@ -0,0 +1,158 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQSuBEr2CLURDACLOWOLoxu6mhBQWRMzGYNgLjjOYT7O+LQSpHda5Zwa5eOzqrJP
+qs08XESLH3CQ3SplSrEyKQE7skWqx6TEC/LmnXHktqXP+MqB4HYJ7bUFqRUWdibq
+aDCuiSHUYQnrNEJYH4Bo9LZ35uXSoPTrzNUavY9dWBUDvm2NGn2yJJ4BDJq+IY3v
+26bHgDdWgcJuuKB876oqtPL/7x58GZ4Kb5rPPcfSVEShGkO6e1T3AWiL/rp80XGi
+gidMwl7h1TCKakiunIhnfcjYeSkEbuQ76IivkjePbyv2Y0j26/cY6SrnTuOyd/6W
+8BjVcadVEfW6GutZQ4HYIMj7R5oFoaGTR1XjBzaQAHY4z/7GJ6pkydmeVDVhUBMF
+12w0blVjAl/qyHB0vx199YH7vgNA/FCXvck5tZAon141CHNQ8/owr7OUY6o4jAnx
+ft7Okmckkrg+UpxHwB77O8F73r4hJACZy3ikEBhwxTRwpH5mXpFMuMvvV9fvN3mM
+X6Kqra+p3sl88bsBAMSIaVyNiDU/tArRtbsKdAuyRcN5azPSc8mptnmiZVWBC/0Z
+Qe9+xKcXwa6/HvplnM/AwewGv/Gw5hZ/8o0VqDezyKzLKLIZfiSdeKLVPPK8rxMW
+3b4InZUPRuEv3Crr3EfgpzQ84FQwgqkuBnxNh9OGeoQaBmoi3WqtKyutxANoeiJo
+m49WuZaVbdgKffH4Wl+OV3AYlFzfJQ7QTaC2YWl4zwjRtrwbIMogiRSRCGhYSkZs
+zQHv+58u2v+lqSAk9rsWgEc6b23iacnxMug9dd4ppS5tPcJ3kdFPavcUUvWv6epr
+i9QVVVrIJyHrNbZPugjL5ZatCjAACtsUn4hMYF7Hl2+cgSwwyfH8K2A+mxeZyKXG
+jVH4mhO/sVRwz+WPunzSv9VeyORQb6MYRZV3EORijxHFkNWZut6kK0VoaFOS5Kxd
+4PfpHQq7gJaKIWVRqrEJ9PmVddmRjjqRBvkAAoaTG4flrZeYvDFjpmkY01a+s7Xy
+qf+bHFa/LSqvpDTPRzPYgujyc8CsqidkAtP5a9f19VQdogbHr+TK8mSX88uzqM0L
+/iDhoL/TapsuLm7ErtrDEIduXIwBJimwsSLWv9r59vDQ4I/tDk8llBw1TTOo9k67
+/fA9U7EgnDwgv5wcyXqt6ri4c4aMlODO+u0VbJkW6N2jYsZt3cTYe7Xev6yyT+OZ
+YWJbKgFdBJs0DsM4riffnxDXL+RiOwd8VMm9M8fWDK9zTAYKaV4RY7RFzUe+TlCv
+fyZKOD7VLPSGGGM1ijpk3FGoVQ6VzFxKb5zmEpkQTirk2DFWUw07uP4seay2Hqm3
+bAaigvr4jx6MxgrL34XPGXqyhEu1mxxffFuypejNRNe9lBzd8V/GYNUqyhZUFX4d
+XjY58kK1gKPin18TCAgmiocAIhP1nxswPpGwfNL0rZUQg7ww/Psw24BfmZos09it
+zOVk0FP7hYuzTz7e0yW4+dPal64wvWcqOIAxEEE+9VPu0fbemN2/sXZ7vmDDuhjZ
+zbylL5Hf7+ASykB2XYxfpSZZGWZarQA9MPynbpxROUmSfNV1DWCP4IZUF0dGueEh
+C7QxVmxhZGltaXIgJ3BoY29kZXInIFNlcmJpbmVua28gPHBoY29kZXJAZ21haWwu
+Y29tPoh/BBMRCgAnAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheABQJRBEVVBQkP
+dD4MAAoJEDWpO3ToLkIJ9jQA/Ao729a6Zx8bN4uF3oCeob/h5wNgylsswydV/pzt
+loJuAP99papmglUEz9iZNbhsGrGQ1lsVtWJCnzVgh/JYAmq89LkDDQRK9gi1EAwA
+t5FNmd1DUqmEIbdnhZB91CbOOZ0kjYy+UMua9zZqD29i7DQofiCLuWKIF3XopLRP
+ZOTXm3XX/RIIbaDN8CmEgyuHwCjC0hMuAhsk5NpFKroi40aYGhNNJ8QKZ4NA4h6+
+ULIQOuHLEKOWAOiXbV+9eZRQxbS5Fm2IKJPmFlb7gkl1nnujLijLjZoioVBbrUlY
+BT5wptM8nKWZJHZbtUg9pedFQf5MGMF2IEOdQq64FMx/jTQplBzKPIThEgooNzDt
+leX1FMx3vVtu9IAKapTnBgO2ywqHYZl6S9F2fCCa2WSowRTTzvhu77kv+dpRnySE
+J9EEwOus6eTl5wMig16fezN5/X+i6NnKM4So65kHOnVJ1Fk8jVACgTlKmntDNcQ/
+xzyr2i7ABdnd3NzBpbpB3DnCwbI1oEHy4oX+Y/D9uF7+DClDZaCtyLctuaca3SeP
+tRXfYpdNg3XG+Noo4KlUBWp/po7O4907zh3uJpXSAyMKhpWcfM1c2TnmvA2N49oD
+AAMFC/91psqlXeiWo9U8+sQlPDPU/CacWpwQfpUoj2KXrjLHf7NGVW2TewuhF9Cm
+7Yc+dqLBhPK7x6SsU3SxdLppvrRVO9f8KDxUd4JFVHvwLnzC7e1uLuLzYWSIDTsc
+PTaauQ1GIy/C6VIBd3ryrlDilKQIHYjMaeUKHll+B168frc5xyybUOAL2+cK6VFe
+pxoi1+sAbapwAL8/AxtR40MJCnYxNtO8EV+MreKbphZy+6xiPsNkTrd5X676VT56
+mm/o7kcGOk2INLMtyhFXU5UbDSb42fXjY4ZbtE4dTTNX5NieWIeLvaaDTbbInnW0
+SDWLOFqRVGLSG4ibc8HGVy0PVO8r9pk2H58t7RVW27oNi/mTsvWY3fjsWUCiQ8rT
+OwI9fReOr6+PamUPnp+XJllkj1/ePGoQF0GyEbEl2j8RPODSYWzUblQE82f6K9Bx
+ti3FEYaiM+OgtjeVJzkpnCpo28WNAi2v7kRV3XxdVRmDguD7ntdYI+7af9fdTKCK
+hKgV7UGIZwQYEQoADwUCSvYItQIbDAUJCWYBgAAKCRA1qTt06C5CCcMYAP46TVLM
+OG1UEWeOqNmrFh7nJU65K/HSt3tMKQygkR1KrAD/fSpRmjC+tLlI2C5sx8/Lo4Z+
+mlSZTporaeX8PHiEe52IZwQYEQoADwIbDAUCUQRFaQUJD3Q+MAAKCRA1qTt06C5C
+CdQRAP901geM4sxNkwH79ujc6+KH2xCNi+XBiSktBGAmA7mztgEAhohh+DiPolE3
+RfpkAFzandp3mUbCogGowQ/GsfWOVyK5Ag0EUnaE9AEQANOdTDnPKEd9NoFmR9LB
+M3G66oPDU4sct3rCSJ/1uWowqCVk2PtYwMkHvLRBGMQhSbhszNs/aElIK/Blfc49
+pjwqWHbMr/wSuz0o+KIjkYc1vosixiIVPhZkkFX9ugKnzQx0CioNJKqQFGn6nK19
+QAvYJFhwjrQFW3Ltj5fRRyYQ56gMbmc1+uuqqJqRekmsJLWylgwcnWwOPPpzKOAY
+oBd7U4bfEwGF7aIaIWWCFQJWwgaSp+43gHPWzMJ2yV8hCkM7nqowX1h+Qe1RztpU
+fq9CVQyus57IFh+GoZOOCNsciC/pbRh3JPlESb1unOVEo7/a5eGh+xSiJX2fr55l
+URGvtPnaA6PONqhgRn2DSFa6sQ0oE4sOoqJnyOOhl78D5yC3midVtVOfe8+pTFM5
+JFfKViR1hZ2WtoMFA7VufE6r4SfeNXTqB64tVTK3maJy7DJOtvPDBsf1dfKAHUdI
+FWY7Po2xhbEGgmTmpQ8Ei8nFX2Em/koPYhjZzo5MIzS+H0i87Jm4Rf4ll3ojUG85
+XJPv0C7e4ejwVhLzJoBxf2SzGbHTPA1AARsr+vyXtUIUCTjVK+BtSKMtfyuUSE0j
+QmUKcQM990qU0f6XM7PQ3HFhaHbsVmZ63ftcXG9WM6Qfb/U5foRSiN0h2Y1pkrmb
+umN6M0LS9Bpzw+va6eXEcx6fABEBAAGJAoAEGBEKAAkFAlJ2hPQCGwICKQkQNak7
+dOguQgnBXSAEGQEKAAYFAlJ2hPQACgkQjzdOBR2HUm8hQxAA0XTMC88+hc1Jfqu/
+16SkP06vgNJQfdpVSHU3zUvCLbTfXcLpuS3+mYNN+hw3NZjlONlV7Y9hVKCI/igB
+eStN7Riav46UL+n/JovNSkRY6q21UxztRPgnD0jPA34SHzPTGSgltDJ7J6+Uk4uC
+i7Qb3P12985lMydt2dnCN+bi9BZwLuIYo021cYYp1l7WXtgZODTzmRCJv9MJEiKH
+k0n4wNsmSWFQ0t+4adqUlvf+Tk8ZALHX5mhmYkfpawxqQ3rJIrCO3DhbBFTyrAG+
+V3aqNEVZgE4QRvc+L9jGkAkPq0O7W8TCJF+Q66C/NQZiFTY3p0riFxZ7GXgfvZKQ
+2E2R/nxN3iJKcnLDg2U4U4MmSxH+2hXuhAWrtQXCTvt2gzH5W0bFV8eu+M1YTOpT
+i71JVVQcgOo5B9IED3skRPU/73bePVlV8G1iCFqH3c5rDvcm5JxyLjl1Ohns28dy
+tCJZXAC3RKoC0pkETHjvLhzBvRcZ7Hha/veyGnX372s5Xr7yBxtwArbhqKMJY9bP
+SIu/hJaMEbKWaId8YKtgzCIYi/tFe80e0o79KUPhwnKUWp8XF01JLHdBTEfc8quC
+Qzsw55zi5VFdosZ1PgwdHPZQj9B1V6dHAZv19jiP2aE8qdyTQsOnGARejTsLIU7s
+0WAx4FYoo9U5pBwFHSfJSXK6rczfEQEAsvoe5D0LWNAXRwxErstJLQFfyO7faQgm
+iFQSDPWyDcMA/j1u485XtKEQf5N08b0698pBYIreG5cYeHStxMolcP96uQSuBFJ2
+im4RDACAQ089lsAbZf597ARjpICjPQgf4B5c9RRtMEGOuhlDqFQhtrF7B0ZiEYrl
+Fd8QLQwCVfrKndWALcxzLayzeGN1f8qBtDGzT8oJ5QgFjCUGT+GQc6F+sqtfVCcS
+K5D2US4Lc/XT/lvi9RrB2D43NeFD9xKCU1lgjiNzlF0LEuRyX4ZpU+sZZtCr3OK7
+HlNvuOd4E2b5W3M0AS46ukQUX5WcqpFSa4rBcIm1If1XrztU57qDtD5iy5sBF/dh
+N27sC9ND8ZgJdq8aDA6oNPNnTNSNvdm4DNhG2s8a19Xc/Gcvk1MDvqKQjVzGBrU5
+Vbu9SAzqUujghwUvXCI6ZC8R4RclcJCGdjtWgYjlWHFYKn2SpDrbLfGTm/IcgWcn
+Shaf/Q/8oiktqn0HX8u9xTIjGggwQyMy3t5ev/pYQjNKWoa6kV14KuURtuAUSYf0
+FSBYSphJmwwLhPjdhDwwbw2OokQy8Q83eLC52PfQSflC3sAU8NkefMsJalr6i3ih
+ADYHx4cBAK+vSoIbPQsqbmpx3mQizrVX11A471EZsxLWr7fG+syNC/9udMIO5aoV
+5eU5YWlBnEsArszBqtzbMMCJqcnaFxefNhJ/dt1YoCe9LDeo1GEuTPJtn/eVykUS
+nev40KP76gWvTVewCA/+IAN6kFApDsVted22vrSTTdRChp2A0At7xttMCGrj2PRw
+i4kFjzyC1G//a2/TQCjd4f83PQPJxXF7QqL0YhrD0E9ZHWPIa5lnAwri+36cmGRl
+iR763JKBQqvdXhjL9qAnS9szMhBdElR81d9B5POFTWH+yC6R9b5b0n7WVnUX6/QC
+xjiQ9plQMNyjghWSC7PFGYKnG7LdPqV0QLTpVQCGHPeZH0JwgBzzCOxSi9/L8kPz
+RK69NqCQkxE/dY+srDd6faGm4jxj84p/k2RlNj7GewKDp8dRbvXHOIm3gTVDk+ix
+H/sycM3d/5eoOtLsHqKrjoU3nnZybeQLOSVVJtjvXdn3IDnkQDV4+LhH1Vl6dlk8
+ZG/DqQQ6X+zIWnTqEKIs/5I+aF1ZWxRMqVnALeEBrY3PY8m/T/P87JkL/1qHxFno
+EG8hVYbwCr2ixnrKmEqBjMMHfePcjKOPJg/N/N7/fXUJAB17QrCJS/5VSK0iEG5R
+Dhugq/QrrFAVjNiQrTndfOBkJ7hdXWKhRR1NfnoEizmmfb1Tlv8DmoMA+V1lUsZA
+iHx3Z6ZboToBZvutxKo8IGL4wTQTG7RJr7pjHCATqGePKsOJVGzpQ3vfBBlvzPyR
+j7cBQgkxnnxdsutBCajtJew3iCHMqJ4LB3PSG99XTmo0cLsFS0ZFINlAVOhOvehr
+StVGRfgJfpWdqAphtXHKGvrrRzIba7999oQnnTMQoQYry993k3Zw6CAuezn2wMDz
+Vb3L22G5nsofuIVFSCOUDoxjHdyh/pCnR4p4VYp3JYm8M0HEe6D3J1xK6mHwSzPq
+38OmhxdhVzYl9Qd6SQENh5+1JYZy/or0q6oso01xTQ8HJaA/cIun8LiGxhL8mARt
+tjxbUkh3dkjEnLe3hBKjUdHHSCwALdlNxlgUX5nGtzD8z6MpZh3Up6xr34jBBBgR
+CgAJBQJSdopuAhsCAGoJEDWpO3ToLkIJXyAEGREKAAYFAlJ2im4ACgkQmBXlbbo5
+nOtRFAD+OVeTRtwanF55CjoJ+k21L/DmAZuAh48WWI5btdaN2hsA/0MRRYrEonfo
+QVSoeo8U06NecG38uVtyIpXP7gfcrFmxzoQA/0ub4YhdH0QDnb6MJxp4E4r8uqOZ
+sEtNRY4pmWTt5VF5AQChzjWNbzq4yjBRl7TDrNHoxaqRhtAvI3lajlBxnzgGbA==
+=g9Cz
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFiWn2QBEADXm20A5f/kQt3zImaTdtSVG3xnyaE9KhhfHfbS5XxoTzH63c04
+AU3OGKQFJCn9fND7BrWDu8g/+D4n16VCvaRX6VYQ4zmaQmQgQQzJPqZ07O67t6/O
+9DO/IJzDyjzkqWIq9u/IlhzzRmQokUQQ2hNVY355eBQHlZ4W5XTKS6r2eI6WaF+8
+/Bqs9vj5R83MmipkwOFvhc39BUeEMY2XVkootIcrQH5cNTKvNHe6QWVUOY4IdxwZ
+mHG0UXm0LbStxMVUln1524NcZi5s2DqQXg4t2Arwo/xv3+UBtbLOi25gyM31GgAR
+NUr4XlTsNQoJpmM53lRNjdyyOor8zF2QdJj9O7NYaO4WsDNEX26ahAzrNTxhPwem
+aqdOvtPMHQKVyKIWTxC0U97ht3FHjSBOJpqk0MXKuNWRI3XoBarjYBgXJGDWhYH7
+292vbo+khSApe2wct2P3h91cmWspsGfRGLPSy6h6o9VLiIbnwPoeiZbgha4C2ofL
+tUnEqkQBJZ27Dqy0wLHil1RuXftiG0OtrSQBuBWWfZHOWH25ozOGblJ5QPqmkd4M
+dWRoYcOVxKxRky0zv8erZnng7IiacXFqSFOcG1IILXpZcPcr/QlXqzl2/ruHgAFR
+Ls7TEMfAgfpEKzgxX9f6vQ3VrvlpuvttWDjZC27MOFjFZxftDseP1F1/zQARAQAB
+tCJEYW5pZWwgS2lwZXIgPGRraXBlckBuZXQtc3BhY2UucGw+iQI+BBMBAgAoAhsD
+BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCWpadowUJC2X/twAKCRCMgYnxmIwh
+ZvViEACC+HC0PMcyo6CPL6Hdc9hyNw+9xSEP8j4+tf7JDfPaRhqr1m8S0MyBtHCt
+y5Fu6/Dg/kpMBjkiR3F7rAnz83mjtsPYc/XWtxNfWRgRx3/gur7B1ZPrSF98TFOd
+7pDv1f2ZAd9fMhJvwkmJn1MqwOBgfHwAtc8eMuRSE+S5tDabj7+IUt4+1gCyXgKS
+lFSL9tcVHgqe0FwtjplCN+5rJTwuzQI+Lb7oREVVaAvlxaUIbw/aHMHaEQO1NjZL
+ESS/M0JSHt7zLl35W5Sod3EB2RHD2B8tWVYxUSOY+5CyEnP+CHoURFYxAMW0yAVA
+cA1U8lskhP59huzy49Hoo/VKWy0T1gcxKxRP6KaQlifGZMe9kSUbwNANS2t+fzPM
+FNhHZSzzOiuCNQRPxHwaErHCCpY7T2ydr1AL2wJOd3iHwAsted+cRdJu+EC0luKv
+zjS8HUJ9fZO7NK3R+shFGNs7y8rUkG6nPxJiQew14KrTpdZxKCBm0X4bkLQU+6ct
+1fZZvwea540NRuFBhqxVBVhT8rRd9+hh4q/a2Ls/ZOicHf+0z1vs3Dan7j/xdS7D
+5MKMfZ21+BNEcBBPYTQrYBhE6W96z8c/ZFprlQYZYKChbA2mxYYMhueAR54bymMx
+gnZ5s02ADAZ7oLv0uwITJHZhDzMInCiOFsJJpVfqTQltuJ0PPbkCDQRYlp9kARAA
+qUMDPgJb/oYbplLbEv2Q/mi8HdxDjunSNR4VhjreueavtHUwLxjuj5fdLQkFUoMi
+Y6D3GaT3EtnihQCI5124K8bfLhDu5xcKBGVT9jaKNy7wglsIp9wSHWGqZT3RHqFJ
+wHtADM5Ga1OK7QuD337bl2TDea+0mXD10SFweFEJDxSw4uVYzALiwMgXJfwzOF1Q
+hMuUGfGMQAIG6YP7t3ZQMHyatWMnDWwsOvZwUnWVYp2lKGX9ypWrHzwBnuwjtxPv
+ETWhm/LCyH3/I4j0S1s0ITfTSUz93WCbvdcUA3rcvXAWjnX3i9D3piPFlQetjjVe
+LY743hsT3WCx0CvqbhdWQLlUMRejC51tMoNoDtZ5Pdmu/boOu/L/5WgT6JOF211/
+hN5B+yiACOllHBgICMe7J9h5Kd22k8ByxMqJCQepISo7f0jdc9Z3qS2w1N7IKXK7
+0ZcJMdHqUB7BnLVFEqf+v8Deo2kS/LvXuTAxU5DcU8dq1bBQTi5e4pB/g48RZ3zs
+XoyFvA38pcppk/sEbKcic+57sPESyLrzmkrwYkiakCtiYm5KzJQp70ZQwHBjhccA
+y5mbe5xqUOWgOWR8u1xwU0JYFzyNUe4ZIo2GlN4F3jiB7VIPh2BPRUgVde81FCsq
++0p+rLSF6qtzhj/k7DQFQOvmG9zlWsfTWMUfmCwXeU0AEQEAAYkCJQQYAQIADwIb
+DAUCWpadwwUJC2X/0wAKCRCMgYnxmIwhZgsMEACGO/D4HdaX7CZb0/dmRAee49OB
+Pd8k9mb2pRi+XFC5l97OcA9bfNt2gKnhB/pHvEFIEqNCrwpTsrjxSFZ/yeGbX3vG
+erD9d8V5TiYFTTREuvbXeI6wrYFeMvzPX3hhEezTYEFDaIlLHEz54m+mtLKTXBt9
+BNyW8lgW9hr0dsaxBY/5746D2OBZNEbP3KZjHa8Qn9emuxG/SJDK/QR24wIt+Z4B
+/VZyB6CcvCgiwxx6vJhByJjEssuR1kLvRy5N+QCtpBnaTmKpvPdFhPCWR1Hhke9J
+uwtmjvCRjJUm08FA8VRU0ZIsKKcP7J6tPVHEtCyqIBUdjSv/FQ5X+3ifS9pPwhrX
+YDmH5PM9zro50AgbI7+Wz6l/RHW/c+fDCRREC6gjXEr1FzbfEJoP5UKCzEI/2bmR
+cr9Xo1r5G+rbL8BhInL45zQEqYKb46utjNH/YYwMP80Uw5SmmhHcyHH7ERP2leyp
+llcK42zImJ8+FeFeNyyhAJAJTXRjECZzXQ+rhKfz3viAqa+rGDgR6QMPsMKsVNPt
+zVESjOKlZGlwPWvC0cyDJSFVAK/mMdXR6M+OgDdQQ3qNiA+VVq2Rq/umm4GQrMkD
+I+bjRQyLsgrNAxm3bKkaRrKPffUy1MvjkiaBBKg/Yd1pjCX9EOYjLncrIRgSrR+L
+R7hydmm7XZTvr0s/NQ==
+=6ZLo
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..eb7fe58
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,9 @@
+version=3
+
+# Official releases:
+opts=pgpsigurlmangle=s/$/.sig/ \
+https://ftp.gnu.org/gnu/grub/grub-([a-z0-9.~]+).tar.xz debian uupdate
+
+# Betas and pre-releases:
+#opts=pgpsigurlmangle=s/$/.sig/ \
+#https://alpha.gnu.org/gnu/grub/grub-([a-z0-9.~]+).tar.xz debian uupdate